本文包含 Zookeeper,Eureka,Nacos,Consul 的基本使用,以及将从多个维度进行对比介绍。
基础介绍与实践
ZooKeeper 篇
Eureka 实战 & 理论
Nacos 实战 & 理论
Consul 实战
CAP 选择
-
Zookeeper:支持CP,即保障一致性和分区容错性
-
Eureka :支持AP,即保障可用性和分区容错性
-
Nacos:支持AP和CP两种模式,常用为AP
临时服务(Ephemeral):临时服务健康检查失败后会从列表中删除,常用于服务注册发现场景。
其一致性模型是 AP,使用 Nacos 为服务注册发现场景定制化的私有协议 distro
持久化服务(Persistent):持久化服务健康检查失败后会被标记成不健康,常用于 DNS 场景。
临时服务使用的是 Nacos 为服务注册发现场景定制化的私有协议 distro,其一致性模型是 AP;
其一致性模型是 CP,使用 raft 协议 -
consul:支持 CP,即保障一致性和分区容错性
一致性协议
-
Zookeeper
ZAB(Zookeeper专门设计的一种支持崩溃恢复的原子广播协议) -
Eureka
无 -
Nacos
AP:Nacos 为服务注册发现场景定制化的私有协议 distro
CP:raft 协议 -
Consul
raft 协议 -
相关协议介绍
Distro协议的设计思想
Nacos 每个节点是平等的都可以处理写请求,同时把新数据同步到其他节点。
每个节点只负责部分数据,定时发送自己负责数据的校验值到其他节点来保持数据一致性。
每个节点独立处理读请求,及时从本地发出响应。
Zookeeper全解析——Paxos作为灵魂
Nacos集群raft选举算法原理
raft 动画解析
集群模式
-
Zookeeper:主从模式, 集群角色包含leader、follower以及observer三类
[leader
]:负责投票的发起和决议
[follower
]:同步leader的状态,参与leader选举。将写操作转发给leader,并参与“过半写成功”策略
[observer
]:同步leader的状态,将写操作转发给Leader。不参加投票选举过程,也不参加写操作的“过半写成功”策略 -
Eureka:去中心化架构, 集群各节点都是平起平坐的关系,数据是相互复制的
-
Nacos:支持平级关系和主从这两种集群架构,常用的是后者
主从模式, 包含leader、follower、candidate三类
[Leader
]: 唯一负责处理客户端写请求的节点,也可以处理客户端读请求,同时负责日志复制工作,整个集群只有一个Leader
[Follower
]: 可以处理客户端读请求,负责同步来自于Leader的日志,当接收到其它Cadidate的投票请求后可以进行投票,当发现Leader挂了其会转变为Cadidate发起选举
[Candidate
]:一种临时的角色,只存在于leader的选举阶段
某个节点想要变成leader,那么就发起投票请求,同时自己变成candidate,如果选举成功,则变为Follower,否则退回为follower -
consul :主从模式, 集群角色包含server-leader、server以及client
[client
] : consul的client模式的节点。接收到consul的客户端请求以后,不做处理,会转发到server-leader,也不会持久化信息
[server
]: consul的server模式的节点,功能和client都一样。唯一不同的是,它会把所有的信息持久化到本地,这样遇到故障,信息是可以被保留的
[server-leader
]: 名字就已经说明,这个server是所有服务端接节点的老大了,那么它自然负责的工作就多啦~ 它除了和普通的server模式的节点一样,需要进行信息持久化以外,还额外需要负责同步注册的信息给其它的server,同时也要负责各个节点的健康监测
可用性
- Zookeeper
在使用 Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用,那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性 - Eureka
- 在集群环境中如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点上,当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。
- Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册表中移除因为长时间没有收到心跳而过期的服务;
- Eureka仍然能够接受新服务注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新注册的信息会被同步到其它节点中。
- Nacos
-
当其中一台机器宕机时,为了不影响整体运行,客户端会存在重试机制
-
注册中心发生故障最坏的一个情况是整个 Server 端宕机,这时候 Nacos 依旧有高可用机制做兜底。 Nacos 存在本地文件缓存机制,nacos-client 在接收到 nacos-server 的服务推送之后,会在内存中保存一份,随后会落盘存储一份快照。snapshot 默认的存储路径为:{USER_HOME}/nacos/naming/ 中。
-
distro 协议下,当节点发生宕机后,原本该节点负责的一部分服务的读写任务会转移到其他节点,从而保证 Nacos 集群整体的可用性
-
Consul
尽管对复制日志的所有写入都通过 Raft,但读取更加灵活。为了支持开发人员可能想要的各种权衡,Consul 支持 3 种不同的读取一致性模式。 -
default
- Raft 使用了领导者租期 -leasing
,提供了一个时间窗口,领导者在其中扮演稳定的角色。但是,如果领导者与其余对等体分开,则可能会在旧领导者持有租期时选出新领导者。这意味着有 2 个领导节点。不存在脑裂的风险,因为旧的领导者将无法提交新的日志。但是,如果旧的领导者仍然为任何读取提供服务,则这些值可能是陈旧的。默认的一致性模式仅依赖于领导者租期,将会给客户端暴露潜在的陈旧值。我们进行这种权衡是因为读取速度很快,通常具有很强的一致性,并且仅在难以触发的情况下才会失效。过时读取的时间窗口也是有界的,因为领导者将因分区而下台。 -
consistent
- 这种模式提供强一致性。它要求领导者与法定人数的对等方一起验证它仍然是领导者。这引入了到所有服务器节点的额外往返。权衡的利:总是一致的读取,弊:由于额外的往返行程而增加了延迟。 -
stale
- 这种模式允许任何服务器为读取提供服务,而不管它是否是领导者。这意味着读取可以任意陈旧,但通常在领导者的 50 毫秒内。权衡是非常快速和可扩展的读取,但具有过时的值。这种模式允许在没有领导者的情况下进行读取,这意味着不可用的集群仍然能够响应。
stale 模式下可以可以保证在选举时读取的可用性
服务感知
- Zookeeper
Zookeeper的Watch机制其实就是一种推拉结合的模式:
服务消费者会去监听相应路径(/HelloWorldService/1.0.0),一旦路径上的数据有任务变化(增加或减少),Zookeeper只会发送一个事件类型和节点信息给关注的客户端,而不会包括具体的变更内容,所以事件本身是轻量级的,这就是推的部分。
收到变更通知的客户端需要自己去拉变更的数据,这就是拉的部分。 - Eureka
- Eureka客户端通过定时HTTP轮询Eureka服务端来获取Provider节点是否有变化,存在效率不高的问题,当接入Eureka的节点过多时,会造成Eureka本身响应的性能问题,如CPU偏高,同时也会造成Eureka的吞吐性能问题,进一步造成客户端不能够及时获取到最新的Provider节点;
- Eureka存在二级缓存机制,会导致 Client获取不到最新的服务实例信息,然后导致无法快速发现新的服务和已下线的服务
第⼀层缓存是readOnlyCacheMap,readOnlyCacheMap是采用ConcurrentHashMap来存储数据的,主要负责定时与readWriteCacheMap进⾏数据同步,默认同步时间为 30 秒⼀次。
第⼆层缓存是readWriteCacheMap,readWriteCacheMap采⽤Guava来实现缓存。缓存过期时间默认为180秒,当服务下线、过期、注册、状态变更等操作都会清除此缓存中的数据。
- Nacos
客户端:维护定时任务定时从Nacos服务端获取服务实例信息
服务端: 开启一个UDP服务实例信息变更推送服务
图文源码分析Nacos如何实时感知服务提供者实例信息/个数的变更 - Consul
自动注销实例
- Zookeeper
它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除 - Eureka
默认情况下,如果Eureka Server在90秒内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(时间间隔可以配置) - Nacos
用户通过客户端SDK注册的实例,将默认开启TTL功能,实例会默认每5秒向服务端发送一次心跳,如果Nacos服务端15秒内没有收到实例的心跳,则会将实例置为不健康,如果30秒没有收到心跳,则会将直接将实例删除 - Consul
不支持
雪崩保护
- Zookeeper
不支持 - Eureka
自我保护机制 - Nacos
为了防止因过多实例 (Instance) 不健康导致流量全部流向健康实例 (Instance) ,继而造成流量压力把健康实例 (Instance) 压垮并形成雪崩效应,应将健康保护阈值定义为一个 0 到 1 之间的浮点数
当域名健康实例占总服务实例的比例小于该值时,无论实例是否健康,都会将这个实例返回给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例 (Instance) 能正常工作 - Consul
不支持
健康检查
- Zookeeper
本身没有健康检查机制,需要消费者自己实现服务提供者的健康检查动作 - Eureka
Eureka Server 与 Eureka Client 之间使用心跳机制来确定Eureka Client 的状态,默认情况下,服务器端与客户端的心跳保持正常,应用程序就会始终保持UP状态 - Nacos
Nacos 支持传输层(PIND 或 TCP)和应用层(如 HTTP、MySQL以及用户自定义)的监控检查,同时还支持类似于Eureka的心跳机制的健康检查 - Consul
基于Agent实现的分布式健康检查机制,每个机器上的Consul Agent会不断的发送请求检查服务是否健康,是否宕机。如果服务宕机了,那么就会通知Consul Server
访问协议
- Zookeeper
Zookeeper 采用 TCP 进行访问 - Eureka
Eureka 采用 HTTP 协议进行访问 - Nacos
Nacos 支持 HTTP 和 DNS 访问协议 - Consul
Consul 支持 HTTP 和 DNS 访问协议
跨数据中心同步
nacos和consul支持跨注册中心同步
参考文章
阿里面试败北:5种微服务注册中心如何选型?这几个维度告诉你!
注册中心选型篇-四款注册中心特点超全总结
注册中心对比和选型:Zookeeper、Eureka、Nacos、Consul和ETCD
图文源码分析Nacos如何实时感知服务提供者实例信息/个数的变更?
Nacos集群raft选举算法原理