Nacos是什么?
Dynamic Naming and Configuration Service:动态命名和配置服务
阿里开源的一个易于使用的平台,专为动态服务发现、配置和管理而设计。
nacos是以服务为中心的现代应用架构,“服务”是nacos世界中的一等公民。nacos几乎支持所有主流类型的“服务”的发现、配置和管理:
Kubernetes Service、gRPC & Dubbo RPC Service、Spring Cloud RESTful Service
Nacos提供四大功能:
- 服务发现和服务状况检查
Nacos使服务可以轻松注册自己,并通过DNS或HTTP接口发现其他服务。Nacos还提供实时服务运 行状况检查,以防止向不健康的主机或服务实例发送请求。
- 动态配置管理
动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在配置 更新时重新部署应用程序和服务的必要性,这使得配置更改更加高效和灵活。
- 动态DNS服务
Nacos支持加权路由,使您在数据中心的生产环境中更容易实现中层负载平衡、灵活的路由策略、流量控制和简单的DNS分辨率服务。它帮助您轻松实现基于DNS的服务发现,并防止应用程序与供应商特定的服务发现API耦合。
- 服务和元数据管理
Nacos提供了一个易于使用的服务仪表板,可帮助您管理服务元数据、配置、kubernetes DNS、服务运行状况和指标统计。
注册中心+配置中心(eureka + apollo)
逻辑架构
整体架构分为用户层、业务层、内核层和插件:
- 用户层主要解决用户使用的易用性问题
- 业务层主要解决服务发现和配置管理的功能问题
- 内核层解决分布式系统⼀致性、存储、高可用等核心问题,
- 插件解决扩展性问题

用户层
- 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 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间(public),分组默认是 DEFAULT_GROUP。
Namespace
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之⼀是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源 (如数据库配置、限流阈值、降级开关)隔离等。如果在没有指定 Namespace 的情况下,默认使用 public 命名空间。
Group
Nacos 中的⼀组配置集,是配置的维度之⼀。通过⼀个有意义的字符串(如 ABTest 中的实验组、 对照组)对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建⼀个配置时, 如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置项,如 database_url 配置和MQ_Topic 配置。
Data ID
Nacos 中的某个配置集的 ID。配置集 ID 是划分配置的维度之⼀。Data ID 通常用于划分系统的配置集。⼀个系统或者应用可以包含多个配置集,每个配置集都可以被⼀个有意义的名称标识。Data ID 尽量保障全局唯⼀,可以参考 Nacos Spring Cloud 中的命名规则:${prefix}-${spring.profiles.active}-${file-extension}
Service
Nacos中的一等公民,可以理解为一般意义上的微服务
配置中心
基本模型

资源隔离模型
Namespace 的设计就是用来进行资源隔离的,我们在进行配置资源的时候可以从以下两个角度来看:
1.从单个租户的角度来看,我们要配置多套环境的配置,可以根据不同的环境来创建 Namespace。比如开发环境、测试环境、线上环境,我们就创建对应的 Namespace(dev、test、prod),Nacos 会自动生成对应的 Namespace Id 。如果同⼀个环境内想配置相同的配置,可以通过 Group 来区分。如下图所示:

2.从多个租户的角度来看,每个租户都可以有自己的命名空间。我们可以为每个用户创建⼀个命名空间,并给用户分配对应的权限,比如多个租户(zhangsan、lisi、wangwu),每个租户都想有⼀套自己的多环境配置,也就是每个租户都想配置多套环境。那么可以给每个租户创建⼀个 Namespace(zhangsan、lisi、wangwu)。同样会生成对应的 Namespace Id。然后使用 Group 来区分不同环境的配置。如下图所示:

配置一致性模型
客户端与Server的一致性协议
客户端与Server一致性协议的核心是通过对比 MD5 值是否一致,如果不一致就拉取最新值。 
注册中心
服务发现是一个古老的话题,当应用脱离单机到集群,服务发现就诞生了。
在最初的架构选型中, DNS+LVS+Nginx 基本可以满足所有的 RESTful 服务的发现,此时服务的 IP 列表通常配置在nginx或者 LVS。后来出现了 RPC 服务,服务的上下线更加频繁,人们开始寻求⼀种能够支持动态上下线并且推送 IP 列表变化的注册中心产品。
Zookeeper + Dubbo、Eureka/Consul + SpringCloud。
经典原理:

服务分级模型:

服务
定义:
在 Nacos 中,服务的定义包括以下几个内容:
- 命名空间(Namespace):Nacos 数据模型中最顶层、也是包含范围最广的概念,用于在类似 环境或租户等需要强制隔离的场景中定义。Nacos 的服务也需要使用命名空间来进行隔离。
- 分组(Group):Nacos 数据模型中次于命名空间的⼀种隔离概念,区别于命名空间的强制隔离属性,分组属于⼀个弱隔离概念,主要用于逻辑区分⼀些服务使用场景或不同应用的同名服务, 最常用的情况主要是同⼀个服务的测试分组和生产分组、或者将应用名作为分组以防止不同应用 提供的服务重名。
- 服务名(Name):该服务实际的名字,⼀般用于描述该服务提供了某种功能或能力。
元数据:
服务的定义只是为服务设置了⼀些基本的信息,用于描述服务以及方便快速的找到服务,而服务的元数据是进⼀步定义了 Nacos 中服务的细节属性和描述信息。主要包含:
- 健康保护阈值(ProtectThreshold):为了防止因过多实例故障,导致所有流量全部流入剩余实例,继而造成流量压力将剩余实例被压垮形成的雪崩效应。应将健康保护阈值定义为⼀个 0 到 1 之间的浮点数。当域名健康实例数占总服务实例数的比例小于该值时,无论实例是否健康,都会将这个实例返回给客户端。这样做虽然损失了⼀部分流量,但是保证了集群中剩余健康实例能正常工作。
- 实例选择器(Selector):用于在获取服务下的实例列表时,过滤和筛选实例。该选择器也被称 为路由器,目前 Nacos 支持通过将实例的部分信息存储在外部元数据管理 CMDB 中,并在发现 服务时使用 CMDB 中存储的元数据标签来进行筛选的能力。
- 拓展数据(extendData):用于用户在注册实例时自定义扩展的元数
Nacos推荐使用由运行环境作为命名空间Namespace、应用名作为分组Group和服务功能作为服务名Name的组合来确保该服 务的天然唯⼀性,当然使用者可以忽略命名空间和分组,仅使用服务名作为服务唯⼀标示,这就需 要使用者在定义服务名时额外增加自己的规则来确保在使用中能够唯⼀定位到该服务而不会发现到 错误的服务上。
集群
定义:
集群是Nacos中⼀组服务实例的⼀个逻辑抽象的概念,它介于服务和实例之间,是⼀部分服务属性的下沉和实例属性的抽象。
元数据:
- 健康检查类型(HealthCheckType):使用哪种类型的健康检查方式,目前支持:TCP,HTTP, MySQL;设置为 NONE 可以关闭健康检查。
- 健康检查端口(HealthCheckPort):设置用于健康检查的端口。
- 是否使用实例端口进行健康检查(UseInstancePort):如果使用实例端口进行健康检查,将会 使用实例定义中的网络端口进行健康检查,而不再使用上述设置的健康检查端口进行。
- 拓展数据(extendData):用于用户自定义扩展的元数据内容,形式为 K-V 。可以自定义扩展该集群的元数据信息,方便用户实现自己的自定义逻辑和标示该集群。
实例
定义:
由于服务实例是具体提供服务的节点,因此 Nacos 在设计实例的定义时,主要需要存储该实例的 ⼀些网络相关的基础信息,主要包含以下内容:
- 网络 IP 地址:该实例的 IP 地址,在 Nacos2.0 版本后支持设置为域名。
- 网络端口:该实例的端口信息。
- 健康状态(Healthy):用于表示该实例是否为健康状态,会在Nacos中通过健康检查的手段进行维护。
- 集群(Cluster):用于标示该实例归属于哪个逻辑集群。
- 拓展数据(extendData):用于用户自定义扩展的元数据内容,形式为 K-V。可以在实例中拓展该实例的元数据信息,方便用户实现自己的自定义逻辑和标示该实例。
元数据:
和服务元数据不同,实例的元数据主要作用于实例运维相关的数据信息。主要包含:
- 权重(Weight):实例级别的配置。权重为浮点数,范围为0-10000。权重越大,分配给该实例的流量越大。
- 上线状态(Enabled):标记该实例是否接受流量,优先级大于权重和健康状态。用于运维人员在不变动实例本身的情况下,快速地手动将某个实例从服务中移除。
- 拓展数据(extendData):不同于实例定义中的拓展数据,这个拓展数据是给予运维人员在不变动实例本身的情况下,快速地修改和新增实例的扩展数据,从而达到运维实例的作用。
注册和订阅:
注册:
订阅:
Nacos通过这两种手段,既保证了实时性,又保证了数据更新不会漏掉
一致性协议
支持AP(Distro)和CP(Raft)
Distro 协议是 Nacos 社区自研的⼀种 AP 分布式协议,是面向临时实例设计的⼀种分布式协议, 其保证了在某些 Nacos 节点宕机后,整个临时实例处理系统依旧可以正常工作。作为⼀种有状态 的中间件应用的内嵌协议,Distro 保证了各个 Nacos 节点对于海量注册请求的统⼀协调和存储。
Distro 协议的主要设计思想如下:
- Nacos 每个节点是平等的都可以处理写请求,同时把新数据同步到其他节点。
- 每个节点只负责部分数据,定时发送自己负责数据的校验值到其他节点来保持数据⼀致性。
- 每个节点独立处理读请求,及时从本地发出响应。
数据初始化
新加入的Distro节点会进行全量数据拉取。具体操作是轮询所有的Distro节点,通过向其他的机器发送请求拉取全量数据。
在全量拉取操作完成之后,Nacos 的每台机器上都维护了当前的所有注册上来的非持久化实例数据。
数据校验
在 Distro 集群启动之后,各台机器之间会定期的发送心跳。心跳信息主要为各个机器上的所有数据的元信息(之所以使用元信息,是因为需要保证网络中数据传输的量级维持在⼀个较低水平)。这种数据校验会以心跳的形式进行,即每台机器在固定时间间隔会向其他机器发起⼀次数据校验请求。
⼀旦在数据校验过程中,某台机器发现其他机器上的数据与本地数据不⼀致,则会发起⼀次全量拉 取请求,将数据补齐。
写操作
整个步骤包括几个部分(图中从上到下顺序):
- 前置的 Filter 拦截请求,并根据请求中包含的 IP 和 port 信息计算其所属的 Distro 责任节点,并将该请求转发到所属的 Distro 责任节点上。
- 责任节点上的 Controller 将写请求进行解析。
- Distro协议定期执行Sync任务,将本机所负责的所有的实例信息同步到其他节点上。
读操作
由于每台机器上都存放了全量数据,因此在每⼀次读操作中,Distro 机器会直接从本地拉取数据。 快速响应。
总结
Distro 协议是 Nacos 对于临时实例数据开发的⼀致性协议。其数据存储在缓存中,并且会在启动 时进行全量数据同步,并定期进行数据校验。
在 Distro 协议的设计思想下,每个 Distro 节点都可以接收到读写请求。所有的 Distro 协议的请 求场景主要分为三种情况:
1. 当该节点接收到属于该节点负责的实例的写请求时,直接写入。
2. 当该节点接收到不属于该节点负责的实例的写请求时,将在集群内部路由,转发给对应的节点, 从而完成读写。
3. 当该节点接收到任何读请求时,都直接在本机查询并返回(因为所有实例都被同步到了每台机 器上)。
这种机制保证了Distro协议可以作为⼀种AP协议,对于读操作都进行及时的响应。在网络分区的情况下,对于所有的读操作也能够正常返回;当网络恢复时,各个 Distro 节点会把各数据分片的数据进行合并恢复。
