Zookeeper 是⼀款经典的服务注册中心产品(虽然它最初的定位并不在于此),在很长⼀段时间里,它是国人在提起 RPC 服务注册中心时心里想到的唯⼀选择。
Eureka 借着微服务概念的流行,与 SpringCloud 生态的深度结合,也获取了大量的用户。
Consul 在设计上把很多分布式服务治理上要用到的功能都包含在内,可以支持服务注册、健康检查、配置管理、Service Mesh 等。
Nacos 携带着阿里巴巴大规模服务生产经验,试图在服务注册和配置管理这个市场上,提供给用户⼀个新的选择。
(CAP理论,指的是在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性),不能同时成立。)
数据模型
Zookeeper 没有针对服务发现设计数据模型,它的数据是以⼀种更加抽象的树形 K-V 组织的,因此理论上可以存储任何语义的数据。
Eureka 和 Consul 都是做到了实例级别的数据扩展,这可以满足大部分的场景,不过无法满足大规模和多环境的服务数据存储。
Nacos 是⼀种服务-集群-实例的三层模型。基本可以满足服务在所有场景下的数据存储和管理。
数据⼀致性
从协议层面上看,⼀致性的选型目前就两种:⼀种是基于 Leader 的非对等部署的单点写⼀致性,⼀种是对等部署的多写⼀致性。
Zookeeper 是CP,采用自定义的 ZAB 协议保证数据的强⼀致。Zookeeper 在 Dubbo 体系下表现出的行为,其实采用 Eureka 的 Renew 机制更加合适,因为 Dubbo 服务往 Zookeeper 注册的就是临时节点,需要定时发心跳到 Zookeeper 来续约节点,并允许服务下线时,将 Zookeeper 上相应的节点摘除。
Eureka 是AP,节点都是对等的,通过相互注册提高可用性,通过renew机制进行数据的最终修复。
Consul 是CP,基于Raft协议保证数据的强一致性。
Nacos 同时支持 CP 和 AP ,⼀个是基于简化的 Raft 的 CP ⼀致性,⼀个是基于自研协议 Distro 的 AP ⼀致性。
负载均衡
Zookeeper 不支持。
Eureka 本身不支持,通过Ribbon做负载均衡。Ribbon是客户端负载均衡,主要通过 IRule、ServerListFilter 等接口实现,Ribbon采用的是两步负载均衡,第⼀步是先过滤掉不会采用的服务提供者实例,第二步是在过滤后的服务提供者实例里,实施负载均衡策略。
Consul 本身不支持,通过Fabio做负载均衡。
Nacos 本身具备负载均衡能力,可以提供服务端负载均衡与客户端负载均衡。
健康检查
服务端健康检查最常见的方式是 TCP 端口探测和 HTTP 接口返回码探测,这两种探测方式因为其协议的通用性可以支持绝大多数的健康检查场景。Zookeeper 和 Eureka 都实现了⼀种 TTL(Time To Live)机制,就是如果客户端在⼀定时间内没有向注册中心发送心跳,则会将这个客户端摘除。
Zookeeper 使用TCP的KeepAlive保持客户端和服务端的连接。
Eureka 通过客户端心跳来确定客户端是否启动。
Consul 通过check方法实现健康检查,check方法有五种:Script + Interval、HTTP + Interval、TCP+ Interval、Docker + interval、TTL。
Nacos 既支持客户端的健康检查(KeepAlive、Client Beet),也支持服务端的健康检查(MYSQL命令等)。
性能与容量
影响读写性能的因素很多:⼀致性协议、机器的配置、集群的规模、存量数据的规模、数据结构及读写逻辑的设计等等。并非性能越高就越好,因为追求性能往往需要其他方面做出牺牲。
Zookeeper 在写性能可以达到上万的 TPS,容量从存储节点数来说可以达到百万级别。不过 Paxos 协议限制了 Zookeeper 集群的规模(3、5个节点)。当大量实例上下线时,Zookeeper 的表现并不稳定,同时在推送机制上的缺陷,会引起客户端的资源占用上升,从而性能急剧下降。
Eureka 在服务实例规模在 5000 左右的时候,就已经出现服务不可用的问题,甚至在压测的过程中,如果并发的线程数过高,就会造成 Eureka crash。
Nacos 在开源版本中,服务实例注册的支撑量约为 100 万,服务的数量可以达到 10 万以上。