服务多,问题多
- 随着互联网分布式系统的普及和微服务的盛行,如何提高服务与服务之间的伸缩性和可扩展性?
- 如何在服务端做变更时候,尽可能的减小对依赖服务的影响?
- 如何在开发或者客户端不知道的时候悄悄的变更服务信息?
- 在Nginx实现的负载均衡背后,如何减少修改配置和重载Nginx服务?
- 如果使用Prometheus监控容器或者服务?你真的需要写一大堆的配置?如果1000个服务你要怎么监控?当一些服务被"优化"掉之后,你是否需要一个一个的从监控服务的配置文件中将其摘除?
- ...
在微服务化的趋势下,为了最大限度增加扩容缩容的灵活性,名字服务和服务发现等方式就越来越受到青睐了。目前,主流的服务发现组件有:consul、etcd、zookeeper,其中的区别这里就不展开说明了,可以在官网查看这些服务之间的区别。
consul是什么
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与注册中心。与其他分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、访问控制、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等)。使用起来也较 为简单。Consul使用Go
语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。
consul优势
- 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft。
- 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。
- 支持健康检查。 etcd 不提供此功能。
- 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。
- 官方提供 web 管理界面, etcd 无此功能。
consul服务架构和核心概念
图中的SERVER是consul服务端高可用集群,CLIENT是consul客户端。consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端。Server之间通过局域网或广域网通信实现数据一致性。每个Server或Client都是一个consul agent,或者说server和client只是agent所扮演的不同角色。
Consul利用两个不同的gossip pool。我们分别把他们称为局域网池(LAN Gossip Pool)或广域网池(WAN Gossip Pool)。每个Consul数据中心(Datacenter)都有一个包含所有成员(Server和Client)的LAN gossip pool。
LAN Pool有如下目的:
- 成员关系允许Client自动发现Server节点,减少所需的配置量
- 分布式故障检测允许的故障检测的工作在某几个Server几点执行,而不是集中整个集群所有节点上
- gossip允许可靠和快速的事件广播,比如Leader选举
WAN Pool是全局唯一的,无论属于哪一个数据中心,所有Server应该加入到WAN Pool。由WAN Pool提供会员信息让Server节点可以执行跨数据中心的请求。也就是说这个Pool不同于LAN Pool,它的目的是为了允许数据中心能够以low-touch的方式发现彼此。当数据中心的server收到来自不同数据中心的请求时,它可转发请求到数据中心的leader
在每个数据中心,client和server是混合的。一般建议有3-5台server。这是基于有故障情况下的可用性和性能之间的权衡结果,因为越多的机器加入达成共识越慢。然而,并不限制client的数量,它们可以很容易的扩展到数千或者数万台。
consul集群搭建
环境 | 服务器IP | 节点名称 | 角色 | DC |
---|---|---|---|---|
ubuntu16.04 | 192.168.99.128 | Node1 | Server | BJ |
ubuntu16.04 | 192.168.99.129 | Node2 | Server | BJ |
ubuntu16.04 | 192.168.99.130 | node3 | Server | BJ |
ubuntu16.04 | 192.168.99.131 | Node4 | Server | SH |
当前我们使用最新的版本用于测试调研:
wget https://releases.hashicorp.com/consul/1.7.2/consul_1.7.2_linux_amd64.zip
apt-get install unzip && unzip consul_1.7.2_linux_amd64.zip && mv consul /usr/local/bin/
for ip in 129 130 131
do
scp /usr/local/bin/consul [email protected].$i:/usr/local/bin/
done
在准备好consul的二进制包之后,我们先在每个机器上运行consul服务实例:
#node1
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.99.128 -bind=192.168.99.128 -client=0.0.0.0 -datacenter=BJ -ui
#node2
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.99.129 -bind=192.168.99.129 -client=0.0.0.0 -datacenter=BJ -ui
#node3
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.99.130 -bind=192.168.99.130 -client=0.0.0.0 -datacenter=BJ -ui
一般喜欢通过--help
查看选项的命令,这里就当做是凑字数吧!
- server: 以server身份启动。默认是client
- bootstrap-expect:集群要求的最少server数量,当低于这个数量,集群即失效。
- data-dir:data存放的目录,更多信息请参阅consul数据同步机制
- node:节点id,集群中的每个node必须有一个唯一的名称。默认情况下,Consul使用机器的hostname
- bind:监听的ip地址。默认绑定0.0.0.0,可以不指定。表示Consul监听的地址,而且它必须能够被集群中的其他节点访问。Consul默认会监听第一个private IP,但最好还是提供一个。生产设备上的服务器通常有好几个网卡,所以指定一个不会出错
- client: 客户端的ip地址,0.0.0.0是指谁都可以访问(不加这个,下面的ui :8500无法访问)
- ui: 可以访问UI界面
- -config-dir指定配置文件夹,Consul会加载其中的所有文件
- -datacenter 指定数据中心名称,默认是dc1
当我们启动consul服务实例完成之后,会发现有报错的日志,这是因为此时三台机器还没有join,不能算是一个集群,三台机器上的consul均不能正常工作,因为leader未选出
2020-04-13T08:55:43.821-0400 [INFO] agent.server.raft: entering follower state: follower="Node at 192.168.99.128:8300 [Follower]" leader=
2020-04-13T08:55:43.823-0400 [INFO] agent.server: Adding LAN server: server="192.168.99.128 (Addr: tcp/192.168.99.128:8300) (DC: bj)"
2020-04-13T08:55:43.823-0400 [INFO] agent.server: Handled event for server in area: event=member-join server=192.168.99.128.bj area=wan
2020-04-13T08:55:43.824-0400 [INFO] agent: Started DNS server: address=0.0.0.0:8600 network=tcp
2020-04-13T08:55:43.825-0400 [INFO] agent: Started HTTP server: address=[::]:8500 network=tcp
2020-04-13T08:55:43.825-0400 [INFO] agent: started state syncer
==> Consul agent running!
2020-04-13T08:55:50.370-0400 [WARN] agent.server.raft: no known peers, aborting election
2020-04-13T08:55:50.833-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
2020-04-13T08:56:07.711-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
2020-04-13T08:56:18.200-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
2020-04-13T08:56:37.477-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
2020-04-13T08:56:50.035-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
2020-04-13T08:57:13.322-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
2020-04-13T08:57:27.154-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
2020-04-13T08:57:38.397-0400 [ERROR] agent: Coordinate update error: error="No cluster leader"
2020-04-13T08:57:58.613-0400 [ERROR] agent.anti_entropy: failed to sync remote state: error="No cluster leader"
当一个consul agent启动后,它不知道任何其他节点,要学习到集群中的其他节点,agent必须加入一个已经存在的集群(cluster)。要加入这样的集群,它只需要知道这个集群中的一个节点即可。它加入后,将会和这个member gossip(交谈)并迅速发现集群中的其他节点。一个consul agent可以加入任何类型的其他agent,而不只是那些运行于server mode的agent。所以我们把192.168.99.129
和192.168.99.130
加入到192.168.99.128
中
# node2
consul join 192.168.99.128
# node3
consul join 192.168.99.128
# 此时就已经加入到集群中了
[email protected]:~# consul members
Node Address Status Type Build Protocol DC Segment
192.168.99.128 192.168.99.128:8301 alive server 1.7.2 2 bj
192.168.99.129 192.168.99.129:8301 alive server 1.7.2 2 bj
192.168.99.130 192.168.99.130:8301 alive server 1.7.2 2 bj
[email protected]:~# consul operator raft list-peers
Node ID Address State Voter RaftProtocol
192.168.99.128 9095c165-7f5f-6892-e9bc-722c3a08ebf0 192.168.99.128:8300 leader true 3
192.168.99.129 7234405d-cde5-e0ef-56b1-55e958de5b6c 192.168.99.129:8300 follower true 3
192.168.99.130 8bbc7729-e41c-e548-c9a8-9bf9c01fdb54 192.168.99.130:8300 follower true 3
consul支持多数据中心节点,在上文就提过,consul是通过WAN pool发现多数据中心节点的,因此我们加一个SH的consul节点:
#node4
consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node=192.168.99.131 -bind=192.168.99.131 -datacenter SH -ui
root@node4-99-131:~# consul join -wan 192.168.99.128
Successfully joined cluster by contacting 1 nodes.
root@node4-99-131:~# consul members -wan
Node Address Status Type Build Protocol DC Segment
192.168.99.128.bj 192.168.99.128:8302 alive server 1.7.2 2 bj
192.168.99.129.bj 192.168.99.129:8302 alive server 1.7.2 2 bj
192.168.99.130.bj 192.168.99.130:8302 alive server 1.7.2 2 bj
192.168.99.131.sh 192.168.99.131:8302 alive server 1.7.2 2 sh
这样就配置好了多数据中心节点集群。我们就可以在consul的web界面上看到集群信息了。