前一篇了解了客户端是怎么通过GRPC与服务端建立连接,并发送注册请求的。Nacos注册中心源码分析-服务注册(上)
这一篇主要是说明 接收到客户端请求后,服务端会如何处理,如何保存客户端信息。
开始之前
下边就上代码分析一波~
开始之前先回顾一下服务注册时的请求信息:
com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy#doRegisterService
public void doRegisterService(String serviceName, String groupName, Instance instance) throws NacosException {
InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,
NamingRemoteConstants.REGISTER_INSTANCE, instance);
requestToServer(request, Response.class);
redoService.instanceRegistered(serviceName, groupName);
}
注意 InstanceRequest type使用的是 REGISTER_INSTANCE
Nacos服务处理注册请求
服务注册过程也没太多的逻辑,我们主要关注的还得是客户端注册信息的存储方式。
图中标记出来的三个重要类中的集合便是注册信息的保存位置。
ServiceManager类的集合
先看一下 Service 内容。
主要属性就是上图这几个,用于标记一类服务,并非指服务具体的实例。
namespaceSingletonMaps
这个集合主要用于 Nacos 自己的服务管理后台页面获取所有注册的服务,Key为不同的命名空间。
// String 为 命名空间 nameSpace,一个命名空间有多个服务。(所有的服务)
private final ConcurrentHashMap<String, Set<Service>> namespaceSingletonMaps;
singletonRepository
这个缓存用于判断服务是否存在
private final ConcurrentHashMap<Service, Service> singletonRepository;
ConnectionBasedClientManager类集合
该集合为具体客户端实例信息的存储,Key为客户端实例的Id。
// String 为 clientId,一个实例对应一个客户端连接
private final ConcurrentMap<String, ConnectionBasedClient> clients = new ConcurrentHashMap<>();
ClientServiceIndexesManager类集合
这个缓存存储的是服务对应的 实例Id。我们通过注册中心获取服务实例时,可以从该集合获取实例。当然具体的实例地址就可以从 ConnectionBasedClientManager#clients 集合来获取了。
// String 为 clientId (一个服务有多个实例)
private final ConcurrentMap<Service, Set<String>> publisherIndexes = new ConcurrentHashMap<>();
通过对以上集合的分析,已经知道了客户端实例是如何存储的了。
下边要关注的就是服务的订阅、订阅服务下线、超时如何处理的。
最开始,我们便知道客户端服务除了注册以外,还会订阅其他服务,当订阅的服务实例异常不可用时,Nacos服务端要能及时感知,感知到后,也需要及时通知所有的订阅的服务,告知实例不可用。
下一节将会围绕这一部分继续分析。