概述
Consul作为注册中心,提供服务发现、配置、健康检查、安全服务通信以及多数据中心等功能, 这些功能可以根据需要单独使用,也可以一起使用来构建完整的微服务系统。
Consul agent
Consul agent是Consul的核心进程。它是运行在Consul节点上,这些节点共同组成Consul集群。agent
进程用于维护成员信息、注册服务、成员健康检查等功能,agent
有如下两种模式运行:
- 客户端模式(client)通过Client模式启动节点加入Consul集群中,这种模式启动的节点数量没有限制,而且它们可以轻松扩展到数千或数万。在同一个数据中心组成的集群中,所有节点参与gossip协议。通过使用gossip协议检测节点故障, 比单纯的心跳方案具有更大的可扩展性。它还为节点提供故障检测;如果
agent
不可达,则节点可能出现故障。Client节点缓存server节点的数据,用以提高性能和可用性。 - 服务端模式(server)通过Server模式启动agent节点参与选举。在生产环境中3到5台服务器组成。这在故障情况下的可用性和性能之间取得了平衡,因为随着增加更多的服务器,一致性会逐渐变慢。集群中所有Server启动模式的agent节点参与Raft协议,共同选举出领导者。选举出领导者的节点负责查询数据以及数据同步到其它Server节点上
agent节点启动
-
从官网下载Consul压缩包。
-
解压启动。如下:
[root@unite-test consul]# consul agent -data-dir=/tmp/consul -node=server184.43 -datacenter=unite-dc -server=true ==> Starting Consul agent... Version: 'v1.7.2' Node ID: '74124b5b-aedc-59c3-5e6c-436443f2c025' Node name: 'server184.43' Datacenter: 'unite-dc' (Segment: '<all>') Server: true (Bootstrap: false) Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 172.27.185.43 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false ==> Log data will now stream in as it occurs: 2022-03-14T11:50:01.620+0800 [WARN] agent: Node name will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes.: node_name=server184.43 2022-03-14T11:50:01.625+0800 [INFO] agent.server.raft: initial configuration: index=0 servers=[] 2022-03-14T11:50:01.625+0800 [INFO] agent.server.serf.wan: serf: EventMemberJoin: server184.43.unite-dc 172.27.185.43 2022-03-14T11:50:01.626+0800 [INFO] agent.server.serf.lan: serf: EventMemberJoin: server184.43 172.27.185.43 2022-03-14T11:50:01.627+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=udp 2022-03-14T11:50:01.627+0800 [INFO] agent.server.raft: entering follower state: follower="Node at 172.27.185.43:8300 [Follower]" leader= 2022-03-14T11:50:01.628+0800 [INFO] agent.server.serf.wan: serf: Attempting re-join to previously known node: server29.6.dc1: 172.27.185.43:8302 2022-03-14T11:50:01.629+0800 [INFO] agent.server.serf.lan: serf: Attempting re-join to previously known node: server29.6: 172.27.185.43:8301 2022-03-14T11:50:01.629+0800 [INFO] agent.server: Adding LAN server: server="server184.43 (Addr: tcp/172.27.185.43:8300) (DC: unite-dc)" 2022-03-14T11:50:01.629+0800 [INFO] agent.server: Handled event for server in area: event=member-join server=server184.43.unite-dc area=wan 2022-03-14T11:50:01.630+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=tcp 2022-03-14T11:50:01.630+0800 [INFO] agent: Started HTTP server: address=127.0.0.1:8500 network=tcp 2022-03-14T11:50:01.631+0800 [INFO] agent: started state syncer ==> Consul agent running! ....
通过consul agent
命令启动成功后,通过日志输出有如下关键信息。如下:
- Node name是节点名字,在集群中唯一的。启动时通过
-node
配置自定义设置节点名字 - Datacenter是数据中心名字,通过
-datacenter
配置数据中心名字 - Server是Consul agent运行(server还是client)模式,通过
-server
配置。
agent节点状态
alive状态
该节点状态处于正常状态。 当agent节点首次启动时,通过如下配置自动完成加入集群中。一旦节点加入集群后,该节点的信息会传递给整个集群,集群中所有的节点成员都会知道彼此的存在。如果该节点是Server模式运行的,其它Server节点会进行日志复制。
retry_join = ["172.26.4.38","172.26.4.125"]
failed状态
当出现网路故障或者agent
进程关闭时,这些节点可能无法被其它节点访问,把这些节点标记为失败(failed)状态。 此时对failed状态的节点,Consul Server(领导者)节点会尝试重新连接该节点。可以看到leader节点日志输出如下:
# client29.118 has failed, no acks received
2021-11-24T16:10:06.279+0800 [INFO] agent.server.memberlist.lan: memberlist: Suspect client29.118 has failed, no acks received
2021-11-24T16:10:10.268+0800 [INFO] agent.server.serf.lan: serf: EventMemberFailed: client29.118 172.24.29.118
2021-11-24T16:10:10.269+0800 [INFO] agent.server: member failed, marking health critical: member=client29.118
2021-11-24T16:10:36.310+0800 [INFO] agent.server.serf.lan: serf: attempting reconnect to client29.118 172.24.29.118:8301
2021-11-24T16:12:06.314+0800 [INFO] agent.server.serf.lan: serf: attempting reconnect to client29.118 172.24.29.118:8301
从日志输出看出,当节点标记为故障状态,leader节点会默认每隔30s尝试重新进行连接。此时通过Consul命令查看节点状态,client29.118节点状态是failed状态。如下:
[root@unite-test consul]# consul members
Node Address Status Type Build Protocol DC Segment
server29.6 172.24.29.6:8301 alive server 1.7.2 2 test-leave-dc <all>
server29.9 172.24.29.9:8301 alive server 1.7.2 2 test-leave-dc <all>
service29.186 172.24.29.186:8301 alive server 1.7.2 2 test-leave-dc <all>
client29.118 172.24.29.118:8301 failed client 1.7.2 2 test-leave-dc <default>
注意
:当网络恢复或者agent被重新启动,节点状态更新为正常(alive)状态。
left状态
对于failed状态的节点,默认72小时,Consul会完全的把它从集群中移除掉,此时的节点标记为离开(left)状态,和失败状态(failed)不同。left状态节点上注册所有服务会被删除,如果节点是server模式启动,停止对它的日志复制。该值由如下参数设置。
reconnect_timeout = "1h" //可以用“s”、“m”、“h”表示秒、分钟或小时。该值必须为大于8小时。
注意
建议将其值设置为节点或者网路分区的最大预期恢复中断的两倍。时间设置过低可能会导致节点故障或者网络分区期间,从Consul集群中删除节点,导致集群恢复复杂。对于failed状态的节点,可以在其它节点发送HTTP请求,强制把它从failed状态变成left状态,对left状态的节点,leader节点不会尝试重新连接。
curl http://172.24.29.186:8500/v1/agent/force-leave/client29.118
leader节点日志变化如下:
2021-11-24T16:27:13.767+0800 [INFO] agent.server.serf.lan: serf: EventMemberLeave (forced): client29.118 172.24.29.118
2021-11-24T16:27:13.767+0800 [INFO] agent.server: deregistering member: member=client29.118 reason=left
对于left状态节点,serf
组件内有tombstone_timeout
参数控制left状态的节点被收割需要时间。收割理解为节点是left状态,从成员中移除掉。默认24小时后,left状态的节点从成员中移除掉。
注意
agent进程优雅的关闭,节点会从alive状态变为left状态。
Consul Architecture
下图表示是系统中多数据中心组成Consul集群架构图。每个数据中心都是局域网内Consul集群。如下图所示,有两个数据中心,分别是DATACENTER1
和DATACENTER2
。不同的数据中心之间不会进行数据同步,但是可以通过RPC请求其它数据中心数据。 在DATACENTER1
的数据中心,存在两种启动模式agent节点,分别是Server和Client。
从上图看出Consul需要多个不同的端口才能正常工作,其中一些端口使用TCP、UDP或者两种协议。主要端口详情如下:
- Server RPC(TCP)端口是8300。用于其它Client节点请求Server节点以及Server节点之间交互请求端口。
- HTTP(TCP)端口8500。用于客户端通过HTTP API通信端口。
- LAN Serf( TCP and UDP )端口8301。用于集群所有节点之间Gossip协议通信端口 。
- DNS( TCP and UDP )端口8600。用于解析DNS查询信息。
Raft协议在Consul应用
所有Consul Server节点参与Raft协议,共同组成Peer Set
。Peer set
理解为参与日志复制所有成员的集合。所有Consul Client节点把请求转发给Consul Server节点。这种设计主要原因是,随着更多Consul节点成员的加入到Peer Set
中。 quorum
的大小也会增加。quorum
理解为多数派。对于N个Consul Server节点成员,quorum
要求至少有(N/2)+1成员。例如,peer set有5个Server节点,就须要至少3个节点才能造成quorum。
注意
: Raft协议理解共识(Consensus)协议。
启动选举
当Consul通过Server模式启动agent进程时,这种模式允许它们选举出领导者。通过查看Consul启动日志看出选举过程,如下通过三个Server节点组成Peer set
参与选举。
-
引导模式启动,通过配置
bootstrap_expect = 3
期望``Peer set`大小为3。[INFO] bootstrap_expect > 0: expecting 3 servers
-
在Raft协议初始化状态下,Server节点启动默认是跟随者(follower)状态。
[INFO] agent.server.raft: initial configuration: index=0 servers=[] [INFO] agent.server.raft: entering follower state: follower="Node at 172.24.29.6:8300 [Follower]" leader=
-
从 Consul启动完成后,使用配置
retry_join = ["172.26.4.38","172.26.4.125"]
属性,通过self
组件发现参与选举的节点数。当达到期望节点数后 最先超时的跟随者节点会增加自己的任期编号,并推举自己为候选人(candidate),给自己投票,然后向其它节点发送请求投票 RPC 消息,请它们选举自己为领导者。[INFO] Consul agent running! Consul Agent [INFO] agent.server.raft: no known peers, aborting election #没有发现peer set,停止选举 #发现预期Peer set数目,尝试引导 [INFO] agent.server: Found expected number of peers, attempting bootstrap #最先超时的节点 增加自己的任期(term)编号,推举自己为候选人,给自己投票 [INFO] agent.server.raft: heartbeat timeout reached, starting election: last-leader= [INFO] agent.server.raft: entering candidate state: node="Node at 172.24.29.6:8300 [Candidate]" term=2
-
获取票数最多的节点,它就会成为本届任期内新的领导者。如果节点当选领导者后,它将周期性地发送心跳消息,通知其它跟随者节点不再发起选举。
[INFO] agent.server.raft: election won: tally=2 [INFO] agent.server.raft: entering leader state: leader="Node at 172.24.29.6:8300 [Leader]"
-
开始日志复制
#已经添加Peer set中,开始日志复制,peer指向其它节点id [INFO] agent.server.raft: added peer, starting replication: peer=e6a8a239-1c5a-3a17-20ab-176fc8c5056e [INFO] agent.server.raft: added peer, starting replication: peer=b4b9fee5-54d9-0455-2cf0-dc647a3af745l
当一个RPC请求到达非Leader Server节点,请求就会被转发到Leader节点。请求分为两种类型:
- 查询(query)类型,这意味着它是只读的,Leader会基于FSM状态机生成相应的结果;
- 操作(transaction)类型,即修改状态,Leader节点产生一个新的日志条目,并基于Raft算法进行管理。一旦日志条目应用于
FSM
,FSM
可以理解为有限状态机,有限个状态以及在这些状态之间的转移和动做等行为的数学模型。新日志的应用,FSM会发生状态转换,相同的日志序列的应用必须致使相同的状态。
每一个数据中心选择独立的Leader和维护Peer set
。数据按照数据中心进行划分,因此每一个Leader只负责在相应数据中心的数据。
一致性(Consistency)模式
虽然全部日志副本的写入都是基于Raft,读取更灵活。但为了支持开发人员可能须要的各类权衡,Consul支持3种不一样的一致性模式。
三种读模式是:
- default:客户端访问领导者节点执行读操作,领导者确认自己处于稳定状态时(在 leader leasing 时间内),返回本地数据给客户端,否则返回错误给客户端。在这种情况下,客户端是可能读到旧数据的,比如此时发生了网络分区错误,新领导者已经更新过数据,但因为网络故障,旧领导者未更新数据也未退位,仍处于稳定状态。
- consistent:客户端访问领导者节点执行读操作,领导者在和大多数节点确认自己仍是领导者之后返回本地数据给客户端,否则返回错误给客户端。在这种情况下,客户端读到的都是最新数据。
- stale:从任意节点读数据,不局限于领导者节点,客户端可能会读到旧数据
Gossip协议在Consul应用
Consul使用Gossip协议管理成员并向集群广播消息,Gossip协议是通过使用Serf
库提供的。Serf
是一个用于集群节点成员(membership)发现、故障检测(failure detection)和编排的工具组件。它是分散的、容错的和高可用性的。非常轻量级运行在内存中脚本中,使用UDP消息进行通信,它使用gossip协议。Consu屏蔽Serf
的抽象提供这些特性。Consul使用两个不同的Gossip Pool
,如下:
- LAN Gossip Pool
- WAN Gossip Pool
在Consul中,每个数据中心都有一个LAN Gossip Pool
,这里面包含这个数据中心的所有成员节点。主要作用如下:
- 成员信息允许客户端自动发现服务器,减少所需的配置。
- 分布式故障检测工作由整个集群节点共同分担,而不是集中在Consul Server节点上。
Gossip Pool
具有可靠和快速的事件广播。
在多数据中心组成服务中,WAN Gossip Pool
是唯一的。不同数据中心下的所有节点都参与 WAN Pool
, 该池允许服务器执行跨数据中心请求。