天天看点

Nacos注册中心设计分析-AP模式一、数据模型二、数据存储三、线程模型四、典型场景五、版本 

AP模式下Nacos集群支持多写多读,即集群中的任一台服务器都能够处理更新服务实例(即注册和摘除实例)的请求,同时也能够处理查询服务实例列表的请求。当集群中的某一台服务器更新本机的服务实例数据之后,会通知集群中的其它服务器更新各自的服务实例数据。在这个过程当中,数据没有在集群中所有的服务器得到同步时,向不同的服务器发送查询请求,可能会得到不同的服务实例列表,但在整个过程中,Nacos集群是持续可用的,也就是舍弃了CAP中的C,保证了AP。

一、数据模型

Nacos中的服务注册数据被设计为五层结构,包括Namespace、Group、Service、Cluster、Instance。

一)隔离层

把Namespace、Group理解为隔离数据,例如,设定Namespace的取值为dev(开发环境)、test(测试环境),用于隔离不同环境;Group的取值设定为payment(支付)和nonpayment(非支付),用于对服务进行分组隔离。在服务实例启动的时候,从配置文件读取固定的Namespace、Group取值,达到不同环境,不同分组之间服务被隔离,不能相互发现并调用的目的。

二)核心层

把Service、Cluster、Instance理解为核心数据,Service是某个具体的服务,Cluster是能够提供该服务的集群,Instance是Cluster下的服务器实例。

二、数据存储

Nacos服务器在两个地方存储核心数据,这里称之为服务器数据存储和一致性数据存储。

其中,服务器数据存储用于响应API请求,一致性数据存储是Nacos实例注册数据实质存放的地方。

Nacos服务器在处理更新服务实例的请求时,会优先更新一致性数据存储的核心数据,然后再通过对一致性数据存储的监听机制,把核心数据同步到本机的服务器数据存储,同时通知订阅相关服务的客户端服务注册数据的变化。

Nacos服务端在更新本机的一致性数据存储之后,会通过API把核心数据同步到集群中的其它节点(AP模式使用接口PUT /nacos/v1/ns/instance/distro/datum),其它节点通过对本身一致性数据存储的监听机制,更新本机的服务器数据存储,同时通知订阅相关服务的客户端服务注册数据的变化,达到最终一致。

一)服务器数据存储

存放于类ServiceManager的内部对象Map<String, Map<String, Service>> serviceMap,这是一个两层Map的嵌套结构,第一层的Key是Namesapce名称,第二层的Key是Group名称和Service名称的组合,第二层的Value是Service的对象。Service内部对象Map<String, Cluster> clusterMap,记录了提供该Service的集群;Cluster内部包含对象Set<Instance> ephemeralInstances,为该集群下AP模式的服务实例。

二)一致性数据存储

存放于类DistroConsistencyServiceImpl的内部对象DataStore dataStore;DataStore中包含对象Map<String, Datum> dataMap,该Map的Key是Namcesapce、Group、Service的组合,Datum包含服务实例列表,即该Map存放一个Service的所有实例。

三、线程模型

一)Tomcat工作线程

处理客户端请求,完成API调用

二)服务实例心跳检测线程

Nacos的AP模式中,服务器对每个Service启动一个健康检查线程,Instance需要主动通过API发送心跳到服务端,服务端记录收到心跳的最后时刻,然后服务实例心跳检测线程检测当前时间和上一次收到心跳时间的间隔,根据间隔长短决定是否摘除Instance,如果需要摘除,则通知到订阅服务的客户端,并调用本机接口delete /nacos/v1/ns/instance删除实例

三)服务变更通知控制线程

当一致性数据存储中的实例数据发生变化(如新增或删除Instance等)时,把数据同步到服务器数据存储,并启动服务变更通知执行线程

四) 数据同步任务调度线程

当实例数据发生变化时,对Nacos集群中的的每个服务器,分别添加一个数据同步任务,由数据同步任务执行线程执行

五) 服务变更通知执行线程

把Service下Cluster或Instance的增减数据,循环发送给各个订阅者

六) 数据同步任务执行线程

当实例数据发生变化(如新增或删除Service、Cluster或Instance等)时,该线程通过PUT /nacos/v1/ns/instance/distro/datum接口把数据变化同步到集群中其它服务器

四、典型场景

一)服务实例注册(POST /nacos/v1/ns/instance)

1. 启动对于Service的服务实例心跳检测线程(Tomcat工作线程)

2. 把实例数据写入一致性数据存储,启动服务变更通知控制线程(Tomcat工作线程)

3. 启动数据同步任务调度线程(Tomcat工作线程)

4. 同步实例数据到服务器数据存储,并启动服务变更通知执行线程(服务变更通知控制线程)

5. 通过UDP数据包,循环把服务provider变更数据通知各个consumer(服务变更通知执行线程)

6. 针对Nacos集群中的每台服务器,分别启动一个数据同步任务执行线程(数据同步任务调度线程)

7. 通过PUT /nacos/v1/ns/distro/datum接口同步到集群中其它服务器(数据同步任务执行线程)

二)服务实例摘除(DELETE /nacos/v1/ns/instance)

1. 把实例数据从一致性数据存储中移除,通过一致性数据存储数据变更的监听,启动服务变更通知控制线程(Tomcat工作线程)

2. 把实例数据从服务器数据存储中移除,并启动服务变更通知执行线程(服务变更通知控制线程)

3. 通过UDP数据包,循环把服务provider变更数据通知各个consumer(服务变更通知执行线程)

三)服务实例同步(PUT /nacos/v1/ns/instance/distro/datum)

1. 把实例数据同步到一致性数据存储,通过一致性数据存储数据变更的监听,启动服务变更通知控制线程(Tomcat工作线程)

2. 把实例数据同步到服务器数据存储,并启动服务变更通知执行线程(服务变更通知控制线程)

3. 通过UDP数据包,循环把服务provider变更数据通知各个consumer(服务变更通知执行线程)

四)服务实例获取(PUT /nacos/v1/ns/instance/list)

1. 查询服务实例列表并返回(Tomcat工作线程)

2. 调用PushService.addClient,把客户端信息加入订阅(服务变更通知控制线程)

五、版本 

本文基于Nacos的1.2.0版本