news 2026/2/24 22:04:13

SpringCloud:Nacos 原理与解析学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringCloud:Nacos 原理与解析学习

总体设计

Nacos架构

整体架构分为用户层、业务层、内核层和插件,用户层主要解决用户使用的易用性问题,业务层主要解决服务发现和配置管理的功能问题,内核层解决分布式系统一致性、存储、高可用等核心问题, 插件解决扩展性问题。

用户层

  • OpenAPI:暴露标准Rest风格HTTP接口,简单易用,方便多语言集成。
  • Console:易用控制台,做服务管理、配置管理等操作。
  • SDK:多语言 SDK,目前几乎支持所有主流编程语言。
  • Agent:Sidecar 模式运行,通过标准 DNS 协议与业务解耦。
  • CLI:命令行对产品进行轻量化管理,像 git 一样好用。

业务层

  • 服务管理:实现服务 CRUD,域名 CRUD,服务健康状态检查,服务权重管理等功能。
  • 配置管理:实现配置管 CRUD,版本管理,灰度管理,监听管理,推送轨迹,聚合数据等功能。
  • 元数据管理:提供元数据 CURD 和打标能力,为实现上层流量和服务灰度非常关键。

内核层

  • 插件机制:实现三个模块可分可合能力,实现扩展点 SPI 机制,用于扩展自己公司定制。
  • 事件机制:实现异步化事件通知,SDK 数据变化异步通知等逻辑,是 Nacos 高性能的关键部分。
  • 日志模块:管理日志分类,日志级别,日志可移植性(尤其避免冲突),日志格式,异常码+帮

助文档。

  • 回调机制:SDK 通知数据,通过统一的模式回调用户处理。接口和数据结构需要具备可扩展性。
  • 寻址模式:解决 Server IP 直连,域名访问,Nameserver 寻址、广播等多种寻址模式,需要可

扩展。

  • 推送通道:解决 Server 与存储、Server 间、Server 与 SDK 间高效通信问题。
  • 容量管理:管理每个租户,分组下的容量,防止存储被写爆,影响服务可用性。
  • 流量管理:按照租户,分组等多个维度对请求频率,长链接个数,报文大小,请求流控进行控制。
  • 缓存机制:容灾目录,本地缓存,Server 缓存机制,是 Nacos 高可用的关键。
  • 启动模式:按照单机模式,配置模式,服务模式,DNS 模式模式,启动不同的模块。
  • 一致性协议:解决不同数据,不同一致性要求情况下,不同一致性要求,是 Nacos 做到 AP 协

议的关键。

  • 存储模块:解决数据持久化、非持久化存储,解决数据分片问题。

插件

  • Nameserver:解决 Namespace 到 ClusterID 的路由问题,解决用户环境与 Nacos 物理环境 映射问题。
  • CMDB:解决元数据存储,与三方 CMDB 系统对接问题,解决应用,人,资源关系。
  • Metrics:暴露标准 Metrics 数据,方便与三方监控系统打通。
  • Trace:暴露标准 Trace,方便与 SLA 系统打通,日志白平化,推送轨迹等能力,并且可以和计

量计费系统打通。

  • 接入管理:相当于阿里云开通服务,分配身份、容量、权限过程。
  • 用户管理:解决用户管理,登录,SSO 等问题。
  • 权限管理:解决身份识别,访问控制,角色管理等问题。
  • 通知系统:核心数据变更,或者操作,方便通过SMS系统打通,通知到对应人数据变更。

Nacos整体架构图

Nacos配置模型

概念介绍

配置(Configuration):系统开发中的一些需要变更的参数、变量,以独立的配置文件的形式存在。

配置管理 (Configuration Management):在 Nacos 中,系统中所有配置的存储、编辑、删除、灰度管理、历史版本管理、变更审计等所有与配置相关的活动统称为配置管理。

配置服务 (Configuration Service):在服务或者应用运行过程中,提供动态配置或者元数据以及配置管理的服务提供者。

配置集(Configuration Set):一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集, 包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。

配置 ID(Data ID):Nacos 中的某个配置集的 ID。配置集 ID 是划分配置的维度之一。Data ID 通常用于划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 尽量保障全局唯一,可以参考 Nacos Spring Cloud 中的命名规则:${prefix}-${spring.profiles.active}-${file-extension}

配置组(Group):Nacos 中的一组配置集,是配置的维度之一。通过一个有意义的字符串(如 ABTest 中的实验组、 对照组)对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时, 如果未填写配置分组的名称,则配置分组的名称默认采用DEFAULT_GROUP。配置分组的常见场景: 不同的应用或组件使用了相同的配置项,如 database_url 配置和 MQ_Topic 配置。

命名空间(Namespace):用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源 隔离,也可以用于租户之间的隔离,例如 zhangsan,lisi,wangwu 。如果在没有指定 Namespace 的情况下,默认使用public命名空间。

配置快照(Configuration Snapshot):Nacos 的客户端 SDK 会在本地生成配置的快照。当客户端无法连接到 Nacos Server 时,可以使 用配置快照显示系统的整体容灾能力。配置快照类似于 Git 中的本地 commit,也类似于缓存,会 在适当的时机更新,但是并没有缓存过期(expiration)的概念。

基础模型

  1. Nacos 提供可视化的控制台,可以对配置进行发布、更新、删除、灰度、版本管理等功能。
  2. SDK 可以提供发布配置、更新配置、监听配置等功能。
  3. SDK 通过 GRPC 长连接监听配置变更,Server 端对比 Client 端配置的 MD5 和本地 MD5 是否相等,不相等推送配置变更。
  4. SDK 会保存配置的快照,当服务端出现问题的时候从本地获取。

Nacos基础模型

配置存储模型(ER 图)

Nacos 存储配置有几个比较重要的表分别是:

  • config_info 存储配置信息的主表,里面包含 dataId、groupId、content、tenantId、encryptedDataKey 等数据。
  • config_info_beta 灰度测试的配置信息表,存储的内容和 config_info 基本相似。有一个 beta _ips 字段用于客户端请求配置时判断是否是灰度的 ip。
  • config_tags_relation 配置的标签表,在发布配置的时候如果指定了标签,那么会把标签和配置 的关联信息存储在该表中。
  • his_config_info 配置的历史信息表,在配置的发布、更新、删除等操作都会记录一条数据,可 以做多版本管理和快速回滚。

内核设计

一致性协议

为什么需要一致性协议

Nacos 的设计目标是,用户只需要一个程序包就可以快速的以单机或集群的方式启动,而 Nacos是一个需要存储数据的组件。单机下其 实问题不大,简单的内嵌关系型数据库即可;但是集群模式下,就需要考虑如何保障各个节点之间 的数据一致性以及数据同步,而要解决这个问题,就要通过算法来保障各个节 点之间的数据的一致性。

为什么 Nacos 选择了 Raft 以及 Distro ?

为什么 Nacos 会在单个集群中同时运行 CP 协议以及 AP 协议呢?这其实要从 Nacos 的场景出发的:Nacos 是一个集服务注册发现以及配置管理于一体的组件,因此对于集群下,各个节点之间的数据一致性保障问题,需要拆分成两个方面:

1、从服务注册发现来看

服务发现注册中心,在当前微服务体系下,是十分重要的组件,服务之间感知对方服务的当前可正常提供服务的实例信息,必须从服务发现注册中心进行获取,因此对于服务注册发现中心组件的可 用性,提出了很高的要求,需要在任何场景下,尽最大可能保证服务注册发现能力可以对外提供服务;同时 Nacos 的服务注册发现设计,采取了心跳可自动完成服务数据补偿的机制。如果数据丢失的话,是可以通过该机制快速弥补数据丢失。

上述的都是针对于 Nacos 服务发现注册中的非持久化服务而言(即需要客户端上报心跳进行服务实 例续约)。而对于 Nacos 服务发现注册中的持久化服务,因为所有的数据都是直接使用调用 Nacos 服务端直接创建,因此需要由 Nacos 保障数据在各个节点之间的强一致性,故而针对此类型的服务 数据,选择了强一致性共识算法来保障数据的一致性。

2、从配置管理来看

配置数据,是直接在 Nacos 服务端进行创建并进行管理的,必须保证大部分的节点都保存了此配置数据才能认为配置被成功保存了,否则就会丢失配置的变更,如果出现这种情况,问题是很严重 的,如果是发布重要配置变更出现了丢失变更动作的情况,那多半就要引起严重的现网故障了,因 此对于配置数据的管理,是必须要求集群中大部分的节点是强一致的,而这里的话只能使用强一致性共识算法。

Nacos 的一致性协议层

在早期的 Nacos 架构中,服务注册和配置管理一致性协议是分开的,没有下沉到 Nacos 的内核模 块作为通用能力演进,服务发现模块一致性协议的实现和服务注册发现模块的逻辑强耦合在一起。在当前的 Nacos 内核中,Nacos已经做到了将一致性协议的能力,完全下沉到了内核模块作为 Nacos 的核心能力,并且尽可能的提供了统一的抽象接口,使得上层的服务注册发现模块以及配置管理模块,不再需要耦合任何一致性语义,解耦抽象分层后,每个模块能快速演进,并且性能和可用性 都大幅提升。下面是当前的 Nacos架构:

Nacos当前的一致性架构

Nacos如何做到一致性协议下沉的

其实,一致性协议,就是用来保证数据一致的,而数据的产生,必然有一个写入的动作;同时还要能够读数据,并且保证读数据的动作以及得到的数据结果,并且能够得到一致性协议的保障。因此, 一致性协议最最基础的两个方法,就是写动作和读动作。

在 Nacos 中,任何使用一致性协议的,都只需要使用getData以及write方法即可。同时,一致性协议已经被抽象在了consistency的包中,Nacos对于AP、CP的一致性协议接口使用抽象都在里面,并且在实现具体的一致性协议时,采用了插件可插拔的形式,进一步将一致性协议具体实现逻辑和服务注册发现、配置管理两个模块达到解耦的目的。

虽然做了比较高度的 一致性协议抽象,服务模块以及配置模块却依然还是要在自己的代码模块中去显示的处理一致性协 议的读写请求逻辑,以及需要自己去实现一个对接一致性协议的存储。这其实是不好的,服务发现和服务配置模块应该专注于数据的使用和计算,而不是数据的存储和保障数据一致性,数据存储以及多节点一致的问题应该交由存储层来保证。为了尽可能让一致性协议只在内核模块中感知,Nacos 这里又做了另一份工作——数据存储抽象。

数据存储抽象主要是利用一致性协议实现一个存储。由于 Nacos 的服务模块存储,更多的都是根据单个或者多个唯一 key 去执行点查的操作,因此 Key-Value 类型的存储接口最适合不过。而 Key-Value 的存储接口定义好之后,其实就是这个KVStore的具体实现了。可以直接将KVStore的实现对接 Redis,也可以直接对接 DB ,或者直接根据 Nacos 内核模块的一致性协议,在此基础之上,实现一个内存或者持久化的分布式强(弱) 一致性 KV。通过功能边界将 Nacos 进程进一步分离为计算逻辑层和存储逻辑层,计算层和存储层之间的交互仅通过一层薄薄的数据操作胶水代码,这样就在单个 Nacos 进程里面实现了计算和存储二者逻辑的彻底分离。

Nacos 自研 Distro 协议

Distro 协议是 Nacos 社区自研的一种 AP 分布式协议,是面向临时实例设计的一种分布式协议, 其保证了在某些 Nacos 节点宕机后,整个临时实例处理系统依旧可以正常工作。作为一种有状态的中间件应用的内嵌协议,Distro 保证了各个 Nacos 节点对于海量注册请求的统一协调和存储。

设计思想

  • Nacos 每个节点是平等的都可以处理写请求,同时把新数据同步到其他节点。
  • 每个节点只负责部分数据,定时发送自己负责数据的校验值到其他节点来保持数据一致性。
  • 每个节点独立处理读请求,及时从本地发出响应。

具体实现介绍

数据初始化:新加入的 Distro 节点会进行全量的数据拉取。具体操作是轮训所有正在运行的 Distro 节点,向它们发送请求拉取全量数据。在全量拉取操作完成之后,Nacos 的每台机器上都维护了当前的所有注册上来的非持久化实例数据。

数据校验:在 Distro 集群启动之后,各台机器之间会定期的发送心跳。心跳信息主要为各个机器上的所有数据 的元信息。这 种数据校验会以心跳的形式进行,即每台机器在固定时间间隔会向其他机器发起一次数据校验请求。一旦在数据校验过程中,某台机器发现其他机器上的数据与本地数据不一致,则会发起一次全量拉 取请求,将数据补齐。

写请求:在一次客户端发起写操作的流程中,当注册非持久化的实例的写请求打到某台 Nacos 服务器时

  • 前置的 Filter 会拦截写请求,并根据请求中包含的 IP 和 port 信息计算其所属的 Distro 责任节点, 将该请求转发到所属的 Distro 责任节点上。
  • 责任节点上的 Controller 将写请求进行解析,并写入数据。
  • Distro 协议定期执行 Sync 任务,将本机所负责的所有的实例信息同步到其他节点上。

读请求:由于每台机器上都存放了全量数据,因此在每一次读操作中,Distro 机器会直接从本地拉取数据。 这种机制保证了 Distro 协议可以作为一种 AP 协议,对于读操作都进行及时的响应。在网络分区 的情况下,对于所有的读操作也能够正常返回;当网络恢复时,各个 Distro 节点会把各数据分片的数据进行合并恢复。

Nacos 通信通道

Nacos 长连接

Nacos的sdk-server间的配置一致性模型

sdk-server配置一致性

Nacos的sdk-server间的服务一致性模型

Nacos的sdk-server间服务一致性模型

寻址机制

对于集群模式,集群内的每个Nacos节点间都需要相互通信。因此这就带来一个问题,该以何种方式去管理集群内的Nacos成员节点信息,这就是Nacos内部的寻址机制。

无论是单机模式还是集群模式,寻址机制的根本需求就是要感知节点的变化情况,Nacos 基于此抽象出了一个 MemberLookup 接口

public interface MemberLookup { void start() throws NacosException; /** * 用于将 ServerMemberManager 注入到 MemberLookup 中,方便利用 ServerMemberManager 的存储、查询能力 */ void injectMemberManager(ServerMemberManager memberManager); /** * The addressing pattern finds cluster nodes. * 是一个事件接口,当 MemberL ookup 需要进行成员节点信息更新时, * 会将当前最新的成员节点列表信息通过该函数进行通知给 ServerMemberManager */ void afterLookup(Collection<Member> members); /** * Addressing mode closed. */ void destroy() throws NacosException; }

Nacos的内部寻址实现

单机寻址:

单机模式的寻址模式很简单,其实就是找到自己的 IP:PORT 组合信息,然后格式化为一个节点信息, 调用 afterLookup 然后将信息存储到 ServerMemberManager 中。

文件寻址:

192.168.16.101:8847 192.168.16.102 192.168.16.103

文件寻址模式是 Nacos 集群模式下的默认寻址实现。文件寻址模式很简单,其实就是每个 Nacos 节点都维护一个叫做cluster.conf的文件。该文件默认只需要填写每个成员节点的 IP 信息即可,端口会自动选择 Nacos 的默认端口8848, 如过说有特殊需求更改了 Nacos 的端口信息,则需要在该文件将该节点的完整网路地址信息补充完整(IP:PORT)。

当 Nacos 节点启动时,会读取该文件的内容,然后将文件内的 IP 解析为节点列表,调用 afterLookup 方法存入 ServerMemberManager 。如果发现集群扩缩容,那么就需要修改每个 Nacos 节点下的 cluster.conf 文件,然后 Nacos 内 部的文件变动监听中心会自动发现文件修改,重新读取文件内容、加载 IP 列表信息、更新新增的节点。但是,这种默认寻址模式有一个缺点——cluster.conf数据修改的运维成本较大!

地址服务器寻址(推荐)

该模式利用了一个简易的 web 服务器,用于管理cluster.conf文件的内容信息,这样,运维人员只需要管理这一份集群成员节点内容。而每个 Nacos 成员节点,只需要向这个 web 节点定时请求当前最新的集群成员节点列表信息即可。

集群节点自动扩缩容(未来)目前,Nacos 的集群节点管理,还都是属于人工操作,因此,未来期望能够基于寻址模式,实现集群节点自动管理的功能,能够实现新的节点上线时,只需要知道原有集群中的一个节点信息,就可以在一定时间内,顺利加入原有 Nacos 集群中;同时,也能够自行发现不存活的节点,自动将其从集群可用节点列表中剔除。这一块的逻辑实现,其实就类似 Consul 的 Gossip 协议。

服务发现模块

注册中心的设计原理

数据模型

注册中心的数据需要存储很多属性,比如核心的服务名称和它对应的 IP 信息,以及健康状态、权重、权限等。Zookeeper 没有针对服务发现设计数据模型,它的数据是以一种更加抽象的树形 K-V 组织的,因此理论上可以存储任何语义的数据。而 Eureka 或者 Consul 都是做到了实例级别的数据扩展,这可以满足大部分的场景,不过无法满足大规模和多环境的服务数据存储。Nacos 在经过内部多年生产经验后提炼出的数据模型,则是一种 服务-集群-实例 的三层模型。

另外一个需要考虑的是数据的隔离模型。Zookeeper、Consul 和 Eureka 在开源层面都没有很明确的针对服务隔离的模型。Nacos 提供了四层的数据隔离模型,企业(Company)->命名空间(Namespace)->服务分组 (Group)->服务名(Service)。企业对应用户账号。一个用户账号可以创建多个命名空间,每个命名空间对应一个客户端实例,这个命名空间对应的注册中心物理集群是可以根据规则进行路由的,这样可以让注册中心内部的升级和迁移对用户是无感知的。再往下是服务分组和服务名组成的二维服务标识,可以满足接口级别的服务隔离。

Nacos 1.0.0介绍的另外一个新特性是:临时实例和持久化实例。在定义上区分临时实例和持久化实例的关键是健康检查的方式。临时实例使用客户端上报模式,而持久化实例使用服务端反向探测模式。临时实例需要能够自动摘除不健康实例,而且无需持久化存储实例。Nacos2.0中我们将是否持久化的数据抽象至服务级别,且不再允许一个服务同时存在持久化实例和非持久化实例,实例的持久化属性继承自服务的持久化属性。

数据一致性

关于一致性协议,从协议层面上看,一致性的选型已经很长时间没有新的成员加入了。目前来看基本可以归为两家:一种是基于 Leader 的非对等部署的单点写一致性,一种是对等部署的多写一致性。当我们选用服务注册中心的时候,并没有一种协议能够覆盖所有场景,例如当注册的服务节点不会定时发送心跳到注册中心时,强一致协议看起来是唯一的选择,因为无法通过心跳来进行数据的补偿注册,第一次注册就必须保证数据不会丢失。而当客户端会定时发送心跳来汇报健康状态时,第一次的注册的成功率并不是非常关键(当然也很关键,只是相对来说我们容忍数据的少量写失败),因为后续还可以通过心跳再把数据补偿上来,此时 Paxos 协议的单点瓶颈就会不太划算了,这也是 Eureka 为什么不采用 Paxos 协议而采用自定义的 Renew 机制的原因。

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

负载均衡

负载均衡严格的来说,并不算是传统注册中心的功能。一般来说服务发现的完整流程应该是先从注册中心获取到服务的实例列表,然后再根据自身的需求,来选择其中的部分实例或者按照一定的流量分配机制来访问不同的服务提供者。但是在阿里内部,服务消费者往往并不关心所访问的服务提供者的负载均衡,而服务提供者,则非常关注自身被访问的流量的调配。

抛开负载均衡到底是在服务提供者实现还是在服务消费者实现,我们看到目前的负载均衡有基于权重、服务提供者负载、响应时间、标签等策略。其中 Ribbon 设计的客户端负载均衡机制,主要是选择合适现有的 IRule、ServerListFilter 等接口实现,或者自己继承这些接口,实现自己的过滤逻辑。这里 Ribbon 采用的是两步负载均衡,第一步是先过滤掉不会采用的服务提供者实例,第二步是在过滤后的服务提供者实例里,实施负载均衡策略。

基于标签的负载均衡策略可以做到非常灵活,使用基于标签的负载均衡器,目前可以实现同标签优先访问的流量调度策略,实际的应用场景中,可以用来实现服务的就近访问,当您的服务部署在多个地域时,这非常有用。但是标签本身需要单独的存储以及读写功能,不管是放在注册中心本身或者对接第三方的 CMDB。

健康检查

服务端健康检查最常见的方式是 TCP 端口探测和 HTTP 接口返回码探测。客户端健康检查主要关注客户端上报心跳 的方式、服务端摘除不健康客户端的机制。而服务端健康检查,则关注探测客户端的方式、灵敏度及设置客户端健康状态的机制。Nacos 既支持客户端的健康检查,也支持服务端的健康检查,同一个服务可以切换健康检查模式。Nacos 在开源版本中,服务实例注册的支撑量约为 100 万,服务的数量可以达到 10 万以上。

扩展性

从协议的层面上来说,Zookee per 使用的 ZAB 协议,由于是单点写,在集群扩展性上不具备优势。Eureka 在协议上来说理论上可以扩展到很大规模,因为都是点对点的数据同步,但是从我们对 Eureka 的运维经验来看, Eureka 集群在扩容之后,性能上有很大问题。Zookeeper 的单点写模式就会有断网恢复后的数据对账问题。Eure ka 的部署模式天然支持多机房容灾,因为 Eureka 采用的是纯临时实例的注册模式:不持久化、所有数据都可以通过客户端心跳上报进行补偿。临时实例和持久化实例都有它的应用场景,为了能够兼容这两种场景,Nacos 支持两种模式的部署,一种是和 Eureka 一样的 AP 协议的部署,这种模式只支持临时实例,可以完美替代当前的 Zookeeper、Eureka,并支持机房容灾。另一种是支持持久化实例的 CP 模式,这种情况下不支持双机房容灾。

注册中心服务数据模型

本节将较为详尽的展开介绍 Nacos 注册中心中的服务数据模型内容。主要会为读者详细介绍 Nacos2.0 版本中注册中心所涉及到的数据模型、各个数据模型的含义及各个数据模型的生命周期, 并介绍 Nacos2.0 版本和 Nacos1.0 版本中,服务数据模型的差异点。

服务(Service)和服务实例(Instance)

在服务发现领域中,服务指的是由应用程序提供的一个或一组软件功能的一种抽象概念。一个应用可能会提供多个服务。而服务实例(以下简称实例)是某个服务的具体提供能力的节点,一个实例仅从属于一个服务,而一个服务可以包含一个或多个实例。在 Nacos 中,服务的定义包括以下几个内容:

  • 命名空间(Namespace):Nacos 数据模型中最顶层、也是包含范围最广的概念,用于在类似环境或租户等需要强制隔离的场景中定义。Nacos 的服务也需要使用命名空间来进行隔离。
  • 分组(Group):Nacos 数据模型中次于命名空间的一种隔离概念,区别于命名空间的强制隔离属性,分组属于一个弱隔离概念,主要用于逻辑区分一些服务使用场景或不同应用的同名服务,最常用的情况主要是同一个服务的测试分组和生产分组,或者将应用名作为分组以防止不同应用提供的服务重名。
  • 服务名(Name):该服务实际的名字,一般用于描述该服务提供了某种功能或能力。

服务元数据

服务的元数据是进一步定义了 Nacos 中服务的细节属性和描述信息。主要包含:

  • 健康保护阈值(ProtectThreshold):为了防止因过多实例故障,导致所有流量全部流入剩余实例,继而造成流量压力将剩余实例被压垮形成的雪崩效应。应将健康保护阈值定义为一个0到1之间的浮点数。当域名健康实例数占总服务实例数的比例小于该值时,无论实例是否健康,都会将这个实例返回给客户端。这样做虽然损失了一部分流量,但是保证了集群中剩余健康实例能正常工作。
  • 实例选择器(Selector):用于在获取服务下的实例列表时,过滤和筛选实例。该选择器也被称为路由器,目前 Nacos 支持通过将实例的部分信息存储在外部元数据管理 CMDB 中,并在发现服务时使用 CMDB 中存储的元数据标签来进行筛选的能力。
  • 拓展数据(extendData):用于用户在注册实例时自定义扩展的元数据内容,形式为 K-V 。可以在服务中拓展服务的元数据信息,方便用户实现自己的自定义逻辑。

持久化属性

Nacos 提供两种类型的服务:持久化服务和非持久化服务,分别给类DNS 的基础的服务组件场景和上层实际业务服务场景使用。为了标示该服务是哪种类型的服务,需要在创建服务时选择服务的持久化属性。考虑到目前大多数使用动态服务发现的场景为非持久化服务的类型(如 Spring Cloud,Dubbo,Service Mesh 等),Nacos 将缺醒值设置为了非持久化服务。

在 Nacos2.0版本后,持久化属性的定义被抽象到服务中,一个服务只能被定义成持久化服务或非持久化服务,一旦定义完成,在服务生命周期结束之前,无法更改其持久化属性。持久化属性将会影响服务及实例的数据是否会被 Nacos 进行持久化存储,设置为持久化之后,实例将不会再被自动移除,需要使用者手动移除实例。

健康检查

在介绍 Nacos 的健康检查机制之前,我们先回顾一下 Nacos 服务有什么特点。Nacos 提供了两种服务类型供用户注册实例时选择,分为临时实例和永久实例。临时实例只是临时存在于注册中心中,会在服务下线或不可用时被注册中心剔除,临时实例会与注册中心保持心跳,注册中心会在一段时间没有收到来自客户端的心跳后会将实例设置为不健康,然后在一段时间后进行剔除。永久实例在被删除之前会永久的存在于注册中心,且有可能并不知道注册中心存在,不会主动向注册中心上报心跳,那么这个时候就需要注册中心主动进行探活。

临时实例的健康检查

在 Nacos 中,用户可以通过两种方式进行临时实例的注册,通过 Nacos 的 OpenAPI 进行服务注册或通过 Nacos 提供的 SDK 进行服务注册。OpenAPI 的注册方式实际是用户根据自身需求调用 Http 接口对服务进行注册,然后通过 Http 接口发送心跳到注册中心。在注册服务的同时会注册一个全局的客户端心跳检测的任务。在服务一段时间没有收到来自客户端的心跳后,该任务会将其标记为不健康,如果在间隔的时间内还未收到心跳,那么该任务会将其剔除。SDK 的注册方式实际是通过 RPC 与注册中心保持连接(Nacos 2.x 版本中,旧版的还是仍然通过 OpenAPI 的方式),客户端会定时的通过 RPC 连接向 Nacos 注册中心发送心跳,保持连接的存活。如果客户端和注册中心的连接断开,那么注册中心会主动剔除该 client 所注册的服务,达到下线的效果。同时 Nacos 注册中心还会在注册中心启动时,注册一个过期客户端清除的定时任务,用于删除那些健康状态超过一段时间的客户端。

从上面的特点我们可以发现,对于不同类型的使用方式,Nacos 对于健康检查的特点实际都是相同的,都是由客户端向注册中心发送心跳,注册中心会在连接断开或是心跳过期后将不健康的实例移除。

永久实例的健康检查

Nacos 中使用 SDK 对于永久实例的注册实际也是使用 OpenAPI 的方式进行注册,这样可以保证即使是客户端下线后也不会影响永久实例的健康检查。

对于永久实例的的监看检查,Nacos 采用的是注册中心探测机制,注册中心会在永久服务初始化时根据客户端选择的协议类型注册探活的定时任务。Nacos 现在内置提供了三种探测的协议,即 Http、TCP 以及 MySQL 。一般而言 Http 和 TCP 已经可以涵盖绝大多数的健康检查场景。 MySQL 主要用于特殊的业务场景,例如数据库的主备需要通过服务名对外提供访问,需要确定当前访问数据库是否为主库时,那么我们此时的健康检查接口,是一个检查数据库是否为主库的 MySQL命令。

Nacos 也是提供了对应的白名单配置,用户可以将服务配置到该白名单,那么 Nacos 会放弃对其进行健康检查,实例的健康状态也始终为用户传入的健康状态。

集群模式的健康检查

对于集群下的服务,Nacos 一个服务只会被 Nacos 集群中的一个注册中心所负责,其余节点的服务信息只是集群副本,用于订阅者在查询服务列表时,始终可以获取到全部的服务列表。临时实例只会对其被负责的注册中心节点发送心跳信息,注册中心服务节点会对其负责的永久实例进行健康探测,在获取到健康状态后由当前负责的注册中心节点将健康信息同步到集群中的其他的注册中心。

在 Nacos 中,服务的注册我们从注册方式维度实际可以分为两大类。第一类通过 SDK RPC 连接进行注册,客户端会和注册中心保持链接。第二类,通过 OpenAPI 进行 IP 和端口注册。

对于第一类,只需要和注册中心集群中的任意一台节点建立联系,那么由这个节点负责这个客户端就可以了。注册中心会在启动时注册一个全局的同步任务,用于将其当前负责的所有节点信息同步到集群中的其他节点,其他非负责的节点也会创建该客户端的信息,在非负责的节点上,连接类型的客户端,会有一个续约时间的概念,在收到其他节点的同步信息时,更新续约时间为当前时间,如果在集群中的其他节点在一段时间内没有收到不是自己的负责的节点的同步信息,那么认为此节点已经不健康,从而达到对不是自己负责的节点健康状态检查。

对于第二类,方式其实也基本和第一类一致,OpenAPI 注册的临时实例也是通过同步自身负责的节点到其他节点来更新其他节点的对应的临时实例的心跳时间,保证其他节点不会删除或者修改此实例的健康状态。对于永久实例,它会在被主动删除前一直存在于注册中心,只需要在负责的节点永久实例健康状态变更的时候通知到其余的节点即可。

配置管理模块

配置一致性模型

Nacos 配置管理一致性协议分为两个大部分,第一部分是 Server 间一致性协议,一个是 SDK 与 Server 的一致性协议,配置作为分布式系统中非强一致数据,在出现脑裂的时候可用性高于一致性,因此阿里配置中心是采用 AP 一致性协议。

Server 间的一致性协议

  • 有DB模式(主从架构)

一致性的核心是 Server 与 DB 保持数据一致性,从而保证 Server 数据一致;Server 之间都是对等的。数据写任何一个 Server,优先进行DB持久化,持久化成功后异步通知其他节点到数据库中拉取最新配置值,并且通知写入成功。

  • 无DB模式

Server 间采用 Raft 协议保证数据一致性,行业大部分产品采用此模式,因此不展开介绍。Nacos 提供此模式,是方便用户本机运行,降低对存储依赖。

SDK 与 Server 的一致性协议

SDK 与 Server 一致性协议的核心是通过 MD5值是否一致,如果不一致就拉取最新值。

Nacos 1.X 采用 Http 1.1短链接模拟长链接,每30s 发一个心跳,跟 Server 对比 SDK 配置 MD 5值是否跟 Server 保持一致,如果一致就 hold 住链接,如果有不一致配置,就把不一致的配置返回,然后 SDK 获取最新配置值。Nacos 2.x 相比上面30s 一次的长轮训,升级成长链接模式,配置变更,启动建立长链接,配置变更服务端推送变更配置列表,然后 SDK 拉取配置更新,因此通信效率大幅提升。

Nacos 高可用设计

全局高可用

Nacos 部署架构上是单 Region 封闭,Region 间独立,跨 Region 通过网关或者 Nacos-sync 完成服务互通。从而降低 Region 间网络故障风险。

同城容灾

Nacos 本身是采用 AP 的一致性模式,同 Region 多个可用区部署,任何一个可用区出问题,剩下部分继续工作。一般用两个可用区,不用三个是因为成本大幅提高

数据多级容灾

Nacos 持久化存储做了主备容灾,而且底层存储数据多副本高可用保障。 Nacos Server 有全量缓存数据,即使存储挂或者不可用,只影响写,核心的读服务不受影响。 Nacos SDK 有所需服务和配置缓存,Server 即使全挂,走本地缓存,保证核心业务调用不受影响。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 7:41:09

导师推荐9个AI论文写作软件,自考学生轻松搞定毕业论文!

导师推荐9个AI论文写作软件&#xff0c;自考学生轻松搞定毕业论文&#xff01; AI 工具如何让论文写作变得轻松高效 在自考学生群体中&#xff0c;毕业论文往往是一道难以逾越的难关。面对繁重的写作任务和时间压力&#xff0c;许多同学感到无从下手。而随着 AI 技术的不断进步…

作者头像 李华
网站建设 2026/2/23 2:51:03

西门子PLC变压器冷却控制系统(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

西门子PLC变压器冷却控制系统(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码S7-1200变压器冷却控制系统变压器冷却控制系统设计西门子S7-1200编程&#xff0c;wincc组态仿真 包括环境温湿度采集及冷却&#xff0c;油温采集及冷…

作者头像 李华
网站建设 2026/2/23 18:34:12

嫣然天使儿童医院区域影像如何分块导出为多张大图

李亚鹏嫣然天使儿童医院是由李亚鹏和王菲等人&#xff0c;于2012年7月1日发起创办的中国首家民办非营利性儿童综合医院。截至2026年&#xff0c;医院已累计完成超过1.1万台唇腭裂手术&#xff0c;其中约7000例为全额免费救助。现在&#xff0c;我们先以嫣然天使儿童医院卫星影像…

作者头像 李华
网站建设 2026/2/21 11:03:46

【Vibe Coding百图计划】用Python点燃一场永不落幕的新春烟花秀

文章目录 写在前面系列文章项目架构技术需求主要代码创作流程写在后面 写在前面 用Python点燃一场永不落幕的新春烟花秀 系列文章 序号文章目录直达链接炫酷系列1无法拒绝的表白界面https://want595.blog.csdn.net/article/details/1347448942满屏飘字表白代码https://want59…

作者头像 李华
网站建设 2026/2/18 7:10:24

引入了 Disruptor 后,系统性能大幅提升!

Disruptor 是一个很受欢迎的内存消息队列&#xff0c;它源于 LMAX 对并发、性能和非阻塞算法的研究。今天一起来学习一下这个消息队列。简介对于主流的分布式消息队列来说&#xff0c;一般会包含 Producer、Broker、Consumer、注册中心等模块。比如 RocketMQ 架构如下&#xff…

作者头像 李华