【zookeeper】如何选择微服务注册中心?
我想结合生产中遇到的一个故障,和你聊聊注册中心的选型问题。
在微服务架构体系相当长的一段发展时间里,ZooKeeper 都占领着微服务注册中心的头把交椅,几乎成为注册中心唯一的选择。
这是为什么呢?接下来我们就重点解读一下 ZooKeeper 的 CP 设计理念。
ZooKeeper 是一个分布式协调组件,符合 CAP 分布式理论中的 CP。
CAP 理论指的是,在一个分布式集群中存储同一份数据,无法同时实现 C(一致性)、A(可用性) 和 P(持久性),只能同时满足其中两个。
由于 P 在数据存储领域是必须要满足的,所以通常需要在 C 与 A 之间做权衡。
ZooKeeper 是保住了一致性和持久性,选择性地牺牲了可用性。
ZooKeeper 的数据写入流程如下:
image.png
在 ZooKeeper 集群中,首先会进行 Leader 选举,根据 ZAB 协议选举出一个 Leader 节点用来处理写请求,然后将数据复制给从节点:
- 当集群内超过半数节点写入成功,则返回“数据写入成功”;
- 如果集群内还没有成功选举出 Leader,则 ZooKeeper 集群无法向外提供数据写入与读取服务。
在 Leader 选举期间,集群是不可用的(牺牲了可用性)。
但在正常生产实践过程中,ZooKeeper 集群内部选举 Leader 节点的耗时在毫秒级别,并不会影响使用。然而,一旦遇到异常情况就很难说了。
我在生产过程中就出现了由于 ZooKeeper 集群内存溢出导致频繁 Full GC 的情况。
当时的情况是,公司内部的 Dubbo 专用 ZooKeeper 地址被业务方用做分布式锁,但他们在使用过程中频繁创建节点,加上遇到 Bug,节点数据没有及时删除,这就导致占用的内存越来越大,最终频繁 Full GC,使得 ZooKeeper 会话超时,所有注册在 ZooKeeper 注册中心的服务全部被删除,所有客户端服务调用都出现“No Provider”警告,酿成一场严重的生产级故障。
经过这次故障,我也开始重新审视 ZooKeeper 和 CP 模式的合理性。
注册中心是微服务体系的大脑,一旦出现问题会带来不可估量的损失,其可用性尤为重要。
也正是因为 CP 模型存在严重的可用性问题,以 AP 为设计思想的注册中心开始逐渐涌现出来。
AP 的核心指导思想是容忍分布式集群中多个节点之间的数据短暂不一致,但最终能达到一致性。
EureKa 就是典型的基于 AP 的注册中心。
由于基于 AP 的注册中心不需要保证强一致性,所以集群内节点的地位通常都是平等的。
客户端在同一时间与集群中一个节点保持长连接,当出现错误后,客户端再从注册中心集群中选择另外一个节点,并且客户端可以向集群中任何一个节点写入数据后立即返回“写入成功”,然后让数据异步在集群内部复制,最终实现数据的一致性。
EureKa 集群的写入流程如下:
image.png
由于集群内部节点的地位是平等的,客户端在其中一个节点不可用时,可以快速切换到另外的节点,这样可用性就得到了保障。
那么问题来了,节点之间路由信息不一致会带来什么问题呢?这些问题我们可不可以接受?
在回答这个问题之前我们不妨来看看一个注册中心各个节点数据不一致的例子,如下所示:
image.png
在这里,由于某种异常,Eureka 集群中各个节点存储的数据并不一致,在节点 1 和 2 中关于 /user/saveUser 接口有三个服务提供者,但在节点 3 中只有两个服务提供者。
但无论是三个服务提供者也好,还是两个服务提供者也好,都会造成负载不均衡,如果节点出现类似 Full GC 的问题,节点无法对外提供服务,这时候客户端会从集群中选择其他节点重试,并不会对系统带来致命影响。
综合来看,服务注册中心这种场景,AP 模式显然比 CP 模式更佳。
这也是为什么现在很多原先使用 CP 模式的注册中心都开始尝试向 AP 转化,而像 Eureka、Nacos 这种注册中心基本都同时提供了 AP 和 CP 两种工作模式,用户可以按照场景进行选择。
以 Eureka 和 Nacos 为代表的注册中心,正在逐渐取代采用 CP 模式的 ZooKeeper,成为注册中心的优先选项。
基于 Zookeeper 搭建的 Dubbo 服务注册中心,由于 ZooKeeper 节点的内存使用不当导致频繁触发 Full GC,最终导致 ZooKeeper 会话超时,在注册中心的服务提供者会全部被删除,所有的消费者调用都感知不到服务提供者,进而导致服务调用雪崩。
这时候我们应该怎么做呢?难道要重启所有服务提供者,让他们重新注册吗?你有什么快速恢复的方法?
清除zookeeper的数据,然后重新启动zookeeper。
这样zookeeper就能快速恢复正常,此时dubbo 服务提供者会自动向zookeeper中注册,消费端就可以动态感知,问题能得到快速恢复。
微服务体系的注册中心必须独占,并且要做好监控告警,目前主要是zookeeper的acl感觉对用户使用不太友好,授权比较麻烦,别人只要知道地址就可以用。