SpringCloud之Consul

简介

Consul是一个GO语言编写的分布式服务注册与发现,用于跨任何运行时平台和公共或私有云连接、保护和配置服务。它内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案。

官方文档:https://www.consul.io/docs/guides/index.html

原理

它使用 Raft 算法(https://www.jdon.com/artichect/raft.html)来保证一致性, 比复杂的 Paxos 算法更直接.

相比较而言, zookeeper 采用的是 Paxos.

client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。

server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其它数据中心通讯。

每个数据中心的 server 数量推荐为 3 个或是 5 个(一般是奇数,方便选举算法)。

Consul 客户端、服务端还支持夸中心的使用,更加提高了它的高可用性。

工作原理

  • 1.当 Producer 启动的时候,会向 Consul 发送一个 post 请求,告诉 Consul 自己的 IP 和 Port
  • 2.Consul 接收到 Producer 的注册后,每隔10s(默认)会向 Producer 发送一个健康检查的请求,检验Producer是否健康
  • 3.当 Consumer 发送 GET 方式请求 /api/address 到 Producer 时,会先从 Consul 中拿到一个存储服务 IP 和 Port 的临时表,从表中拿到 Producer 的 IP 和 Port 后再发送 GET 方式请求 /api/address
  • 4.该临时表每隔10s会更新,只包含有通过了健康检查的 Producer

使用

安装

Consul 不同于 Eureka 需要单独安装,访问Consul 官网

下载 Consul 的最新版本,我这里是 consul_1.4.4。

#cmd启动:
consul agent -dev      
服务生产者producer

1.pom.xml,添加相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.xbmchina</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.xbmchina</groupId>
    <artifactId>cloud-consul-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-consul-producer</name>
    <description>consul-producer</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

启动类中需要设置@EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class CloudConsulProducerApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudConsulProducerApplication.class, args);
    }

    @RequestMapping("/hello")
    public String hello() {
        return "helle consul";
    }
}

application.yml配置相关端口和服务名称

spring:
  application:
    name: spring-cloud-consul-producer2
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
         ##注册到consul的服务名称
        service-name: service-producer  
server:
  port: 8505
服务消费者consumer

同理也需要添加相应的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.xbmchina</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.xbmchina</groupId>
    <artifactId>cloud-consul-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-consul-consumer</name>
    <description>consul消费者</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

调用生产者Producer中的服务

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class CallHelloController {

    @Autowired
    private LoadBalancerClient loadBalancer;//用于负载均衡

    @RequestMapping("/call")
    public String call() {
        ServiceInstance serviceInstance = loadBalancer.choose("service-producer");
        System.out.println("服务地址:" + serviceInstance.getUri());
        System.out.println("服务名称:" + serviceInstance.getServiceId());

        String callServiceResult = new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/hello", String.class);
        System.out.println(callServiceResult);
        return callServiceResult;
    }

}

application.yml配置连接注册到consul

spring:
  application:
    name: cloud-consul-consumer
  cloud:
    consul:
      host: 127.0.0.1
      port: 8500
      discovery:
      ##设置不需要注册到 consul 中
        register: false
server:
  port: 8503

效果: 访问地址http://localhost:8503/call.

如果报错的话,你可以看一下日志,是否是你本机名没在hosts中配置,导致的。

总结

Consul 真厉害!!

原文发布于微信公众号 - 爱编码(ilovecode)

原文发表时间:2019-04-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券