简述
Consul 是 HashiCorp 公司推出的开源产品,用于实现分布式系统的服务发现、服务隔离、服务配置,这些功能中的每一个都可以根据需要单独使用,也可以同时使用所有功能。Consul 官网目前主要推 Consul 在服务网格中的使用。
与其它分布式服务注册与发现的方案相比,Consul 的方案更“一站式”——内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具。Consul 本身使用 go 语言开发,具有跨平台、运行高效等特点,也非常方便和 Docker 配合使用。
Consul 调用过程
安装 Consul
Consul 不同于 Eureka 是由 go 语言开发而成,因此需要我们单独来安装
官网 https://www.consul.io/downloads.html
consul agent -dev # -dev表示开发模式运行,另外还有-server表示服务模式运行
浏览器输入 http://localhost:8500
Consul 核心概念
Consul 基础架构
Consul 集群
从上图可以看出,有两个数据中心,分别标记为 DATACENTER 1 和 DATACENTER 2 ,两个数据中心通过 WAN GOSSIP 在 Internet 上交互报文,由此可知 Consul 是支持多数据中心的。
每个数据中心都有两个角色 Server 和 Client,它们之间通过 GRPC 通信。Server 端参与 Raft 仲裁,维护集群的状态,响应 RPC 查询,Client 负责转发 RPC 到 Server 。
Server 和 Client 之间,还有一条 LAN GOSSIP 通信,当 LAN 内部发生了拓扑变化时,存活的节点能够及时感知,比如 Server 节点 Down 掉后,Client 就会触发将对应 Server 节点从可用列表中剥离出去。
官方建议每个 Consul Cluster 有 3 到 5 台 Server,兼顾故障处理和性能的平衡。如果增加越多的机器,则 Consensus 会越来越慢。对 Client 没有限制,可以很容易地扩展到成千上万或数万。
快速入手
接下来我们使用一个简单的示例,来了解 Consul 的服务注册和调用。首先我们构建一个 Consul 的服务提供者,只提供一个简单的 hello 调用方法。
<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>
</dependencies>
#项目名称
spring.application.name=consul provider01
#项目端口
server.port=8501
#consul的地址也端口
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
#注册consul的服务名称
spring.cloud.consul.discovery.service-name=service-provider01
spring.cloud.consul.discovery.serviceName
是指注册到 Consul 的服务名称,客户端可根据这个名称进行服务调用。
@SpringBootApplication
@EnableDiscoveryClient
public class Consulprovider01 {
public static void main(String[] args) {
}
}
- Controller
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello consul";
}
}
为了模拟多服务提供调用,复制上述项目重命名为 consul-provider02 ,修改对应的端口为 8502,修改 hello 方法的返回值为:”hello consul two”,修改完成后依次启动两个项目。
建立消费者
consul-consumer01
<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>
</dependencies>
@RestController
public class CallHelloController {
@Autowired
private LoadBalancerClient loadBalancer;
@RequestMapping("/call")
public String call() {
ServiceInstance serviceInstance = loadBalancer.choose("service-provider");
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;
}
}
@SpringBootApplication
public class Consulconsumer01 {
public static void main(String[] args) {
SpringApplication.run(Consulconsumer01.class,args);
}
}
启动后,页面访问
http://localhost:8601/call
服务地址:http://WQ-20180918NHDW:8503
服务名称:service-provider
hello consul two
服务地址:http://WQ-20180918NHDW:8501
服务名称:service-provider
hello consul one
服务地址:http://WQ-20180918NHDW:8503
服务名称:service-provider
hello consul two
服务地址:http://WQ-20180918NHDW:8501
服务名称:service-provider
hello consul one
服务地址:http://WQ-20180918NHDW:8503
服务名称:service-provider
hello consul two
服务地址:http://WQ-20180918NHDW:8501
服务名称:service-provider
hello consul one
服务地址:http://WQ-20180918NHDW:8503
服务名称:service-provider
hello consul two
服务地址:http://WQ-20180918NHDW:8501
服务名称:service-provider
hello consul one
服务地址:http://WQ-20180918NHDW:8503
服务名称:service-provider
hello consul two
服务地址:http://WQ-20180918NHDW:8501
服务名称:service-provider
hello consul one
服务地址:http://WQ-20180918NHDW:8503
服务名称:service-provider
hello consul two
服务地址:http://WQ-20180918NHDW:8501
服务名称:service-provider
hello consul one
可以看出服务调用者已经成功获得了服务提供者的响应信息,并且两个服务提供者交替返回信息,服务调用自动实现了均衡负载的功能。