当前位置:网站首页>【Nacos】NacosClient在服务注册时做了什么

【Nacos】NacosClient在服务注册时做了什么

2022-07-25 09:16:00 高级摸鱼工程师

项目集成

以springboot和nacos的集成为例。
sb项目中添加nacos-discovery依赖:

<dependency>
  <groupId>com.alibaba.boot</groupId>
  <artifactId>nacos-discovery-spring-boot-starter</artifactId>
  <version>0.2.10</version>
</dependency>
nacos:
discovery:
server-addr: http://localhost:8848
namespace: public
username: nacos
password: nacos
auto-register: true
register:
   service-name: sb-provider
   healthy: true

要注意的属性:

  • auto-register: 这个配置默认是false,也就是默认不会将此实例注册到nacos server
  • register.service-name :当前实例的service name,不能为空,否则项目启动完之后,注册到nacos server时会报错。这是nacos-client的内部的一个校验。

解析

starter

找到我们集成nacos client使用的jar包:nacos-discovery-spring-boot-starter
在这里插入图片描述

再看 nacos-discovery-spring-boot-autoconfigure , 根据命名就可以看出来,这是nacos装配的配置就在这里了
在这里插入图片描述

直接看 spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.alibaba.boot.nacos.discovery.autoconfigure.NacosDiscoveryAutoConfiguration

看到org.springframework.boot.autoconfigure.EnableAutoConfiguration其实就懂关键的装配代码在哪里了,那就直接看NacosDiscoveryAutoConfiguration
在这里插入图片描述

代码很简单,从@Bean就可以看出自动注册是通过 new NacosDiscoveryAutoRegister() 实现的。

还是那一套,通过SpringEvent监听 WebServerInitializedEvent事件来实现。
在这里插入图片描述

前边几个校验逻辑很简单,那关键的就是 namingService.registerInstance 这里做实例注册的事情了。

NamingService

@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
    
    NamingUtils.checkInstanceIsLegal(instance);
    clientProxy.registerService(serviceName, groupName, instance);
}

NamingUtils.checkInstanceIsLegal(instance); 这里是业务校验,校验了以下两个设置是否有误:

  • heart beat timeout must > heart beat interval
  • ip delete timeout must > heart beat interval
    ps:其实就是校验设置的超时时间是否符合要求,要求就是要大于默认的心跳周期。很合理

那么重头戏就是clientProxy.registerService(serviceName, groupName, instance)这个方法了。
clientProxy是一个接口,封装了很多service相关的操作。嗯,合理

那么具体来看registerService是怎么实现的

@Override
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
    
    getExecuteClientProxy(instance).registerService(serviceName, groupName, instance);
}

private NamingClientProxy getExecuteClientProxy(Instance instance) {
    
    return instance.isEphemeral() ? grpcClientProxy : httpClientProxy;
}

为什么根据是否是临时实例而选择不同的clientProxy?
it’s a question .
先不管了,接着看

@Override
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
    
    NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance {}", namespaceId, serviceName,
                       instance);
    redoService.cacheInstanceForRedo(serviceName, groupName, instance);
    doRegisterService(serviceName, groupName, instance);
}

redoService.cacheInstanceForRedo 做的事情就是将本实例做个缓存。

private final ConcurrentMap<String, InstanceRedoData> registeredInstances = new ConcurrentHashMap<>();

public void cacheInstanceForRedo(String serviceName, String groupName, Instance instance) {
    
    String key = NamingUtils.getGroupedName(serviceName, groupName);
    InstanceRedoData redoData = InstanceRedoData.build(serviceName, groupName, instance);
    //registeredInstances是个map
    synchronized (registeredInstances) {
    
        registeredInstances.put(key, redoData);
    }
}

在这里插入图片描述

InstanceRedoData有个属性叫registered,语义是: 是否注册。
可以看到第一次放到缓存的时候这个属性是false

接着看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);
}

requestToServer内部是调用方法去server注册实例,就不研究了。

public void instanceRegistered(String serviceName, String groupName) {
    
    String key = NamingUtils.getGroupedName(serviceName, groupName);
    synchronized (registeredInstances) {
    
        InstanceRedoData redoData = registeredInstances.get(key);
        if (null != redoData) {
    
            redoData.setRegistered(true);
        }
    }
}

instanceRegistered就是将刚才缓存的实例registered字段修改为true,代表此实例已在server端注册成功。

下一篇研究下server是怎么处理client的service注册请求的

原网站

版权声明
本文为[高级摸鱼工程师]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Paranoia_ZK/article/details/125834531