Nacos架构与原理深度分析
作者:mmseoamin日期:2023-12-25

目录

一、Nacos 生态

二、Nacos 优势

三、设计原则

1、架构图

 2、用户

3、业务层

4、 内核层

5、插件

四、配置(Configuration)

五、 配置资源模型

六、Nacos服务发现模块设计

1、数据模型

2、数据⼀致性

3、负载均衡

 4、健康检查

七、高可用设计


一、Nacos 生态

   Nacos 几乎支持所有主流语言, 其中 Java/Golang/Python 已经支持 Nacos 2.0 长链接协议, 能

最大限度发挥 Nacos 性能。 阿里微服务 DNS(Dubbo+Nacos+Spring-cloud-alibaba/Seata/

Sentinel) 最佳实践, 是 Java 微服务生态最佳解决方案; 除此之外, Nacos 也对微服务生态活跃

的技术做了无缝的支持, 如目前比较流行的 Envoy、 Dapr 等, 能让用户更加标准获取微服务能力。

生态仓库: https://github.com/nacos-group

二、Nacos 优势

易⽤: 简单的数据模型, 标准的 restfulAPI, 易用的控制台, 丰富的使用文档。

稳定: 99.9% 高可用, 脱胎于历经阿里巴巴 10 年生产验证的内部产品, 支持具有数百万服务的大

规模场景, 具备企业级 SLA 的开源产品。

实时: 数据变更毫秒级推送生效; 1w 级, SLA 承诺 1w 实例上下线 1s, 99.9% 推送完成; 10w

级, SLA 承诺 1w 实例上下线 3s, 99.9% 推送完成; 100w 级别, SLA 承诺 1w 实例上下线 9s

99.9% 推送完成。

规模: 十万级服务/配置, 百万级连接, 具备强大扩展性。

三、设计原则

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

    1、架构图

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

    Nacos架构与原理深度分析,第1张

     2、用户层

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

      3、业务层

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

        4、 内核层

        •  插件机制: 实现三个模块可分可合能力, 实现扩展点 SPI 机制, 用于扩展自己公司定制。
        •  事件机制: 实现异步化事件通知, SDK 数据变化异步通知等逻辑, 是 Nacos 高性能的关键部分。
        •  日志模块: 管理日志分类, 日志级别, 日志可移植性(尤其避免冲突) , 日志格式, 异常码+帮助文档。
        •  回调机制: SDK 通知数据, 通过统⼀的模式回调用户处理。 接口和数据结构需要具备可扩展性。
        • 寻址模式: 解决 Server IP 直连, 域名访问, Nameserver 寻址、 广播等多种寻址模式, 需要可扩展。
        •  推送通道: 解决 Server 与存储、 Server 间、 Server 与 SDK 间高效通信问题。
        • 容量管理: 管理每个租户, 分组下的容量, 防止存储被写爆, 影响服务可用性。
        • 流量管理: 按照租户, 分组等多个维度对请求频率, 长链接个数, 报文大小, 请求流控进行控制。
        • 缓存机制: 容灾目录, 本地缓存, Server 缓存机制, 是 Nacos 高可用的关键。
        • 启动模式: 按照单机模式, 配置模式, 服务模式, DNS 模式模式, 启动不同的模块。
        •  ⼀致性协议: 解决不同数据, 不同⼀致性要求情况下, 不同⼀致性要求, 是 Nacos 做到 AP 协议的关键。
        • 存储模块: 解决数据持久化、 非持久化存储, 解决数据分片问题。

          5、插件

          • Nameserver: 解决 Namespace 到 ClusterID 的路由问题, 解决用户环境与 Nacos 物理环境映射问题。
          • CMDB: 解决元数据存储, 与三方 CMDB 系统对接问题, 解决应用, 人, 资源关系。
          • Metrics: 暴露标准 Metrics 数据, 方便与三方监控系统打通。
          • Trace: 暴露标准 Trace, 方便与 SLA 系统打通, 日志白平化, 推送轨迹等能力, 并且可以和计量计费系统打通。
          • 接入管理: 相当于阿里云开通服务, 分配身份、 容量、 权限过程。
          • 用户管理: 解决用户管理, 登录, SSO 等问题。
          • 权限管理: 解决身份识别, 访问控制, 角色管理等问题

            四、配置(Configuration)

            配置管理 (Configuration Management)

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

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

            ⼀个具体的可配置的参数与其值域, 通常以 param-key = param-value 的形式存在。 例如我们常

            配置系统的日志输出级别(logLevel = INFO | WARN | ERROR) 就是⼀个配置项。
            配置集(Configuration Set)

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

            用于进行租户粒度的配置隔离。 不同的命名空间下, 可以存在相同的 Group 或 Data ID 的配置。

            Namespace 的常用场景之⼀是不同环境的配置的区分隔离, 例如开发测试环境和生产环境的资源

            (如数据库配置、 限流阈值、 降级开关) 隔离等。 如果在没有指定 Namespace 的情况下, 默认使用 public 命名空间。
            配置组(Group)

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

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

            Nacos 的客户端 SDK 会在本地生成配置的快照。 当客户端无法连接到 Nacos Server 时, 可以使

            用配置快照显示系统的整体容灾能力。 配置快照类似于 Git 中的本地 commit, 也类似于缓存, 会在适当的时机更新, 但是并没有缓存过期(expiration) 的概念

            Nacos架构与原理深度分析,第2张

            五、 配置资源模型

            Namespace 的设计就是用来进行资源隔离的, 我们在进行配置资源的时候可以从以下两个角度来

            看: 从单个租户的角度来看, 我们要配置多套环境的配置, 可以根据不同的环境来创建 Namespace 。比如开发环境、 测试环境、 线上环境, 我们就创建对应的 Namespace(dev、 test、 prod) ,Nacos 会自动生成对应的 Namespace Id 。 如果同⼀个环境内想配置相同的配置, 可以通过Group 来区分。 如下图所示:

            Nacos架构与原理深度分析,第3张

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

            Nacos架构与原理深度分析,第4张

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

             config_info 存储配置信息的主表, 里面包含 dataId、 groupId、 content、 tenantId、 encrypt

            edDataKey 等数据。

             config_info_beta 灰度测试的配置信息表, 存储的内容和 config_info 基本相似。 有⼀个 beta

            _ips 字段用于客户端请求配置时判断是否是灰度的 ip。

             config_tags_relation 配置的标签表, 在发布配置的时候如果指定了标签, 那么会把标签和配置

            的关联信息存储在该表中。

              his_config_info 配置的历史信息表, 在配置的发布、 更新、 删除等操作都会记录⼀条数据, 可

            以做多版本管理和快速回滚。

            六、Nacos服务发现模块设计

            1、数据模型

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

             Nacos 提供了四层的数据逻辑隔离模型, 用户账号对应的可能是⼀个企业或者独立的个体, 这个数据⼀般情况下不会透传到服务注册中心。 ⼀个用户账号可以新建多个命名空间, 每个命名空间对应⼀个客户端实例, 这个命名空间对应的注册中心物理集群是可以根据规则进行路由的, 这样可以让注册中心内部的升级和迁移对用户是无感知的, 同时可以根据用户的级别, 为用户提供不同服务级别的物理集群。 再往下是服务分组和服务名组成的二维服务标识, 可以满足接口级别的服务隔离

            2、数据⼀致性

            Nacos 因为要支持多种服务类型的注册, 并能够具有机房容灾、 集群扩展等必不可少的能力, 在

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


            3、负载均衡

            在 Nacos 0.7.0 版本中, 我们除了提供基于健康检查和权重的负载均衡方式外, 还新提供了基于第三方 CMDB 的标签负载均衡器, 具体可以参考 CMDB 功能介绍文章。 使用基于标签的负载均衡器,目前可以实现同标签优先访问的流量调度策略, 实际的应用场景中, 可以用来实现服务的就近访问,当您的服务部署在多个地域时, 这非常有用。 使用这个标签负载均衡器, 可以支持非常多的场景,这不是本文要详细介绍的。 虽然目前 Nacos 里支持的标签表达式并不丰富, 不过我们会逐步扩展它支持的语法。 除此以外, Nacos 定义了 Selector, 作为负载均衡的统⼀抽象。 

             
            4、健康检查

            Nacos 目前支持临时实例使用心跳上报方式维持活性, 发送心跳的周期默认是 5 秒, Nacos 服务端会在 15 秒没收到心跳后将实例设置为不健康, 在 30 秒没收到心跳时将这个临时实例摘除。

            Nacos 既支持客户端的健康检查, 也支持服务端的健康检查, 同⼀个服务可以切换健康检查模式。

            我们认为这种健康检查方式的多样性非常重要, 这样可以支持各种类型的服务, 让这些服务都可以使用到 Nacos 的负载均衡能力。 Nacos 下⼀步要做的是实现健康检查方式的用户扩展机制, 不管Nacos 架构 < 74是服务端探测还是客户端探测。 这样可以支持用户传入⼀条业务语义的请求, 然后由 Nacos 去执行, 做到健康检查的定制

            七、高可用设计

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

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

            同城容灾

            Nacos 本身是采用 AP 的⼀致性模式, 同 Region 多个可用区部署, 任何⼀个可用区出问题, 剩下部分继续工作。很多人问为什么不是三个可用区呢? 因为业务都部署三个可用区从理论上是可用性最好的, 但是成本会大幅增加, 因此⼀般公司只选择两个可用区。
            Nacos架构与原理深度分析,第6张

            欢迎来到Doker,欢迎点赞和评论!或者加微信进入技术群聊!