1、NacosClient在服务注册时做了什么

本文详细介绍了SpringBoot项目中如何集成Nacos,并深入解析了Nacos服务发现的实例注册过程,包括配置项、自动注册逻辑、服务注册的关键代码以及客户端与服务端的交互细节。

项目集成

以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注册请求的

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高级摸鱼工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值