• nacos原理--nacos注册原理分析


    1. nacos使用
    引入pom文件
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>${官方版本号}</version>
    </dependency>
    

    在启动类上添加@EnableDiscoveryClient

    @SpringBootApplication
    @EnableDiscoveryClient
    public class SpringCloudConfigClientApplication {
    
       public static void main(String[] args) {
          SpringApplication.run(SpringCloudConfigClientApplication.class, args);
       }
    }
    

    并添加配置文件

    spring.cloud.nacos.discovery.server-addr=http://localhost:8848
    
    2. nacos注册原理
    查看spring-cloud-starter-alibaba-nacos-discovery包中spring.factories类能够看到如下源码:
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
      com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,
      com.alibaba.cloud.nacos.ribbon.RibbonNacosAutoConfiguration,
      com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,
      com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,
      com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,
      com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,
      com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration
    org.springframework.cloud.bootstrap.BootstrapConfiguration=
      com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration
    

     其中关键类:NacosServiceRegistryAutoConfiguration

    @Bean
    public NacosServiceRegistry nacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
       return new NacosServiceRegistry(nacosDiscoveryProperties);
    }
    
    @Bean
    @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    public NacosRegistration nacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties,ApplicationContext context) {
       return new NacosRegistration(nacosDiscoveryProperties, context);
    }
    
    @Bean
    @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    public NacosAutoServiceRegistration nacosAutoServiceRegistration(
          NacosServiceRegistry registry,AutoServiceRegistrationProperties autoServiceRegistrationProperties,NacosRegistration registration) {
       return new NacosAutoServiceRegistration(registry,
             autoServiceRegistrationProperties, registration);
    }
    

    NacosServiceRegistry和NacosRegistration都将作为参数注册到NacosAutoServiceRegistration,那么NacosAutoServiceRegistration是个核心类,同时能够看到继承的接口AbstractAutoServiceRegistration也继承了ApplicationListener<WebServerInitializedEvent>,那么就是当Web程序初始化完成后调用:

    // web程序初始化完成后发送消息,本类监听到事件后执行
    public void onApplicationEvent(WebServerInitializedEvent event) {
        this.bind(event);
    }
    
    public void bind(WebServerInitializedEvent event) {
        ApplicationContext context = event.getApplicationContext();
        if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
            this.port.compareAndSet(0, event.getWebServer().getPort());
            this.start();
        }
    }
    
    public void start() {
        if (!this.isEnabled()) {
            //...
        } else {
            // 用于是否已经注册了
            if (!this.running.get()) {
                this.context.publishEvent(new InstancePreRegisteredEvent(this, this.getRegistration()));
                // 关键方法,即本方法就是将服务注册到nacos中
                this.register();
                if (this.shouldRegisterManagement()) {
                    this.registerManagement();
                }
    
                this.context.publishEvent(new InstanceRegisteredEvent(this, this.getConfiguration()));
                this.running.compareAndSet(false, true);
            }
    
        }
    }
    // 此处就调用NacosServiceRegistry中register方法
    protected void register() {
        this.serviceRegistry.register(this.getRegistration());
    }
    

    接下啦是NacosServiceRegistry类register方法

    public void register(Registration registration) {
        // 服务ID为空直接退出
       if (StringUtils.isEmpty(registration.getServiceId())) {
          return;
       }
       String serviceId = registration.getServiceId();
       String group = nacosDiscoveryProperties.getGroup();
        // 生成Instance
       Instance instance = getNacosInstanceFromRegistration(registration);
    
       try {
           // 调用http请求注册
          namingService.registerInstance(serviceId, group, instance);
       }
    }
    
    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
        if (instance.isEphemeral()) {
            // 如果是临时实例,需要通过心跳的方式保持
            BeatInfo beatInfo = new BeatInfo();
            beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
            beatInfo.setIp(instance.getIp());
            beatInfo.setPort(instance.getPort());
            beatInfo.setCluster(instance.getClusterName());
            beatInfo.setWeight(instance.getWeight());
            beatInfo.setMetadata(instance.getMetadata());
            beatInfo.setScheduled(false);
            beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());
            // 定时任务,每隔一段时间发送短信
            this.beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);
        }
        // 注册
        this.serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
    }
    // 发送心跳
    public void addBeatInfo(String serviceName, BeatInfo beatInfo) {
        // ...省略
        this.dom2Beat.put(key, beatInfo);
        // 定时任务
        this.executorService.schedule(new BeatReactor.BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
        MetricsMonitor.getDom2BeatSizeMonitor().set((double)this.dom2Beat.size());
    }
    
    // 参数拼接调用http请求
    public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
        LogUtils.NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", new Object[]{this.namespaceId, serviceName, instance});
        Map<String, String> params = new HashMap(9);
        params.put("namespaceId", this.namespaceId);
        params.put("serviceName", serviceName);
        params.put("groupName", groupName);
        params.put("clusterName", instance.getClusterName());
        params.put("ip", instance.getIp());
        params.put("port", String.valueOf(instance.getPort()));
        params.put("weight", String.valueOf(instance.getWeight()));
        params.put("enable", String.valueOf(instance.isEnabled()));
        params.put("healthy", String.valueOf(instance.isHealthy()));
        params.put("ephemeral", String.valueOf(instance.isEphemeral()));
        params.put("metadata", JSON.toJSONString(instance.getMetadata()));
        this.reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, "POST");
    }
    

     总结:nacos客户端注册原理简单,通过找到Spring注解的源码,并顺着往下读,基本能够看到Nacos通过http的方式将生产的Instance发送客户端。如果是临时节点,需要通过心跳的方式维持,而心跳式通过定时任务的方式间隔的发送来保持。

  • 相关阅读:
    UITableView加载显示更多内容
    UITableView  折叠效果
    40个GitHub上最受欢迎的iOS开源项目
    oc中的block使用心得
    iOS CGRectContainsPoint的用法
    ios NSComparator 三种枚举类型
    错误提示 Unsupported compiler 'com.apple.compilers.llvmgcc42' selected for architecture 'i386'
    IOS 第三方库之-MBProgressHUD的使用详解
    ios 测试工程是否内存泄漏
    单双击手势
  • 原文地址:https://www.cnblogs.com/skyice/p/14854577.html
Copyright © 2020-2023  润新知