CAP理论
CAP理论是分布式架构中重要理论
- 一致性(Consistency) (所有节点在同一时间具有相同的数据)
- 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
主流注册中心产品
Nacos | Eureka | Consul | CoreDNS | Zookeeper | |
---|---|---|---|---|---|
一致性协议 | CP+AP | AP | CP | — | CP |
健康检查 | TCP/HTTP/MYSQL/Client Beat | Client Beat | TCP/HTTP/gRPC/Cmd | — | Keep Alive |
负载均衡策略 | 权重/ metadata/Selector | Ribbon | Fabio | RoundRobin | — |
雪崩保护 | 有 | 有 | 无 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 不支持 | 支持 |
访问协议 | HTTP/DNS | HTTP | HTTP/DNS | DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 不支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
跨注册中心同步 | 支持 | 不支持 | 支持 | 不支持 | 不支持 |
SpringCloud集成 | 支持 | 支持 | 支持 | 不支持 | 支持 |
Dubbo集成 | 支持 | 不支持 | 不支持 | 不支持 | 支持 |
K8S集成 | 支持 | 不支持 | 支持 | 支持 | 不支持 |
测试目标
- 内部服务注册和健康检查
- 外部服务注册和健康检查
测试环境
节点名称 | 节点IP | 运行服务 | 服务版本 |
---|---|---|---|
consul_server1 | 192.168.48.132 | consul、consul-esm | Consul v1.8.3、consul-esm v0.4.0 |
consul_server2 | 192.168.48.133 | consul、consul-esm | Consul v1.8.3、consul-esm v0.4.0 |
consul_server3 | 192.168.48.134 | consul、consul-esm | Consul v1.8.3、consul-esm v0.4.0 |
consul_client1 | 192.168.48.135 | consul_client | Consul v1.8.3 |
consul_client2 | 192.168.48.131 | consul_client | Consul v1.8.3 |
Consul 集群配置
consul server
1 | $ cat consul_server.json |
consul-esm
无需配置,在server服务器上启动服务即可
consul client
1 | cat consul_client.json |
测试过程
内部服务注册
在Consul的上下文中,内部服务是由Consul代理可以直接运行的节点(机器)提供的。
内部服务通过服务定义注册。服务定义可以由Consul代理启动时加载的配置文件提供,也可以通过/agent/service/register的本地HTTP API端点提供。
服务注册
我们将用以下配置注册一个内部web示例,web.json
1 | { |
这个示例web服务将具有惟一的id web1、逻辑名称web、运行在端口80上并每隔3秒进行一次健康检查。
通过使用PUT请求调用HTTP API来注册示例web服务
1 | $ curl --request PUT --data @web.json 192.168.48.135:8505/v1/agent/service/register |
要验证示例web服务已注册上去,请查询/catalog/service/:service 端点
1 | $ curl 192.168.48.135:8505/v1/agent/checks |
服务发现
可以在任意一台consul服务上通过dns查询创建的web服务
1 | $ dig @192.168.48.131 -p 8605 web.service.consul dc1 |
当服务健康检测正常时可查询到类似如下信息,便是web服务的地址了
web.service.consul. 0 IN A 192.168.48.134
模拟consul集群故障
模拟server节点故障
关闭server leader节点后,剩余server节点会进行leader选举,期间集群会短暂的无法提供服务,以下是重新选举的leader节点
查询web服务
1 | $ dig @192.168.48.131 -p 8605 web.service.consul dc1 |
此时可以正常进行查询,可见当server节点故障后consule集群依然可以正常提供服务
模拟client节点故障
client1故障前
关闭client1节点后,发现通过client1注册的web服务也不存在
client1故障后
再次通过client2节点进行查询
1 | $ dig @192.168.48.131 -p 8605 web.service.consul dc1 |
此时consul集群中查询不到web服务,当前环境中通过内部服务注册方式注册该web服务到client1节点,此时client1节点负责对此web服务进行健康检测,当client1故障时注册到该节点的服务在consul集群中也会随即失联。
服务剔除
通过内部服务注册到client后,client会对注册的服务进行健康检测并将结果传递给leader,由leader只对健康检测通过的服务进行解析。
以下两种方式都可以实现
1 | $ curl --request PUT http://192.168.48.135:8505/v1/agent/service/deregister/web1 |
注:通过内部服务注册到client1后只能通过client1进行删除。
外部服务注册
在Consul的上下文中,外部服务是由不能运行Consul代理的节点提供的服务。这些节点可能位于基础设施内部(例如大型机、虚拟设备或不支持的平台)或基础设施外部(例如SaaS平台)。
因为根据定义,外部服务在没有运行Consul代理的节点上运行,因此无法向本地代理注册。相反,它们必须使用/catalog/register端点 直接与目录一起注册。这个端点的对象上下文是节点,而不是像/agent/service/register 端点那样的服务。当使用/catalog/register端点时,将注册整个节点。而使用/agent/service/register 端点(这是我们在上面的第一个例子中使用的端点),本地节点上下文中的单个服务被注册。
直接通过目录注册的外部服务的配置与通过代理注册的内部服务的配置略有不同:
- 节点(Node)和地址(Address)都是必需的,因为它们不能从本地节点Consul代理自动确定。
- 服务(Service)和健康检查(Checks)是分开定义的。
- 如果提供的ServiceID与该节点上的服务ID匹配,则该检查将被视为服务级健康检查,而不是节点级健康检查。
- 可以为Definition 字段提供TCP或HTTP健康检查的详细信息。有关更多信息,请参阅健康检查。
使用Consul ESM监控外部服务
Consul ESM是一个与Consul一起运行的守护进程,用于运行外部节点的健康检查并更新目录中那些健康检查的状态。ESM的多个实例可以运行以获得可用性,并且ESM将通过持有一个Consul中的锁来执行领导人选举。然后,领导者将继续监视Consul对目录的更新,并执行在它发现的任何外部节点上定义的健康检查。这允许外部注册的服务和检查访问与Consul代理在本地注册相同的功能。
Consul ESM是作为一个单一的二进制文件提供的。要安装,请下载适合的版本。
在所有consul server服务器上,执行 consul-esm启用Consul ESM
1 | $ consul-esm |
如果您的internet提供者不允许UDP ping,为了使本文中的示例正常工作,您可能需要在配置文件中设置ping_type = “socket”,并使用该配置文件启动consult -esm。如果你正在使用macOS,你将需要执行sudo
1 | $ sudo consul-esm -config-file=./consul-esm.hcl |
示例外部服务定义中包含以下节点元数据(NodeMeta),这些元数据使Consul ESM能够进行健康监视:
“external-node”标识该节点是Consul ESM应该监视的外部节点。
“external-probe”:“true”告诉Consul ESM定期对节点执行ping,并维护节点的外部节点健康检查(类似于Consul代理使用的serfHealth检查)。
服务注册
要演示外部服务注册是如何工作的,请考虑谷歌提供的外部搜索服务。我们用以下配置来注册这个服务,web3.json
1 | { |
该配置定义了一个名为test_web 的节点,可以在地址192.168.48.134上访问,该节点提供一个web3服务,ID为search3,运行在端口8080上。它还定义了每3秒运行一次的http类型健康检查,并设置了该检查的初始状态 passing。
通常,外部服务是通过专门用于此目的的节点注册的,因此我们将继续使用Consul dev代理(localhost)进行示例,就好像它是在和内部web服务(例如“Web”)不同的另一个节点(例如“External Services”)上运行一样。
使用PUT请求注册外部服务
1 | $ curl --request PUT --data @web3.json 192.168.48.135:8505/v1/catalog/register |
与通过代理端点注册的内部服务一样,我们可以通过查询/catalog/service/:service 端点来验证外部服务的注册
1 | $ curl 192.168.48.135:8505/v1/catalog/service/web3 |
在我们的内部web服务示例中,我们通过查询本地代理端点 /agent/checks 来验证健康检查是活跃的。如果在添加外部服务之后再次查询此内容,我们将不会看到列出的健康检查,因为它是在服务目录中注册的,而不是本地代理。相反,我们需要查询目录级端点,例如/health/service/:service、/health/node/:node、/health/state/:state。
我们还可以看到Consul UI中列出的服务和健康检查
服务发现
可以在任意一台consul服务上通过dns查询创建的web服务
1 | $ dig @192.168.48.135 -p 8605 web3.service.consul dc1 |
当服务健康检测正常时可查询到类似如下信息,便是web服务的地址了
web3.service.consul. 0 IN A 192.168.48.134
模拟consul集群故障
模拟server节点故障
关闭server leader节点后,剩余server节点会进行leader选举,期间集群会短暂的无法提供服务,以下是重新选举的leader节点
查询web服务
1 | $ dig @192.168.48.131 -p 8605 web3.service.consul dc1 |
此时可以正常进行查询,可见当server节点故障后consule集群依然可以正常提供服务
模拟client节点故障
由于web3服务使用了外部服务注册方式进行服务注册,我们将现有的两台client节点全部下线
client节点故障前
client节点故障后
再次查询web3服务,由于两台client都无法提供服务我们通过其中一台server进行查询
1 | $ dig @192.168.48.134 -p 8600 web3.service.consul dc1 |
此时consul集群依然可以正常查询到web3服务,当前环境中由于使用了外部服务注册方式,服务直接注册为目录(节点);由consul-esm对服务进行健康检测,这样即解耦了服务和consul client的绑定关系又可规避因consul client故障时带来的服务发现问题。
服务剔除
通过上图可以发现,外部服务注册后服务最终落在了Nodes栏,可以在任意节点对node进行剔除。
1 | $ curl -X PUT -H 'application/json' -d '{"Datacenter": "dcNode": "test_web"}' http://127.0.0.1:8500/v1/catalog/deregister |