Nacos的服务注册表结构是怎样的
回答
Nacos采用了数据分级存储模型,最外层是 Namespace,用来隔离环境。然后是Group,用来对服务分组。接下来就是服务(Service)了,一个服务包含多个实例,但是可能处于不同的机房,因此Service下有多个集群(Cluster),Cluster下是不同的实例(Instance)。
对应到Java代码中,Nacos采用了多层的Map结构来表示。即Map<String, Map<String, Service>>, 其中最外层Map的key就是namespaceid,值是一个Map。这个Map也就是内层Map的key是group拼接serviceName,值是Service对象。Service对象内部又是一个Map,key是集群的名称,值是Cluster对象。而Cluster对象内部维护了一个Instance的Set集合
如图:
源码分析
首先打开nacos官网,打开Open API指南:https://nacos.io/zh-cn/docs/open-api.html
访问注册实例
可以看到一个请求的url,我们顺着这个url去找源码:
/nacos/v2/ns/instance
nacos是一个控制端模块:
所以我们要跟入到naming这个模块看下。可以发现controllers里面有大量的控制器,可以顺着url找到一个Instance有关的,就可以发现就是这个类,起到了服务注册的作用:
而且它还是一个post请求,找到postmapping就能找到它的具体哪个接口了:
这就是服务注册的入口。
跟着这个register源码。首先它会从request里面获取一些信息,比如namespaceId,接着获取服务名:serviceName,而且要对这个服务名称做格式校验checkServiceNameFormat,然后再将request解析成一个服务实例对象Instance
这个Instance又继承了com.alibaba.nacos.api.naming.pojo.Instance这个对象,跟进去:
会发现它的一些服务的属性,比如ip、端口、实例Id等等都是通过这个Instance进行封装的。
接下来通过serviceManager也就是服务管理器调用服务注册实例方法registerInstance,在这个服务管理器最上面有个Map(serviceMap)就是来维护整个nacos注册表的。
我们跟踪它内部的这个map的service再看看:
发现它里面还维护了一个Map,这个就是service集群Map,这个Map的key即使集群的名称,这个值就是集群本身。我们接着跟Cluster里面:
发现里面维护了两个集合,一个是persistentInstances,存放永久实例,一个是ephemeralInstances存放临时实例。
以上就是Nacos服务分级存储模型。
总结:
首先最外层是一个Map,结构为:Map<String, Map<String, Service>>
:
- key:是namespace_id,起到环境隔离的作用。namespace下可以有多个group
- value:又是一个
Map<String, Service>
,代表分组及组内的服务。一个组内可以有多个服务- key:代表group分组,不过作为key时格式是group_name:service_name
- value:分组下的某一个服务,例如userservice,用户服务。类型为
Service
,内部也包含一个Map<String,Cluster>
,一个服务下可以有多个集群- key:集群名称
- value:
Cluster
类型,包含集群的具体信息。一个集群中可能包含多个实例,也就是具体的节点信息,其中包含一个Set<Instance>
,就是该集群下的实例的集合- Instance:实例信息,包含实例的IP、Port、健康状态、权重等等信息
每一个服务去注册到Nacos时,就会把信息组织并存入这个Map中。