zoukankan      html  css  js  c++  java
  • Nacos(一)源码分析Nacos注册示例流程

    nacos官方地址:https://nacos.io/zh-cn/

    大家可以看一下nacos的中文手册以及官方源码,博主就不带领大家快速入门 了,官方文档中都有而且非常标准,比其他博客写的好多了并且还是实时更新的。

    先看一下博主给大家画的流程图,掌握一下大概的基本流程,好理解,博主给大家讲源码:

    https://www.processon.com/view/link/5f7e895be0b34d0711f65178

    nacos最主要的功能就是服务注册及发现,那它到底是如何实现的呢?博主用的springboot开发的,所以直接就去找nacos的jar包下的spring.factories,这是每个要自动注入的服务jar的必备文件,我们来看一下

       里面有很多的自动配置类,我们只看一下NacosServiceRegistryAutoConfiguration,该类主要做的是服务注册的相关事宜,如果大家第一次看源码的话不知道该如何下手,最笨的方法就是一个一个看。总会找到的,最好要找名字看起来就像自己找的,因为这是阿里巴巴开发的,他们是有java开发规范的,要做到见名知意。

     1  /**
     2      * @author xiaojing
     3      * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
     4      */
     5     @Configuration(proxyBeanMethods = false)
     6     @EnableConfigurationProperties
     7     @ConditionalOnNacosDiscoveryEnabled
     8     @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
     9             matchIfMissing = true)
    10     @AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
    11             AutoServiceRegistrationAutoConfiguration.class,
    12             NacosDiscoveryAutoConfiguration.class })
    13     public class NacosServiceRegistryAutoConfiguration {
    14 
    15         @Bean
    16         public NacosServiceRegistry nacosServiceRegistry(
    17                 NacosDiscoveryProperties nacosDiscoveryProperties) {
    18             return new NacosServiceRegistry(nacosDiscoveryProperties);
    19         }
    20 
    21         @Bean
    22         @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    23         public NacosRegistration nacosRegistration(
    24                 NacosDiscoveryProperties nacosDiscoveryProperties,
    25                 ApplicationContext context) {
    26             return new NacosRegistration(nacosDiscoveryProperties, context);
    27         }
    28 
    29         @Bean
    30         @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    31         public NacosAutoServiceRegistration nacosAutoServiceRegistration(
    32                 NacosServiceRegistry registry,
    33                 AutoServiceRegistrationProperties autoServiceRegistrationProperties,
    34                 NacosRegistration registration) {
    35             //这里才是自动注入的类,我们需要进去看一下
    36             return new NacosAutoServiceRegistration(registry,
    37                     autoServiceRegistrationProperties, registration);
    38         }
    39 
    40     }
     1 public class NacosAutoServiceRegistration
     2         extends AbstractAutoServiceRegistration<Registration> {
     3 
     4     private static final Logger log = LoggerFactory
     5             .getLogger(NacosAutoServiceRegistration.class);
     6 
     7     private NacosRegistration registration;
     8 
     9     public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
    10             AutoServiceRegistrationProperties autoServiceRegistrationProperties,
    11             NacosRegistration registration) {
    12         super(serviceRegistry, autoServiceRegistrationProperties);
    13         this.registration = registration;
    14     }
    15 
    16     @Deprecated
    17     public void setPort(int port) {
    18         getPort().set(port);
    19     }
    20 
    21     @Override
    22     protected NacosRegistration getRegistration() {
    23         if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
    24             this.registration.setPort(this.getPort().get());
    25         }
    26         Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
    27         return this.registration;
    28     }
    29 
    30     @Override
    31     protected NacosRegistration getManagementRegistration() {
    32         return null;
    33     }
    34 
    35     @Override
    36     protected void register() {
    37         if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
    38             log.debug("Registration disabled.");
    39             return;
    40         }
    41         if (this.registration.getPort() < 0) {
    42             this.registration.setPort(getPort().get());
    43         }
    44         super.register();
    45     }
    46 
    47     @Override
    48     protected void registerManagement() {
    49         if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
    50             return;
    51         }
    52         super.registerManagement();
    53 
    54     }
    55 
    56     @Override
    57     protected Object getConfiguration() {
    58         return this.registration.getNacosDiscoveryProperties();
    59     }
    60 
    61     @Override
    62     protected boolean isEnabled() {
    63         return this.registration.getNacosDiscoveryProperties().isRegisterEnabled();
    64     }
    65 
    66     @Override
    67     @SuppressWarnings("deprecation")
    68     protected String getAppName() {
    69         String appName = registration.getNacosDiscoveryProperties().getService();
    70         return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
    71     }
    72 
    73 }
    看到这里,大家可能有点懵,我应该找那个方法呢?大家可以看一下构造器中,引用了父类,当我们看到父类的时候,发现父类实现了ApplicationListener,这个类大家不陌生,系统会自动执行其onApplicationEvent而正好我们的类实现了这个方法,最后我们发现了应该看register() 方法,大家可以来看看这个方法的实现
     1 @Override
     2     public void register(Registration registration) {
     3 
     4         if (StringUtils.isEmpty(registration.getServiceId())) {
     5             log.warn("No service to register for nacos client...");
     6             return;
     7         }
     8         //看到这两个参数,大家看过nacos文档就知道这两个参数要干啥用了
     9         String serviceId = registration.getServiceId();
    10         String group = nacosDiscoveryProperties.getGroup();
    11         //要发送的实例对象,具体的属性,大家可以看看这个方法
    12         Instance instance = getNacosInstanceFromRegistration(registration);
    13 
    14         try {
    15         //走这里,是真正的注册服务
    16             namingService.registerInstance(serviceId, group, instance);
    17             log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
    18                     instance.getIp(), instance.getPort());
    19         }
    20         catch (Exception e) {
    21             log.error("nacos registry, {} register failed...{},", serviceId,
    22                     registration.toString(), e);
    23             // rethrow a RuntimeException if the registration is failed.
    24             // issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132
    25             rethrowRuntimeException(e);
    26         }
    27     }
     1     @Override
     2     public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
     3          //是否是临时的,这个参数默认是临时实例,这个是临时或者是否持久很重要,先记住
     4         if (instance.isEphemeral()) {
     5             //填写各种心跳信息,毕竟服务需要往nacos发送心跳,nacos才能知道该服务是否还存活
     6             BeatInfo beatInfo = new BeatInfo();
     7             beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
     8             beatInfo.setIp(instance.getIp());
     9             beatInfo.setPort(instance.getPort());
    10             beatInfo.setCluster(instance.getClusterName());
    11             beatInfo.setWeight(instance.getWeight());
    12             beatInfo.setMetadata(instance.getMetadata());
    13             beatInfo.setScheduled(false);
    14             beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());
    15             //看一下客服端是如何发送心跳
    16             beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);
    17         }
    18         //注册服务
    19         serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
    20     }
     1         @Override
     2         public void run() {
     3             if (beatInfo.isStopped()) {
     4                 return;
     5             }
     6             long nextTime = beatInfo.getPeriod();
     7             try {
     8                 //会调用nacos服务端的/instance/beat接口
     9                 JSONObject result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);
    10                 long interval = result.getIntValue("clientBeatInterval");
    11                 boolean lightBeatEnabled = false;
    12                 if (result.containsKey(CommonParams.LIGHT_BEAT_ENABLED)) {
    13                     lightBeatEnabled = result.getBooleanValue(CommonParams.LIGHT_BEAT_ENABLED);
    14                 }
    15                 BeatReactor.this.lightBeatEnabled = lightBeatEnabled;
    16                 if (interval > 0) {
    17                     nextTime = interval;
    18                 }
    19                 int code = NamingResponseCode.OK;
    20                 if (result.containsKey(CommonParams.CODE)) {
    21                     code = result.getIntValue(CommonParams.CODE);
    22                 }
    23                 //如果找不到服务,则进行注册服务
    24                 if (code == NamingResponseCode.RESOURCE_NOT_FOUND) {
    25                     Instance instance = new Instance();
    26                     instance.setPort(beatInfo.getPort());
    27                     instance.setIp(beatInfo.getIp());
    28                     instance.setWeight(beatInfo.getWeight());
    29                     instance.setMetadata(beatInfo.getMetadata());
    30                     instance.setClusterName(beatInfo.getCluster());
    31                     instance.setServiceName(beatInfo.getServiceName());
    32                     instance.setInstanceId(instance.getInstanceId());
    33                     instance.setEphemeral(true);
    34                     try {
    35                         //该方法封装好参数后,会调用/instance接口
    36                         serverProxy.registerService(beatInfo.getServiceName(),
    37                             NamingUtils.getGroupName(beatInfo.getServiceName()), instance);
    38                     } catch (Exception ignore) {
    39                     }
    40                 }
    41             } catch (NacosException ne) {
    42                 NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, code: {}, msg: {}",
    43                     JSON.toJSONString(beatInfo), ne.getErrCode(), ne.getErrMsg());
    44 
    45             }
    46             //定时线程池不会一直循环进行调用,所以每次执行完之后会继续添加定时任务进行发送心跳
    47             executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS);
    48         }

      看完发送心跳的方法,我们该看注册服务的方法了:serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);其实就是发送心跳后,找不到服务时调用的/instance接口。

      到此,我们的服务就会注册到nacos服务端中,客户端的代码就是如此,还是挺简单的,我们下一篇就会带大家走进服务端的代码。


  • 相关阅读:
    ELF静态链接
    linux
    百度图表插件
    秀米(图文编辑)
    Html 助手
    在型原型工具
    AnalyticDB
    H5 (webApi) 接口帮助文档
    H5 拖拽读取文件和文件夹
    mongodb int字段的一个小坑
  • 原文地址:https://www.cnblogs.com/guoxiaoyu/p/14183350.html
Copyright © 2011-2022 走看看