关于spring:springcloudalibabanacos的自动注册流程

有趣味的能够下载源码调试 spring-cloud-alibaba源码地址 版本2021.1
本篇文章次要目标是阐明流程,所以除了办法名是源码以外,其余代码有简写或重写,可看作伪代码,只为了表白逻辑和展现流程。

一个代码块中调用办法的内容根本能够本代码块或上面一个代码块中找到。

服务注册

nacos服务器就是一个web我的项目,对nacos的所有操作都就是发送一个http申请,所以只须要找到spring-cloud-alibaba-nacos在什么中央发送了这个申请。

  1. spring boot启动时,会调用spring的refresh办法实现spring的启动,在启动的最初,调用finishRefresh办法。这个办法的最终目标是调用spring容器中所有SmartLifecycle实现类的start办法

    @Override
    public void refresh() throws BeansException, IllegalStateException {
         //...
         finishRefresh();
         //...
    }
    protected void finishRefresh() {
         //...
         //初始化生命周期处理器,默认为DefaultLifecycleProcessor
         initLifecycleProcessor();
         //调用生命周期处理器的onRefresh
         getLifecycleProcessor().onRefresh();
         //...
    }
    public class DefaultLifecycleProcessor{
    
     @Override
     public void onRefresh() {
         startBeans(true);
     }
    
     private void startBeans(boolean autoStartupOnly) {
         //获取spring容器中SmartLifecycle的实现类的bean
         SmartLifecycle beans=getSmartLifecycleBeans();
         for(SmartLifecycle bean:beans){
             //SmartLifecycle实现了Phased接口,能够返回一个int值,示意调用程序
             //数字越小的越先调用
             int phase=beans.getPhase();
             //把bean放入LifecycleGroup中,phase雷同的放到同一个LifecycleGroup
             //目标在于能够对立调用phase雷同的bean的办法
             LifecycleGroup lifecycleGroups=new LifecycleGroup(phase,bean));
         }
         //依据phase的值排序
         sort(lifecycleGroups);
         //依据顺序调用LifecycleGroup的start
         lifecycleGroups.start();
     }
    
     //这是一个外部类
     private class LifecycleGroup {
    
         public void start() {
             doStart(bean);
         }
    
         private void doStart(){
             bean.start()
         }
     }
    }
  2. spring boot提供了一个SmartLifecycle的实现类WebServerStartStopLifecycle,并且重写了start办法

    //这个是servlet包下的,反应式的在reactive包下,同样也是公布事件
    package org.springframework.boot.web.servlet.context;
    
    public void start() {
         //在start办法中公布了个事件,示意Servlet web服务器已初始化实现
         applicationContext.publishEvent(new ServletWebServerInitializedEvent());
    }
    //这个事件的继承关系
    public class ServletWebServerInitializedEvent extends WebServerInitializedEvent
  3. spring-cloud提供了个抽象类监听了WebServerInitializedEvent事件

    public abstract class AbstractAutoServiceRegistration<R extends Registration> implements ApplicationListener<WebServerInitializedEvent> {
     //这里应用了装璜器模式,须要从子类中传入数据
     protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry, AutoServiceRegistrationProperties properties) {
         this.serviceRegistry = serviceRegistry;
         this.properties = properties;
     }
    
     public void onApplicationEvent(WebServerInitializedEvent event) {
         this.bind(event);
     }
    
     public void bind(WebServerInitializedEvent event) {
         this.start();
     }
    
     //这里调用的是nacos实现类再调用super,但子类中并没有什么重要逻辑,所以省略
     public void start() {
         this.register();
     }
    
     //上方一顿调用,调到这里,这里就是spring-cloud提供的主动注册逻辑
     protected void register() {
         //从子类获取Registration并应用子类传入的serviceRegistry进行注册
         this.serviceRegistry.register(this.getRegistration());
     }
    
     protected abstract R getRegistration();
    }

    简略看一下RegistrationServiceRegistry两个接口

    1. public interface ServiceInstance {
          String getServiceId();
          String getHost();
          int getPort();
      }
      //Registration的子类须要返回注册所需的根本信息
      public interface Registration extends ServiceInstance {
      }
    2. //把Registration传入register办法,在子类中实现注册逻辑
      public interface ServiceRegistry<R extends Registration> {
      void register(R registration);
      }
  4. spring-cloud-alibaba-nacos提供了AbstractAutoServiceRegistration的实现类,从继承关系来看,实质是一个监听了WebServerInitializedEvent的监听器

    public class NacosAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration>{
     //传入注册器和注册所需根本信息
     public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
                                         AutoServiceRegistrationProperties properties,
                                         NacosRegistration registration) {
         //把serviceRegistry传入父类
         super(serviceRegistry, autoServiceRegistrationProperties);
         this.registration = registration;
     }
    
     @Override
     //返回registration
     protected NacosRegistration getRegistration() {
         return this.registration;
     }
    }
     

    NacosAutoServiceRegistration对象是在主动配置类中创立的,springboot主动配置的大抵逻辑

    springboot启动时会获取classpath*:META-INF/spring.factories中的键值对

    再应用spring的通用解析逻辑去解析value所示意的类,实现解析的办法是:org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

    #spring-cloud-starter-alibaba-nacos-discovery包中的spring.factories文件,这只是其中一个value
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration 
    public class NacosServiceRegistryAutoConfiguration {
    
     @Bean
     public NacosServiceRegistry nacosServiceRegistry() {
         return new NacosServiceRegistry();
     }
    
     @Bean
     public NacosRegistration nacosRegistration() {
         return new NacosRegistration();
     }
    
     @Bean
     public NacosAutoServiceRegistration nacosAutoServiceRegistration(
         NacosServiceRegistry registry,
         NacosRegistration registration) {
         return new NacosAutoServiceRegistration(registry, registration);
     }
    
    }
  5. nacos的注册逻辑

    public class NacosServiceRegistry implements ServiceRegistry<Registration>{
        @Override
        public void register(Registration registration) {
            //这个NamingService是nacos-api包中的类,是在主动配置类中HealthIndicator
            //创立的过程中被创立,这里是通过一个管理器去获取
            //NamingService中蕴含了服务的获取、注册、删除等办法
            NacosNamingService namingService = namingService();
            //应用registration创立一个服务实例
            Instance instance = createNacosInstance(registration);
            //注册服务
            namingService.registerInstance(serviceId, group, instance);
    
    }
    public class NacosNamingService implements NamingService{
        @Override
        public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
    
            //结构心跳信息
            BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
            //发送心跳信息,也就是每隔一段时间就向nacos服务器发一个申请,
            //服务器收到后解析申请就能晓得该服务没有下线
            //beatReactor在结构器中被创立
            beatReactor.addBeatInfo(groupedServiceName, beatInfo);
    
            //发送注册申请
            //serverProxy在结构器中被创立
            serverProxy.registerService(groupedServiceName, groupName, instance);
        }
    }    
    //这个代码块是发送心跳逻辑
    public class BeatReactor{
    
       public void addBeatInfo(String serviceName, BeatInfo beatInfo) {
           //这是一个定时线程池,默认为虚拟机最大可用处理器数量的一半
           //具体调用的是Runtime.getRuntime().availableProcessors()数量包含超线程,但不是肯定精确。
           //第一个参数是要执行的工作,第二个是延迟时间,默认5秒,第三个是工夫单位
           executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit);
       }
    }
    
    class BeatTask implements Runnable {
       @Override
       public void run() {
           //发送心跳信息
           serverProxy.sendBeat(beatInfo);
           //这里又调用了本人,造成了递归,所以会每5秒就向nacos服务器发送信息
           executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit);
       }
    }
    

    这是nacos官网提供的注册申请实例,所以只须要构建出这个申请发给nacos服务器就行了

    curl -X POST ‘http://127.0.0.1:8848/nacos/v…

    //发送注册逻辑
    public class NamingProxy {
        public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
            //instance中蕴含了注册服务所需的信息,信息起源为NacosDiscoveryProperties和其余中央
            //应用传入的三个参数构建params
            //构建header
            //构建uri
            //应用NacosRestTemplate发送申请,外面应用了JdkHttpClientRequest,
            //再外面应用了sun.net.www.protocol.http.HttpURLConnection
            //申请往nacos服务器一发,完事。
            //在这个http申请有返回值,nacos也创立了一个ResponseHandler去把返回值解析为HttpRestResult
            //但在这个流程中最终没有应用返回值。
            //心跳的发送也是http申请,所以与注册的逻辑是差不多的。
            reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
        } 
    }

总结

一. spring,启动实现后调用SmartLifecyclestart办法

二. spring-boot,提供了SmartLifecycle的实现类WebServerStartStopLifecycle,在start中公布了ServletWebServerInitializedEvent

三. spring-cloud,应用一个抽象类AbstractAutoServiceRegistration监听了ServletWebServerInitializedEvent,通过调用子类的ServiceRegistryRegistration注册服务

四. spring-cloud-alibaba-nacos,提供了AbstractAutoServiceRegistration的实现类NacosServiceRegistryAutoConfiguration,并在主动配置类中初始化。

五. nacos,在NacosServiceRegistryAutoConfiguration中实现具体的http申请的构建与发送

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理