在 Spring Cloud 体系中,几乎每个角色都会有两个以上的产品提供选择,比如在注册中心有:Eureka、Consul、zookeeper、etcd 等;网关的产品有 Zuul、Spring Cloud Gateway 等。在注册中心产品中,最常使用的是 Eureka 和 Consul,两者各有特点,企业可以根据自述项目情况来选择。

Spring Cloud Consul 项目是针对 Consul 的服务治理实现。Consul 是一个分布式高可用的系统,它包含多个组件,但是作为一个整体,在微服务架构中,为我们的基础设施提供服务发现和服务配置的工具。

什么是Consul?

Consul 是 HashiCorp 公司推出的开源产品,用于实现分布式系统的服务发现、服务隔离、服务配置,这些功能中的每一个都可以根据需要单独使用,也可以同时使用所有功能。Consul 官网目前主要推 Consul 在服务网格中的使用。
与其它分布式服务注册与发现的方案相比,Consul 的方案更“一站式”——内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具。Consul 本身使用 go 语言开发,具有跨平台、运行高效等特点,也非常方便和 Docker 配合使用。

Consul 的主要特点有:

Service Discovery : 服务注册与发现,Consul 的客户端可以做为一个服务注册到 Consul,也可以通过 Consul 来查找特定的服务提供者,并且根据提供的信息进行调用。
Health Checking: Consul 客户端会定期发送一些健康检查数据和服务端进行通讯,判断客户端的状态、内存使用情况是否正常,用来监控整个集群的状态,防止服务转发到故障的服务上面。
KV Store: Consul 还提供了一个容易使用的键值存储。这可以用来保持动态配置,协助服务协调、建立 Leader 选举,以及开发者想构造的其它一些事务。
Secure Service Communication: Consul 可以为服务生成分布式的 TLS 证书,以建立相互的 TLS 连接。 可以使用 intentions 定义允许哪些服务进行通信。 可以使用 intentions 轻松管理服务隔离,而不是使用复杂的网络拓扑和静态防火墙规则。
Multi Datacenter: Consul 支持开箱即用的多数据中心,这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

Consul 角色:

Server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其它数据中心通讯。 每个数据中心的 Server 数量推荐为 3 个或是 5 个。
Client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。

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 的 Web 管理界面有一些菜单,我们这里做一下简单的介绍:

Services,管理界面的默认页面,用来展示注册到 Consul 的服务,启动后默认会有一个 consul 服务,也就是它本身。
Nodes,在 Services 界面双击服务名就会来到 Services 对应的 Nodes 界面,Services 是按照服务的抽象来展示的,Nodes 展示的是此服务的具体节点信息。比如启动了两个订单服务实例,Services 界面会出现一个订单服务,Nodes 界面会展示两个订单服务的节点。
Key/Value ,如果有用到 Key/Value 存储,可以在界面进行配置、查询。
ACL,全称 Access Control List,为访问控制列表的展示信息。
Intentions,可以在页面配置请求权限。

键值对操作

创建键值对

1
consul kv put {key} {value}

递归创建键值对

1
consul kv put {key1}/{key2} {value1} {value2}

查看创建所有的键值对

1
consul kv get -keys

查看指定键值对对应的值

1
consul kv get {key}

查看指定的键值对的详细信息

1
consul kv get -detailed {key}

删除指定的键值对

1
consul kv delete {key}

递归删除键值对

1
consul kv delete -recurse {key}

导出键值对,并以json格式输出

1
consul kv export {key}

查看consul集群信息

查看集群中角色为server的节点信息

1
curl 1.1.1.6:8500/v1/status/peers

集群中任意一个IP

查看群集中的主机点

1
curl 1.1.1.6:8500/v1/status/leader

查看集群中的详细信息,并美化输出

1
curl 1.1.1.6:8500/v1/catalog/nodes?pretty

?pretty:指的是美化输出格式

服务器信息

IP 服务
1.1.1.3 maven+spring-cloud+consul
1.1.1.4 maven+spring-cloud+consul
1.1.1.5 maven+spring-cloud+consul
1.1.1.6 client+ui

部署consul

节点一server端

1
2
3
unzip consul_1.4.0_linux_amd64.zip -d /usr/bin/
mkdir -p /consul/{data,config}
consul agent -server -bootstrap-expect 2 -data-dir /consul/data -config-dir /consul/config -bind 1.1.1.3 -client 0.0.0.0 -enable-script-checks=true -node=consulA -datacenter=test

bind:本机IP

节点二server端

1
2
3
unzip consul_1.4.0_linux_amd64.zip -d /usr/bin/
mkdir -p /consul/{data,config}
consul agent -server -data-dir /consul/data -config-dir /consul/config -bind 1.1.1.4 -client 0.0.0.0 -enable-script-checks=true -node=consu1B -datacenter=test -join=1.1.1.3

join:加入到节点一集群

节点三server端

1
2
3
unzip consul_1.4.0_linux_amd64.zip -d /usr/bin/
mkdir -p /consul/{data,config}
consul agent -server -data-dir /consul/data -config-dir /consul/config -bind 1.1.1.5 -client 0.0.0.0 -enable-script-checks=true -node=consu1B -datacenter=test -join=1.1.1.3

节点四client端

1
2
3
unzip consul_1.4.0_linux_amd64.zip -d /usr/bin/
mkdir -p /consul/{data,config}
consul agent -ui -data-dir /consul/data -config-dir /consul/config -bind 1.1.1.6 -client 0.0.0.0 -node=consulD -datacenter=test -enable-script-checks=true -join=1.1.1.3

查看consul集群成员

1
2
3
4
5
6
consul members
Node Address Status Type Build Protocol DC Segment
consul1 1.1.1.3:8301 alive server 1.4.0 2 pjf01 <all>
consul2 1.1.1.4:8301 alive server 1.4.0 2 pjf01 <all>
consul3 1.1.1.5:8301 alive server 1.4.0 2 pjf01 <all>
client 1.1.1.6:8301 alive client 1.4.0 2 pjf01 <default>

放行所有防火墙

1
2
3
firewall-cmd --add-port=8301
firewall-cmd --add-port=8500
setenforce 0

访问ui端页面1.1.1.6:9500

upload successful

节点一部署生产者

1
2
3
4
5
6
cd /usr/local/spring-cloud-examples/spring-cloud-consul/spring-cloud-consul-producer
vi src/main/resources/application.properties
修改:UI端IP
spring.cloud.consul.host=1.1.1.6

mvn spring-boot:run

节点二部署生产者

1
2
3
4
5
6
cd /usr/local/spring-cloud-examples/spring-cloud-consul/spring-cloud-consul-producer-2/
vi src/main/resources/application.properties
修改:UI端IP
spring.cloud.consul.host=1.1.1.6

mvn spring-boot:run

节点三部署消费者

1
2
3
4
5
6
cd /usr/local/spring-cloud-examples/spring-cloud-consul/spring-cloud-consul-consumer/
vi src/main/resources/application.properties
修改:UI端IP
spring.cloud.consul.host=1.1.1.6

mvn spring-boot:run

验证

访问消费者,实现生产者1和2的轮询效果

1
2
3
4
curl 1.1.1.6:8503/call
helle consul
curl 1.1.1.6:8503/call
helle consul two

将生产者1断开之后,再次访问消费者的话不会再将请求交给生产者1,会直接显示生产者2 的消息,如果生产者1恢复之后,消费者会继续实现轮询效果