注册中心的简单演化史及 Nacos 和 Zookeeper 的区别

321 阅读7分钟

IMG_1411.jpg

博客:liufq.com

注册中心作为分布式系统的基础组件,粗略经历了三个阶段:Zookeeper 的 CP 阶段(优先满足一致性),Eureka、Nacos 的 AP 阶段(优先满足可用性),云原生阶段(服务网格)。

之所以这样演变大概是因为微服务初期服务信息都比较小,CP 模式对可用性的影响不大,大家能忍,而且没有一个专门的注册中心组件(Zookeeper 不是专门做注册中心的),还有很大原因是因为 Dubbo 选择了 Zookeeper。

但注册中心本质是个数据库,存的是服务的节点信息,对一致性的要求并不高,节点上下线导致数据变化时,数据不一致可能会导致调用了一个已经下线的服务,这个影响并不大,重试另一个节点就好了,只要保证最终一致性就可以。于是随着服务节点越来越多,Zookeeper 性能问题开始明显,而且毕竟不是专门做注册中心的组件,在健康检查、扩展性等方面不满足需求,这时自然演变成了 Eureka、Nacos 等 AP 模式的组件。

到了云原生时代,把打包、部署、硬件资源分配等都交给了 Kubernetes 等云基础设施完成,有人就想服务发现、负载均衡也是底层通用能力,能不能把这些从业务服务里抽象出来,放到单独的一层网络基础设施层?于是服务网格出现了,但目前还不是很成熟。

注册中心作为微服务最基本的组件之一,深入理解至少一个组件是很有必要的,理解了一个其他都是大同小异的,也很容易理解。主要的产品有 Zookeeper、Consul、Eureka、Nacos。

Nacos

学习 Nacos 首先推荐看下官方出的《Nacos 架构与原理》,这本书里解答了很多为什么的问题,为什么这么设计、为什么选这个通信组件、为什么要造一个新轮子,为什么有时候比是什么更重要。

然后是官方的文档,最后最好自己再部署搭建使用下,这里主要是看这本书记的一些笔记。

点击展开《Nacos 架构与原理》 - 思维导图

看完这本书需要弄懂的几个核心问题

  1. 一致性设计、通信设计、寻址设计,为什么这么设计?各种方案优缺点和选择原因?
  2. 注册中心的一致性、数据存储、负载均衡、健康检查如何实现?
  3. 配置中心的一致性、数据存储如何实现?

Nacos 架构设计原则

架构设计的核心是围绕分层模块化设计

设计原则:

  1. 极简原则,简单才好用,简单才稳定,简单才易协作。
  2. 架构一致性,一套架构要能适应开源、内部、商业化(公有云及专有云)3个场景。
  3. 扩展性,以开源为内核,商业化做基础,充分扩展,方便用户扩展。
  4. 模块化,将通用部分抽象下沉,提升代码复用和健壮性。
  5. 长期主义,不是要一个能支撑未来3年的架构,而是要能够支撑10年的架构。
  6. 开放性,设计和讨论保持社区互动和透明,方便大家协作。

Nacos 一致性方案设计

  1. 各种一致性方案适应场景,分析 Nacos 选择的原因
  2. 一致性协议具体实现选型
  3. 一致性协议下沉到内核,成为通用模块
  4. 一致性协议和数据存储模块拆分解耦

Nacos 通信通道的设计

  1. 短连接到长连接的升级过程
  2. 长连接技术选型考虑
  3. 长连接和短连接在负载均衡方面的差异与选取

Nacos 寻址机制设计

  1. 通过 MemberLookup 列表维护动态成员节点信息
  2. 通过单机寻址、文件寻址、地址服务器寻址等方式把节点 ip、端口信息封装成节点加入 MemberLookup 列表

Zookeeper

Zookeeper 的本质是一个保证分布式环境下数据一致的系统

用作注册中心,数据就是服务 IP、端口等信息,用作配置中心,数据就是配置项,所以 Zookeeper 并不是专门用来做注册中心的,只是它的特点适合用来做注册中心。

既然是分布式环境,CP 和 AP 必然要选择其一,既然要保证数据一致性,必然涉及到数据存储和同步。

所以 Zookeeper 的关键问题就是选择什么样的一致性算法来存储和同步数据

一致性选取

Zookeeper 的定位决定了它是优先一致性的,也就是 CP 模式,但为了更好的可用性,只要超过半数写入成功就算成功了,牺牲了一定一致性换来更好的可用性,从这个角度看它并不完全是一个强一致性协议。

一致性实现

Zookeeper 通过 ZAB 协议实现一致性,可以简单理解为类似二阶段提交协议,但是第二阶段只要超过半数就算成功。

Zookeeper 节点分为 Leader 和 Follower,Leader 只能有一个,作用类似二阶段协议里的协调者,负责数据写入(所有写入操作都会转发到 Leader),写入的过程会广播所有 Follower 节点写入数据,过半成功后 Leader 才真正提交本次操作(跟二阶段思想是一样的)。由于写操作保证了数据一致性,读操作可以在任意节点直接返回。

上述就是 ZAB 的广播模式,当 Leader 崩溃或者集群刚启动没有 Leader 时,ZAB 进入恢复模式选择一个 Leader。

Leader 选举

选举通过所有节点参与两轮投票选出。

第一轮所有节点都投自己,把自己的 SID(服务器微医标识)和 ZXID(事务 id)发送给其他所有节点。

收到其他节点投票信息后会比较 SID 和 ZXID,发起第二轮投票,优先认可 ZXID 比自己大的,再认可 SID 比自己大的,否则坚持原有投票。

投票需要所有节点的参会,当为了支持更多的客户端加入了很多 Zookeeper 节点时,节点越多延迟也就越高,为了提高选举性能,可以把部分节点设为 Observer 节点,跟 Follower 类似,只是没有投票权,以此来提高投票性能。

Nacos 和 Zookeeper 有什么区别?

主要区别在于:一致性协议数据模型使用场景不一样。

一致性协议

Zookeeper 主要通过 ZAB 协议来保证数据一致性,ZAB 是 ZK 自研的一种强一致性协议,在牺牲可用性的情况下保证了一致性;而 Nacos 默认是 AP 模式,用的是阿里自研的 Distro 协议,是一种最终一致性协议,通过定期检查、补齐数据来保证数据一致,优先可用性。同时支持 CP 模式,使用 Raft 协议保证数据一致性。

数据模型

Zookeeper 是通过它的树形节点来存储数据,同时监听节点数据变化,是持久化数据;

Nacos 注册中心默认是非持久化的数据,通过客户端上报来维持数据。当客户端无法上报时也支持持久化服务,使用 CP 模式更新数据。

Nacos 配置中心默认是数据库持久化。

使用场景

Zookeeper 并不是专门用来做注册中心、配置中心的,只不过它的特性恰好可以用来实现注册中心和配置中心,除此之外还可以用作分布式协调、通知、选举、分布式锁等场景。

而 Nacos 是专门为注册中心、配置中心开发的,场景更专一。