一、介绍

1、背景

目前java主流常用微服务框架有Dubbo和SpringCloud,bubbo在国内很火,但是在2014年的时候因为不知名原因停更了。随后Spring在2016年的时候发布了SpringCloud。随后将netflix公司开源的组件集成了进来,诞生了SpringCloud-netflix版,然后由于netflix不在开发,进入维护模式后,在2020年发布了alibaba版本,nacos就产生于SpringCloud (alibaba)版本提供的组件中。

2、简介

Nacos(Dynamic Naming and Configuration Service)是构建以 “服务” 为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。致力于服务发现、配置和管理,且提供了一组简单易用的特性集。让微服务的发现、管理、共享、组合更加容易。

二、版本对比

CAP原则

  • consistency:数据一致性
  • availability:高可用性
  • partition tolerance:分区容错性

分布式架构只能满足x其中两种,不可能全部都满足

  • AC:单点集群,满足一致性,可用性,可扩展性不强
  • CP:保证数据一致性。在整个系统中保证数据时刻一致,强一致性,一旦数据不一致就会出现提示:用户系统异常
  • AP: 保证高可用,即保证某个服务故障仍然可以正常访问,牺牲了数据的一致性。一旦网络或者服务恢复就会进行数据同步保证数据最终一致性。

注册中心:特性更加适合AP,基于内存,保证高可用所以在Nacos中使用Distro协议;

配置中心:特性需要保证各节点配置是同步的,基于存储设备,所以使用的JRaft协议;

1、AP与CP结合

Nacos 1.x版本架构

Nacos 2.x版本架构

在新的 Nacos 架构中,已经完成了将⼀致性协议从原先的服务注册发现模块下沉到了 内核模块当中,并且尽可能的提供了统⼀的抽象接口,使得上层的服务注册发现模块以及配置管理模块,不再需要耦合任何⼀致性语义,解耦抽象分层后,每个模块能快速演进,并且性能和可用性 都大幅提升

2、长连接代替短连接

长连接

优点:可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户端适合使用长连接。

缺点:client端一般不会主动关闭连接,当client与server之间的连接一直不关闭,随着客户端连接越来越多,server会保持过多连

接。server端需要采取一些策略来控制

使用场景:长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。

短连接

优点:对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。

缺点:客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。需要频繁的建立连接

使用场景:WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接

Nacos 1.X

Nacos 1.X 采用 Http 1.1 短连接模拟长连接,每 30s 发⼀个心跳跟 Server 对比 SDK 配置 MD 5 值是否跟 Server 保持⼀致,如果⼀致就 hold 住链接,如果有不⼀致配置,就把不⼀致的配置 返回,然后 SDK 获取最新配置值。

Nacos 2.X

Nacos 2.x 相比上面 30s ⼀次的长轮训,升级成长连接模式,配置变更,启动建立长连接,配置变更服务端推送变更配置列表,然后SDK 拉取配置更新,因此通信效率大幅提升。

3、服务架构

Nacos 1.X 版本

存在的问题

1、心跳数量多,导致 TPS 居高不下

通过心跳续约,当服务规模上升时,特别是类似 Dubbo 的接口级服务较多时,心跳及配置元数据的轮询数量众多,导致集群 TPS 很

高,系统资源高度空耗

2、通过心跳续约感知服务变化,时延长

心跳续约需要达到超时时间才会移除并通知订阅者,默认为 15s,时延较长,时效性差。若改短超时时间,当网络抖动时,会频繁触

发变更推送,对客户端服务端都有更大损耗

3、UDP 推送不可靠,导致 QPS 居高不下

由于 UDP 不可靠,因此客户端则需要每隔一段时间进行对账查询,保证客户端缓存的服务列表的状态正确,当订阅客户端规模上升

时,集群 QPS 很高,但大多数服务列表其实不会频繁改变,造成无效查询,从而存在资源空耗

4、基于 HTTP 短连接模型,TIME_WAIT 状态连接过多

HTTP 短连接模型,每次客户端请求都会创建和销毁 TCP 链接,TCP 协议销毁的链接状态是 WAIT_TIME,完全释放还需要一定时

间,当 TPS 和 QPS 较高时,服务端和客户端可能有大量的 WAIT_TIME 状态链接,从而会导致连接超时

5、配置模块的 30 秒长轮询引起的频繁 GC

配置模块使用 HTTP 短连接阻塞模型来模拟长连接通信,但是由于并非真实的长连接模型,因此每 30 秒需要进行一次请求和数据的

上下文切换,每一次切换都有引起造成一次内存浪费,从而导致服务端频繁 GC

Nacos 2.X 版本

Nacos 2.X 在 1.X 的架构基础上 新增了对长连接模型的支持,同时保留对旧客户端和 openAPI 的核心功能支持。通信层通过 gRPC 和 Rsocket 实现了长连接 RPC 调用和推送能力。

1、客户端不再需要定时发送实例心跳,只需要有一个维持连接可用 keepalive 消息即可。重复 TPS 可以大幅降低。
2、TCP 连接断开可以被快速感知到,提升反应速度。
3、长连接的流式推送,比 UDP 更加可靠;nio 的机制具有更高的吞吐量,而且由于可靠推送,可以加长客户端用于对账服务列表的时间,甚至删除相关的请求。

重复的无效 QPS 可以大幅降低。
4、长连接避免频繁连接开销,可以大幅缓解 TIME_ WAIT 问题。
5、真实的长连接,解决配置模块 GC 问题。
6、更细粒度的同步内容,减少服务节点间的通信压力。

4、通信协议

功能/版本

1.x distro

2.x distro

1.x raft

2.x raft

注册/注销

http

grpc

grpc

http

订阅

http

grpc

grpc

grpc

心跳/健康检查

http

TCP

TCP

TCP/http/mysql

推送

udp

grpc

grpc

grpc

集群间数据同步

http/distro

grpc/distro

grpc/distro

jraft

5、同步协议

临时实例

  • 临时实例:靠client的心跳或连接保活,当不存活时,直接下线实例;适用于主动注册的服务
  • 永久实例:注册后不用保活,靠服务端健康检查来判断实例是否健康,不健康实例也不用下线;适用于ip不常变化的场景

在Nacos中他们的主要区别如下:

emphemral

true

false

名称

临时实例

永久实例

CAP

AP

CP

一致性协议

distro

raft

是否持久化

健康检查方式

心跳/连接

服务端检查(TCP、HTTP、MYSQL)

1、Distro协议

概念

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

设计思想

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

实现原理

1、数据初始化

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

2、数据校验

在Distro集群启动之后,各台机器之间会定期的发送心跳进行数据校验。如果某台机器校验发现与其他机器数据不一致,则会进行全量拉去请求将数据补齐。

3、写操作

当注册非持久化的实例的写请求打到某台Nacos服务器时,首先被Filter拦截,根据请求的IP端口信息转发到对应的Distro责任节点上处理请求。Distro协议还会定期执行Sync任务,将本机所负责的所有的实例信息同步到其他节点上。

4、读操作

读操作,由于每台机器上都存放了全量数据,因此在每⼀次读操作中,Distro机器会直接从本地拉取数据,快速响应

小结

这种机制保证了 Distro 协议可以作为⼀种 AP 协议,对于读操作都进行及时的响应。在网络分区 的情况下,对于所有的读操作也能够正常返回;当网络恢复时,各个 Distro 节点会把各数据分片的 数据进行合并恢复。

2、raft

6、推送机制代替轮询机制

推送机制:

客户端,通过客户端来选择可获节点,比如它第⼀次拉取的是⼀个正常节点,这个正常节点就会 跟它维护⼀个订阅关系,后面有变化就会有⼀个相应的实地变化推送给我。如果当前节点挂掉,他会通过重连, 在节点列表上,连上⼀个正常的节点。这时候会有新的 DNS 关系出现。

SDK ,在服务端寻找可获节点。服务端每个节点之间,会进行⼀个可活的探 测,选择其中⼀个可活节点用户维护这个订阅关系。当这个节点出现问题,连接断开后,SDK 重新发送订阅请求,服务端会再次选择另外⼀个可活的节点来维护这个订阅关系。这就保证整了推送过 程不会因为某个节点挂掉而没有推送

推送的效率方面,主要是用 UDP 的方式。

7、数据模型

1 – 服务

概念:

服务指的是由应用程序提供的⼀个或⼀组软件功能的⼀种抽象概念(例如登陆或支付)。它和应用有所不同,应用的范围更广,和服务属于包含关系,即⼀个应用可 能会提供多个服务。为了能够更细粒度地区分和控制服务,Nacos 选择服务作为注册中心的最基本 概念。

定义服务

  • 命名空间(Namespace)
  • 分组(Group)
  • 服务名(Name)

服务元数据

  • 健康保护阈值(ProtectThreshold)
  • 实例选择器(Selector)
  • 拓展数据(extendData)

2 – 服务实例

概念:

服务实例是某个服务的具体提供能力的节点,⼀个实例仅从属于⼀个服务,而⼀个服务可以包含⼀个或多个实例。在许多场景下,实例又被称为服务提供者(Provider),而使用该服务的实例被称为服务消费者(Consumer)

定义实例

  • 网络 IP 地址:该实例的 IP 地址,在 Nacos2.0 版本后支持设置为域名。
  • 网络端口:该实例的端口信息
  • 健康状态(Healthy)
  • 集群(Cluster)
  • 拓展数据(extendData)

实例元数据

  • 权重(Weight):实例级别的配置。权重为浮点数,范围为 0-10000。权重越大,分配给该实例 的流量越大
  • 上线状态(Enabled):标记该实例是否接受流量,优先级大于权重和健康状态。用于运维人员 在不变动实例本身的情况下,快速地手动将某个实例从服务中移除
  • 拓展数据(extendData)

3 – 小结

1、定义实例的网络ip地址支持域名

2、 Nacos2.0 版本中,实例数据被拆分为实例定义实例元数据

原因如下:

  • 实例数据使用场景不同
  • 运维操作需要保证操作的原子性,不能够因为外部环境的影响 而导致操作被重置

3、Nacos2.0 版本中定义实例的这部分数据,会受到持久化属性的的影响,而实例元数据部分,会默认进行持久化,在对应实例删除后保

存一段时间。

三、问题记录

1、dubbbo 发布元数据失败

原因是nacos有安全验证,需要设置密码

4、拓展

1、ReferenceConfig

缓存ReferenceConfig

在Dubbo 中使用ReferenceConfig 实例很重,因为封装了与注册中心的连接以及与提供者的连接,需要缓存。否则重复生成 ReferenceConfig 可能造成性能问题并且会有内存和连接泄漏。在 API 方式编程时,容易忽略此问题。2.4.0 版本开始, dubbo 提供了简单的工具类 ReferenceConfigCache用于缓存 ReferenceConfig 实例。

ReferenceConfig reference = new ReferenceConfig();reference.setInterface(XxxService.class);reference.setVersion("1.0.0");......ReferenceConfigCache cache = ReferenceConfigCache.getCache();// cache.get方法中会缓存 Reference对象,并且调用ReferenceConfig.get方法启动ReferenceConfigXxxService xxxService = cache.get(reference);// Cache会持有ReferenceConfig,不要在外部再调用ReferenceConfig的destroy方法,导致Cache内的ReferenceConfig失效!// 使用xxxService对象xxxService.sayHello();

自定义key

ReferenceConfigCache 把相同服务 Group、接口、版本的 ReferenceConfig 认为是相同,缓存一份。即以服务 Group、接口、版本为缓存的 Key。在 ReferenceConfigCache.getCache 时,传一个 KeyGenerator。可以自定义key。

KeyGenerator keyGenerator = new ...ReferenceConfigCache cache = ReferenceConfigCache.getCache(keyGenerator );

2、dubbo的service改为dubboService

5、参考文献

nacos官网:什么是 Nacos

nacos版本更新大纲:Dubbo生态-Nacos三大使用建议,公开 Nacos3.0 规划图

nacos架构&原理:文件下载-阿里云开发者社区

nacos架构设计新模型:支持gRPC长链接,深度解读Nacos2.0架构设计及新模型