Swoft与Consul(一) - 高可用集群架构
Consul介绍
Consul 是一个分布式的解决方案,可以部署多个 Consul 实例,确保数据中心的持续稳定,
在 Consul 集群中,内部采用投票的方式选举出 leader,只有选举出 leader 后,集群才开始工作;
当一个服务注册到 Consul 后,集群将该服务进行同步,确保 Consul 集群内的每个节点都存储了该服务的信息;
然后,Consul 集群将对该服务进行健康检查和投票,超过半数通过,即认为该服务为正常(或者异常);
一旦被投票认定为异常的服务,该服务将不会被外部发现(不可访问),在此过程中,Consul 将持续的对该异常的服务进行检查,一旦服务恢复,Consul 即刻将其加入正常服务。
Consul 支持两种运行的方式,即 server 和 client 模式,
当一个 Consul 节点以 server 模式运行的时候,就表示该 Consul 节点会存储服务和配置等相关信息,并且参与到健康检查、leader 选举等服务器事务中,与之相反的是,client 模式不会存储服务信息。
每个Consul节点都需要加入一个命名的数据中心(DataCenter) ,一个节点上,可以运行多个数据中心,数据中心的作用在于应用隔离,相当于服务分组。可以简单理解为,一个数据中心为一个二层联通的子网。
Consul工作原理
首先 Consul 支持多数据中心,在上图中有两个 DataCenter,他们通过 Internet 互联,同时请注意为了提高通信效率,只有 Server 节点才加入跨数据中心的通信。
在单个数据中心中,Consul 分为 Client 和 Server 两种节点(所有的节点也被称为 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 端口完成。
构建Consul集群服务
Consul集群构建官方建议是采用奇数个数(3,5,7...)
本例启动 5 个 Consul Agent,3 个 Server(会选举出一个 Leader),2 个 Client。
# 创建consul容器集群1master 2slaves 2client
version: "3.6" # 确定docker-composer文件的版本
services: # 代表就是一组服务 - 简单来说一组容器
# server
consul_master_server_170_30: # 这个表示服务的名称,可自定义; 注意不是容器名称
image: consul1.4 # 指定容器的镜像文件
ports: # 配置容器与宿主机的端口
- "8500:8500"
networks: ## 引入外部预先定义的网段
consul:
ipv4_address: 170.200.7.30 #设置ip地址
container_name: consul_master_server_170_30 # 这是容器的名称
command: ./consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node=consul_master_server_170_30 -bind=170.200.7.30 -ui -client=0.0.0.0
consul_slaves_server_170_20: # 这个表示服务的名称,可自定义; 注意不是容器名称
image: consul1.4 # 指定容器的镜像文件
ports: # 配置容器与宿主机的端口
- "8520:8500"
networks: ## 引入外部预先定义的网段
consul:
ipv4_address: 170.200.7.20 #设置ip地址
container_name: consul_slaves_server_170_20 # 这是容器的名称
command: ./consul agent -server -data-dir /tmp/consul -node=consul_slaves_server_170_20 -bind=170.200.7.20 -ui -client=0.0.0.0 -join 170.200.7.30
consul_slaves_server_170_10: # 这个表示服务的名称,可自定义; 注意不是容器名称
image: consul1.4 # 指定容器的镜像文件
ports: # 配置容器与宿主机的端口
- "8510:8500"
networks: ## 引入外部预先定义的网段
consul:
ipv4_address: 170.200.7.10 #设置ip地址
container_name: consul_slaves_server_170_10 # 这是容器的名称
command: ./consul agent -server -data-dir /tmp/consul -node=consul_slaves_server_170_10 -bind=170.200.7.10 -ui -client=0.0.0.0 -join 170.200.7.30
# client
consul_client_170_50: # 这个表示服务的名称,可自定义; 注意不是容器名称
image: consul1.4 # 指定容器的镜像文件
ports: # 配置容器与宿主机的端口
- "8550:8500"
networks: ## 引入外部预先定义的网段
consul:
ipv4_address: 170.200.7.50 #设置ip地址
container_name: consul_client_170_50 # 这是容器的名称
command: ./consul agent -data-dir /tmp/consul -node=consul_client_170_50 -bind=170.200.7.50 -ui -client=0.0.0.0 -join 170.200.7.30
consul_client_170_40: # 这个表示服务的名称,可自定义; 注意不是容器名称
image: consul1.4 # 指定容器的镜像文件
ports: # 配置容器与宿主机的端口
- "8540:8500"
networks: ## 引入外部预先定义的网段
consul:
ipv4_address: 170.200.7.40 #设置ip地址
container_name: consul_client_170_40 # 这是容器的名称
command: ./consul agent -data-dir /tmp/consul -node=consul_client_170_40 -bind=170.200.7.40 -ui -client=0.0.0.0 -join 170.200.7.30
# 设置网络模块
networks:
# 自定义网络
consul:
driver: bridge
ipam: #定义网段
config:
- subnet: "170.200.7.0/24"
以上可以看到执行了5次command命令配置consul启动,consul容器的启动可能不是按顺序启动,而是随机启动的,
这时可以多次执行docker-compose up -d直到所有容器都启动成功。
查看consul集群
http://192.168.3.98:8550/ui/dc1/nodes
进入master_server容器
docker exec -it consul_master_server_170_30 sh
查看所有server服务
./consul operator raft list-peers