Nacos 注册中心的设计原理:让你的应用轻松实现高效注册与发现!

2023-11-14

当应用开始脱离单机运行和访问时,服务发现就诞生了。目前的网络架构是每个主机都有⼀个独立的 IP 地址,服务发现基本都是通过某种方式获取到服务所部署的 IP 地址。

DNS 协议是最早将⼀个网络名称翻译为网络 IP 的协议,在最初的架构选型中,DNS+LVS+Nginx 基本满足所有 RESTful 服务的发现,此时服务的 IP 列表通常配置在 nginx 或 LVS。后来出现 RPC 服务,服务的上下线更加频繁,人们开始寻求⼀种能够支持动态上下线并且推送 IP 列表变化的注册中心产品。

互联网软件行业普遍热捧开源产品,因为开源产品代码透明、可以参与共建、有社区进行交流和学习,当然更重要是免费。个人开发者或者中小型公司往往会将开源产品作为选型首选。

1 开源产品

1.1 Zookeeper

经典服务注册中心产品(虽然它最初的定位并不在于此),在很长⼀段时间里,是国人在提起 RPC 服务注册中心时心里想到的唯⼀选择,这很大程度上与 Dubbo 在中国的普及程度有关。

1.2 Consul 和 Eureka

都出现于 2014 年:

  • Consul 在设计上把很多分布式服务治理上要用到的功能都包含在内,可以支持服务注册、健康检查、配置管理、Service Mesh 等
  • Eureka借微服务概念流行,与 SpringCloud 生态的深度结合,也获取了大量的用户

1.3 Nacos

则携带着阿里巴巴大规模服务生产经验,试图在服务注册和配置管理这个市场上,提供给用户⼀个新的选择。

图 1 服务发现:

1.4 开源产品的优势

开发人员可以去阅读源代码,理解产品的功能设计和架构设计,同时也可以通过本地部署来测试性能,随之而来的是各种产品的对比文章。

不过当前关于注册中心的对比,往往停留在表面的功能对比上,对架构或者性能并没深入探讨。

1.5 痛点

是服务注册中心往往隐藏在服务框架背后,作为默默支持的产品。优秀的服务框架往往支持多种配置中心,但是注册中心的选择依然强关联与服务框架,⼀种普遍的情况是⼀种服务框架会带⼀个默认的服务注册中心。这样虽然免去了用户在选型上的烦恼,但是单个注册中心的局限性,导致用户使用多个服务框架时,必须部署多套完全不同的注册中心,这些注册中心之间的数据协同也是⼀个问题。

本文从各个角度深度介绍 Nacos 注册中心的设计原理,并试图从我们的经验和调研中总结和阐述服务注册中心产品设计上应该去遵循和考虑的要点。

2 数据模型

注册中心的核心数据:

  • 服务的名字
  • 它对应的网络地址

当服务注册了多个实例时,我们需要对不健康的实例过滤或针对实例的⼀些特征进行流量分配,就需要在实例存储⼀些如健康状态、权重等属性。随服务规模扩大,渐渐的又需要在整个服务级别设定⼀些权限规则、以及对所有实例都生效的⼀些开关,于是在服务级别又会设立⼀些属性。再往后,我们又发现单个服务的实例又会有划分为多个子集的需求,例如⼀个服务是多机房部署的,那么可能需要对每个机房的实例做不同的配置,这样又需要在服务和实例之间再设定⼀个数据级别。

对比

  • Zookeeper 没有针对服务发现设计数据模型,它的数据是以⼀种更加抽象的树形 K-V 组织的,因此理论上可以存储任何语义的数据
  • Eureka 或者 Consul 都做到实例级的数据扩展,可满足大部分的场景,不过无法满足大规模和多环境的服务数据存储
  • Nacos 在经过内部多年生产经验后提炼出的数据模型,则是⼀种服务-集群-实例的三层模型。基本满足服务在所有场景下的数据存储和管理。

Nacos 的数据模型虽然相对复杂,但它不强制你使用它里面的所有数据,在大多数场景下,你可以选择忽略这些数据属性,此时可降维成和 Eureka 和 Consul ⼀样的数据模型。

数据的隔离模型

作为⼀个共享服务型的组件,需要能够在多个用户或者业务方使用情况下,保证数据的隔离和安全,这在稍微大⼀点的业务场景中非常常见。另⼀方面服务注册中心往往会支持云上部署,此时就要求服务注册中心的数据模型能够适配云上的通用模型。

Zookeeper、Consul 和 Eureka 在开源层面都没有很明确的针对服务隔离的模型,Nacos 则在⼀开始就考虑到如何让用户能够以多种维度进行数据隔离,同时能够平滑的迁移到阿里云上对应的商业化产品。

图 3 服务的四层的数据逻辑隔离模型:

用户账号对应可能是⼀个企业或独立的个体,这个数据⼀般情况不会透传到服务注册中心。⼀个用户账号可新建多个命名空间,每个命名空间对应⼀个客户端实例,这个命名空间对应的注册中心物理集群是可以根据规则进行路由的,这样可以让注册中心内部的升级和迁移对用户无感知,同时根据用户的级别,为用户提供不同服务级别的物理集群。

再往下是服务分组和服务名组成的二维服务标识,可以满足接口级别的服务隔离。

Nacos 1.0.0 介绍的另外⼀个新特性是:临时实例和持久化实例。在定义上区分临时实例和持久化实例的关键是健康检查的方式。临时实例使用客户端上报模式,而持久化实例使用服务端反向探测模式。临时实例需要能够自动摘除不健康实例,而且无需持久化存储实例,那么这种实例就适用于类 Gossip 的协议。右边的持久化实例使用服务端探测的健康检查方式,因为客户端不会上报心跳,那么自然就不能去自动摘除下线的实例。

图 4 临时实例和持久化实例:

大中型公司,这两种类型的服务都有:

  • ⼀些基础组件如数据库、缓存等,这些往往不能上报心跳,这种类型的服务在注册时,就需要作为持久化实例注册
  • 上层的业务服务,例如微服务或者 Dubbo 服务,服务的 Provider 端支持添加汇报心跳的逻辑,可使用动态服务的注册方式

Nacos 2.0 沿用持久化及非持久化的设定,但有调整。Nacos 1.0 中持久化及非持久化的属性是作为实例的⼀个元数据进行存储和识别。导致同⼀个服务下可同时存在持久化实例和非持久化实例。但实际使用中,这种模式:

  • 会给运维人员带来极大的困惑和运维复杂度
  • 从系统架构来看,⼀个服务同时存在持久化及非持久化实例的场景也是存在⼀定矛盾

导致该能力事实上未被广泛使用。为简化 Nacos 的服务数据模型,降低运维复杂度,提升 Nacos 易用性,在 Nacos2.0 中:

  • 是否持久化的数据抽象至服务级别
  • 不再允许⼀个服务同时存在持久化实例和非持久化实例,实例的持久化属性继承自服务的持久化属性

3 数据⼀致性

分布式系统永恒话题,协议层面上看,⼀致性的选型已经很长时间没有新的成员加入了。目前来看基本

可归两家:

  • 基于 Leader 的非对等部署的单点写⼀致性
  • 对等部署的多写⼀致性

选用服务注册中心,没有⼀种协议能覆盖所有场景,如:

  • 当注册的服务节点不会定时发送心跳到注册中心时,强⼀致协议看起来是唯⼀的选择,因为无法通过心跳来进行数据的补偿注册,第⼀次注册就必须保证数据不会丢失
  • 而当客户端会定时发送心跳来汇报健康状态时,第⼀次的注册的成功率并不是非常关键(当然也很关键,只是相对来说我们容忍数据的少量写失败),因为后续还可以通过心跳再把数据补偿上来,此时 Paxos 协议的单点瓶颈就会不太划算了,这也是Eureka 为什么不采用 Paxos 协议而采用自定义的 Renew 机制

这两种数据⼀致性协议有各自使用场景,对服务注册需求不同,就会导致使用不同协议。Zookeeper 在 Dubbo 体系下表现出的行为,其实采用 Eureka 的 Renew 机制更合适,因为 Dubbo 服务往 Zookeeper 注册的就是临时节点,需要定时发心跳到 Zookeeper来续约节点,并允许服务下线时,将 Zookeeper 上相应的节点摘除。Zookeeper 使用 ZAB 虽保证数据的强⼀致,但是它的机房容灾能力的缺乏,无法适应⼀些大型场景。

Nacos 因为要支持多种服务类型的注册,并能够具有机房容灾、集群扩展等必不可少的能力,1.0.0 正式支持 AP 和 CP 两种⼀致性协议并存。1.0.0 重构数据的读写和同步逻辑,将与业务相关的 CRUD 与底层的⼀致性同步逻辑进行了分层隔离。然后将业务的读写(主要是写,因为读会直接使用业务层的缓存)抽象为 Nacos 定义的数据类型,调用⼀致性服务进行数据同步。在决定使用 CP 还是 AP ⼀致性时,使用⼀个代理,通过可控制的规则进行转发。

目前的⼀致性协议实现,⼀个是基于简化的 Raft 的 CP ⼀致性,⼀个是基于自研协议 Distro 的AP ⼀致性。Raft 协议不必多言,基于 Leader 进行写入,其 CP 也并不是严格的,只是能保证⼀半所见⼀致,以及数据的丢失概率较小。Distro 协议则是参考了内部 ConfigServer 和开源 Eureka,在不借助第三方存储的情况下,实现基本大同小异。Distro 重点是做了⼀些逻辑的优化和性能的调优

图 5 Nacos ⼀致性协议:

本文由博客一文多发平台 OpenWrite 发布!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nacos 注册中心的设计原理:让你的应用轻松实现高效注册与发现! 的相关文章

随机推荐

  • python从视频信息中提取音频,只用了三行代码...

    在做多媒体素材的时候 往往需要从视频中提取音频信息 在python中提供了moviepy这个非标准库 可以很快的帮助我们完成这个操作 算上导入moviepy非标准库的操作只需要三行代码完成 喜欢记得收藏 关注 点赞 1 单文件处理 将mov
  • Java 性能优化的 50 个细节

    前言 在JAVA程序中 性能问题的大部分原因并不在于JAVA语言 而是程序本身 养成良好的编码习惯非常重要 能够显著地提升程序性能 1 尽量在合适的场合使用单例 使用单例可以减轻加载的负担 缩短加载的时间 提高加载的效率 但并不是所有地方都
  • MySQL 表的 添加、更新与删除数据

    添加数据 为表中的所有 部分字段 添加数据 可以添加部分 也可以全部添加 INSERT INTO 表名称 字段名 VALUES 数据类型对应的 值 指定的字段 或 全部字段添加的数据 INSERT INTO 表名称 SET 字段名 值 同时
  • 用python实现时间序列自相关图(acf)、偏自相关图(pacf)

    自相关图是一个平面二维坐标悬垂线图 横坐标表示延迟阶数 纵坐标表示自相关系数 偏自相关图跟自相关图类似 横坐标表示延迟阶数 纵坐标表示偏自相关系数 自相关图与偏自相关图的python代码实现 from statsmodels graphic
  • 一个对象赋予另一个对象

    它的两个对象 n1 和n2 是在 main 里创建的 每个对象中的i 值都赋予了一个不 同的值 随后 将 n2 赋给n1 而且 n1 发生改变 当给n1 i赋值时 n2 i也会随着改变 这是由于无论n1 还是n2 都包含了相同的句柄 它指向
  • stm32cubeide驱动LCD1602显示屏

    STM32驱动LCD1602 硬件连接关系 STM32CUBEIDE设置 代码 项目设置 最后运行 硬件连接关系 LCD1602 STM32 VCC VCC GND GND VO VCC 滑动变阻 RS PB1 RW PB2 BOOT1 E
  • 上海国际区块链赋能传统产业峰会-王伟:道道人才链启动

    上海国际区块链赋能传统产业峰会 王伟 道道人才链启动 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 万赢信采编 在当前 区块链成为全球技术发展的前沿阵地 谋定研究 对话中国经济和信息化 区块链将加速 可信
  • QPixmap的尺寸设置

    问题描述 在控件上使用QPixmap时 希望能重新修改图片的分辨率 而不是使用图片的原始分辨率 解决方法 主要有两种方法 设置控件的尺寸 例如QPixmap被传入一个QLabel控件时 可以通过设置QLabel控件的尺寸来对QPixmap进
  • C++11 noexcept 关键字用法学习

    最近学习和写了一个 mint 的板子 其中用到了 noexcept 关键字 对这个关键字不太熟悉 便学习一下刘毅学长的文章 C 98 中的异常规范 Exception Specification 傲芙小说网 https www 3973 i
  • kaggle冠军代码汇总

    https www cnblogs com rw rongwei p 6509146 html
  • linux 查看进程和内存使用情况,深入理解linux下查看进程内存的使用情况

    本篇文章是对linux下查看进程内存的使用情况进行了详细的分析介绍 需要的朋友参考下 动态查看一个进程的内存使用 复制代码 代码如下 1 top命令 top d 1 p pid pid 设置为delay 1s 默认是delay 3s 如果想
  • 为什么C++内置类型的局部变量不能默认初始化

    C 有个人所共知的特性 就是它的内置类型是无法在局部区域内默认初始化的 如下所示 int k int main int m cout lt
  • 对象中BigDecimal值转换为JSON中精度丢失(出错)的问题解决方法

    代码如下 1 定义一个包含BigDecimal类型的类 Data public class User private String name private BigDecimal salary 2 分别使用两种方法将对象转换为字符串 pub
  • Linux安装python3

    一 卸载python命令 rpm qa grep python xargs rpm ev allmatches nodeps 强制删除已安装程序及其关联 whereis python xargs rm frv 删除所有残余文件 xargs
  • Opencv寻找轮廓的最小外接矩形,并获取矩形的中心点,旋转角度

    本代码可用于获取物体的坐标偏移量 旋转角度 if thresholdValue Mat src Mat imHeight imWidth CV 8U pImageBuffer Mat mat src copyTo mat threshold
  • springboot 普通类自动注入mapper

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 解决方法 解决方法 普通类使用 Component注解修饰 添加本类型静态属性 所需mapper属性 添加init方法 用 PostConstruct注解修饰 方法
  • vue +element实现图片上传加展示

    一 声明变量 我们在这里声明了两个qrcodeaddress 分别是绑定表单的字段和作为展示图片的字段 二 编写html部分 在这里img标签是我们上传之后 展示的地方 action是上传路径 on success是上传成功后的方法 三编写
  • Vue之路由

    Vue之路由 今天来看看vue怎么实现路由功能 我们在vue cil脚手架搭建好的基础上来实现路由功能 如果搭建完初始化项目时没有路由功能则需在npm安装路由 命令 npm install vue router 然后在main js中引用路
  • 【Python】os.path.exists()的含义 及文件存在但os.path.exists()返回False的原因

    os path exists 函数的功能是查看给定的文件 目录是否存在 存在返回True 不存在返回False 如果给定的文件只有文件名 会在当前文件的目录下索引 给定的文件 目录可以是绝对索引 文件存在但os path exists 返回
  • Nacos 注册中心的设计原理:让你的应用轻松实现高效注册与发现!

    当应用开始脱离单机运行和访问时 服务发现就诞生了 目前的网络架构是每个主机都有 个独立的 IP 地址 服务发现基本都是通过某种方式获取到服务所部署的 IP 地址 DNS 协议是最早将 个网络名称翻译为网络 IP 的协议 在最初的架构选型中