0. 环境
- nacos版本:1.4.1
- Spring Cloud : 2020.0.2
- Spring Boot :2.4.4
- Spring Cloud alibaba: 2.2.5.RELEASE
1. InstanceController#register
nacos注册中心功能是在naming
这个子项目下面的,是个springboot项目,然后我们直接找controller
就可以了,找到这个InstanceController
,第一个方法就是服务注册方法(register方法
):
@CanDistro
@PostMapping
@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
public String register(HttpServletRequest request) throws Exception {
// 从请求中获取指定属性值
final String namespaceId = WebUtils
.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
// 从请求中获取指定属性值
final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
// 检测serviceName是否合法
NamingUtils.checkServiceNameFormat(serviceName);
// 通过请求参数组装出instance
final Instance instance = parseInstance(request);
// todo 将instance写到注册表
serviceManager.registerInstance(namespaceId, serviceName, instance);
return "ok";
}
复制代码
先是解析出来instance
,就是根据client发送的那堆参数解析出来的。接着就是调用serviceManager组件
进行实例注册,这个serviceManager
组件在注册中心是个核心组件(服务注册,下线,获取服务列表等),都是找这个组件的。
2. ServiceManager#registerInstance
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
// 创建 空service
// 第三个参数 true表示临时实例
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
// 从注册表获取到service
Service service = getService(namespaceId, serviceName);
// 这里指定不能为null
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
}
// todo 将instance写入到service,即写入到了注册表
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
复制代码
这几个步骤都很重要,我们挨个看看,createEmptyService
这个方法就是当service 不存在的时候,创建一个空的serivce
,这service你可以理解为服务,其实就是服务的意思,看下这个方法
2.1 ServiceManager#createEmptyService
public void createEmptyService(String namespaceId, String serviceName, boolean local) throws NacosException {
// local为true,表示当前实例为临时实例
createServiceIfAbsent(namespaceId, serviceName, local, null);
}
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
throws NacosException {
// 从注册表中获取service
Service service = getService(namespaceId, serviceName);
// 若当前注册instance是其提供服务的第一个实例,则注册表中是没有该service的,
// 此时会创建一个service实例
if (service == null) {
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
// 修改时间
service.setLastModifiedMillis(System.currentTimeMillis());
// todo 重新计算校验和
service.recalculateChecksum();
if (cluster != null) {
// cluster与service建立联系
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
// todo 将service写入到注册表
putServiceAndInit(service);
// 对持久实例的操作
if (!local) {
addOrReplaceService(service);
}
}
}
复制代码
先是根据namespace与serviceName
获取service
,如果没有的话,就创建,最开始的时候,肯定是没有的,然后就会创建一个service
,看下这个getService
方法:
public Service getService(String namespaceId, String serviceName) {
if (serviceMap.get(namespaceId) == null) {
return null;
}
return chooseServiceMap(namespaceId).get(serviceName);
}
复制代码
说白了其实就是去serviceMap
这个成员中获取,对应关系看下面这个注释就可以。
// namespace ---》 ser