参考:
http://blog.didispace.com/consul-service-discovery-exp/
https://www.fangzhipeng.com/springcloud/2019/02/14/sc-consul-g.html
1 Consul是什么
Consul
是基于GO
语言开发的开源工具,主要面向分布式系统提供服务注册/发现和配置管理的功能等。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格。Consul
不仅具有服务治理的功能,而且使用分布式一致协议RAFT
算法实现,有多数据中心的高可用方案,并且很容易和Spring Cloud
等微服务框架集成,使用起来非常的简单,具有简单、易用、可插排等特点。使用简而言之,Consul
提供了一种完整的服务网格解决方案 。
Consul
的功能都很实用,其中包括:
- 服务注册/发现:可以通过
consul
的客户端向consul
的服务端注册应用服务信息,其他应用服务可以通过consul
的客户端来发现服务的提供者。consul
提供了DNS
和HTTP API
来注册/发现服务。 - 运行时健康检查:
consul
客户端可以提供任意数量的运行状况检查机制,这些检查机制可以是给定服务或本地节点相关联。这些信息可以用来监控群集的运行状况,服务发现组件可以使用这些监控信息来路由流量,可以使流量远离不健康的服务。 - Key/Value存储:应用程序可以将
consulc的键/值存储用于任何需求,包括动态配置,功能标记,协调,领导者选举等。它采用
HTTP API`使其易于使用。 - 安全服务通信:
consul
可以为服务生成和分发TLS
证书,以建立相互的TLS
连接。 - 多数据中心:
consul
支持多个数据中心。这意味着consul
的用户不必担心构建额外的抽象层以扩展到多个区域。 - 分布式一致性保证:
consul
使用分布式一致协议RAFT
算法来保证多个节点数据的一致性。
Consul
本身只是一个二进制的可执行文件,所以安装和部署都非常简单,只需要从官网下载后,在执行对应的启动脚本即可。
2 Consul工作原理
引用官网的一张图:
工作原理:
- 每个
Consul
实例都通过agent
启动。agent
是一个守护进程,可以指定client
或server
模式,支持DNS
或HTTP API
接口,并负责运行时检查和保持服务同步。 Consul
支持多数据中心。在上图中有两个DataCenter
,他们通过网络互连,同时请注意为了提高通信效率,只有Server
节点才加入跨数据中心的通信。- 在单个数据中心中,
Consul
分为Server
和Client
两种节点(所有的节点也被称为Agent
)。Server
节点保存注册的服务信息数据,Client
节点存在于应用服务中,负责服务注册、健康检查、转发数据请求到Server
;Server
节点有一个Leader
和多个Follower
,Leader
节点会将数据同步到Follower
,Server
的数量推荐是3
个或者5
个,在Leader
挂掉的时候会启动选举机制产生一个新的Leader
。 Consul
集群内的节点通过gossip
协议(流言协议)维护成员关系。也就是说某个节点了解集群内现在还有哪些节点,这些节点是Client
还是Server
。单个数据中心的流言协议同时使用TCP
和UDP
通信,并且都使用8301
端口。跨数据中心的流言协议也同时使用TCP
和UDP
通信,端口使用8302
。- 集群内数据的读写请求既可以直接发到
Server
,也可以通过Client
使用RPC
转发到Server
,请求最终会到达Leader
节点。在允许数据轻微陈旧的情况下,读请求也可以在普通的Server
节点完成,集群内数据的读写和复制都是通过TCP
的8300
端口完成。
3 Consul服务注册/发现的原理
Consul
可用于分布式系统中的服务注册/发现。
图片来源:http://blog.didispace.com/consul-service-discovery-exp/
服务注册/发现原理:
- 首先在
Server1
、Server2
、Server3
三个服务器上面分别部署了一个Consul Server
,组成一个Consul
集群。这个集群中有leader
,也有follower
,假设他们选举了Server2
上的Consul Server
节点为leader
。这些服务器上最好只部署Consul
程序,以尽量维护Consul Server
的稳定。 - 然后在服务器
Server4
和Server5
上通过Consul Client
分别注册Service A
、Service B
、Service C
,这里每个Service
分别部署在了两个服务器上,这样可以避免Service
的单点问题。服务注册到Consul
可以通过HTTP API(8500端口)
的方式,也可以通过Consul配置文件
的方式。Consul Client
可以认为是无状态的,它将注册信息通过RPC
转发到Consul Server
,注册过的服务信息真实的保存在Consul Server
的各个节点中,并且通过Raft算法
实现了强一致性。 - 最后在服务器
Server6
中有一个Service D
服务,需要访问Service B
。这时候Service D
首先会访问本机Consul Client
提供的HTTP API
,本机的Consul Client
会将请求转发到Consul Server
(由集群中的leader
来处理请求),Consul Server
查询到Service B
当前的服务信息并返回,最终Service D
拿到了Service B
的所有部署的IP
和端口,然后就可以从中选择Service B
的其中一个部署实例并向其发起请求了。 - 如果服务发现采用的是
DNS
方式,则Service D
中直接使用Service B
的服务发现域名,域名解析请求首先到达本机DNS
代理,然后转发到本机Consul Client
,本机Consul Client
会将请求转发到Consul Server
,Consul Serve
r查询到Service B
当前的信息返回,最终Service D
拿到了Service B
的某个部署的IP
和端口。