2026/3/1 21:51:15
网站建设
项目流程
能看各种网站的浏览器,wordpress 回复 楼中楼,在深圳注册公司需要什么资料,网站建设模板案例响应式总体设计
Nacos架构
整体架构分为 用户层、业务层、内核层和插件#xff0c;用户层主要解决用户使用的易用性问题#xff0c;业务层主要解决服务发现和配置管理的功能问题#xff0c;内核层解决分布式系统一致性、存储、高可用等核心问题#xff0c; 插件解决扩展性问题。…总体设计Nacos架构整体架构分为用户层、业务层、内核层和插件用户层主要解决用户使用的易用性问题业务层主要解决服务发现和配置管理的功能问题内核层解决分布式系统一致性、存储、高可用等核心问题 插件解决扩展性问题。用户层OpenAPI暴露标准Rest风格HTTP接口简单易用方便多语言集成。Console易用控制台做服务管理、配置管理等操作。SDK多语言 SDK目前几乎支持所有主流编程语言。AgentSidecar 模式运行通过标准 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 的常用场景之一是不同环境的配置的区分隔离例如开发测试环境和生产环境的资源 隔离也可以用于租户之间的隔离例如 zhangsanlisiwangwu 。如果在没有指定 Namespace 的情况下默认使用public命名空间。配置快照(Configuration Snapshot)Nacos 的客户端 SDK 会在本地生成配置的快照。当客户端无法连接到 Nacos Server 时可以使 用配置快照显示系统的整体容灾能力。配置快照类似于 Git 中的本地 commit也类似于缓存会 在适当的时机更新但是并没有缓存过期(expiration)的概念。基础模型Nacos 提供可视化的控制台可以对配置进行发布、更新、删除、灰度、版本管理等功能。SDK 可以提供发布配置、更新配置、监听配置等功能。SDK 通过 GRPC 长连接监听配置变更Server 端对比 Client 端配置的 MD5 和本地 MD5 是否相等不相等推送配置变更。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(CollectionMember 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 CloudDubboService 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 即使全挂走本地缓存保证核心业务调用不受影响。