SpringCloud 基于Nacos和Eureka 实现双注册双订阅

3分钟前 828阅读

一、使用场景/原因

  • 过渡期迁移:

    • 当系统从一个服务注册中心迁移到另一个时,例如从 Eureka 迁移到 Nacos,可以在过渡期内同时使用两个注册中心,确保服务平稳迁移,逐步过渡,避免一次性切换带来的风险。
  • 兼容性考虑:

    • 不同的微服务可能使用不同的注册中心,为了兼容这些微服务,可以同时支持 Nacos 和 Eureka。这样既可以支持新开发的服务使用 Nacos,也可以兼容旧有的使用 Eureka 的服务。

    二、增加注册中心

            本篇文章我们升级的项目本身现在使用的是Eureka,然后新创建的项目采用的是 Nacos来作为注册中心,这就会出现一个问题 , 那就是微服务之间调用困难, 因为新旧微服务分别都注册在不同的注册中心。如果采用一次性整体切换成Nacos,对于已经运行了很久的现有项目来说, 工作量有点大, 所以我们采用这种办法, 就是项目同时支持Nacos、Eureka两个服务注册,为后续的逐步迁移做准备。

     2.1、Pom文件分别配置Nacos、Eureka

        com.alibaba.cloud
        spring-cloud-starter-alibaba-nacos-discovery
    
    
        org.springframework.cloud
        spring-cloud-starter-netflix-eureka-client
    
    

    2.2、启动类注解

    1、注释掉 @EnableEurekaClent   // 弃用Eureka 专门的注册注解

    2、新添加 @EnableDiscoveryClient  

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

    2.3、项目配置文件Application.yml

    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:9002/eureka/
      instance:
        prefer-ip-address: true
    server:
      port: 11500
    spring:
      application:
        name: Ko
      cloud:
        service-registry:
          auto-registration:
            enabled: false
        nacos:
          discovery:
            server-addr: http://127.0.0.1:9999
            namespace: 47dea8bf-3dce-4c86-82bc-82f1497c57d2
    

    三、启动项目

    至此,并没有结束,配置结束后,我们来启动项目,看效果。

    不出意外的话,会出现下面这个报错, 出意外的话那就是出意外了 🙃🙃🙃🙃

     3.1、自动注册时候报错

    图和文字是一样的 为了方便看,可方便复制SpringCloud 基于Nacos和Eureka 实现双注册双订阅

    Disconnected from the target VM, address: 'localhost:63051', transport: 'socket'
    ***************************
    APPLICATION FAILED TO START
    ***************************
    Description:
    Field autoServiceRegistration in org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration required a single bean, but 2 were found:
    	- nacosAutoServiceRegistration: defined by method 'nacosAutoServiceRegistration' in class path resource [com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.class]
    	- eurekaAutoServiceRegistration: defined by method 'eurekaAutoServiceRegistration' in class path resource [org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.class]
    Action:
    Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

            言简意赅的阐述一下出现这个报错的原因是因为, @EnableDiscoveryClient 在启动的时候会进行自动注册, 干这件事情的就是 AutoServiceRegistrationAutoConfiguration ,然后这个了类在一开始 注入了一个类型为 AutoServiceRegistration的类 

    SpringCloud 基于Nacos和Eureka 实现双注册双订阅

    继续往下看, AutoServiceRegistration这个类的实现有两个,分别是EurekaAutoServiceRegistration 和 NacosAutoServiceRegistration,这都是因为引入了两个注册中心后导致的,

    SpringCloud 基于Nacos和Eureka 实现双注册双订阅

    然后我们再说日志中给出的建议,他是说建议你在其中一个类上面加@Primary , 这样虽然能解决问题, 但是,这是源代码,无法修改的,难道不修改源码就没什么办法了么 ?

      

    让我们在回到最开始的那个自动配置类上 , 注意看 , 这个类的init , 在进行了注入之后,  什么都没有做 , 就只是做了一下Check ,我个人感觉啊, 把这个自动配置类, 给忽略掉,也就是将其排除。 不让他自动执行!

    SpringCloud 基于Nacos和Eureka 实现双注册双订阅

    3.2、注入失败问题解决

    前面我们说到,为了解决在自动注册时候注入类时候出现两个配置类的问题, 我们采用排除这个配置类的方式,排除办法有两种, 可以根据习惯自行选择

    3.2.1 application.yml 配置方式 autoconfigure.exclude

    spring:
      application:
        name: Ko
      cloud:
        nacos:
          discovery:
            server-addr: http://127.0.0.1:9999
            namespace: 47dea8bf-3dce-4c86-82bc-82f1497c57d2
          config:
            enabled: false
            server-addr: http://127.0.0.1:9999
            import-check: false
            namespace: 47dea8bf-3dce-4c86-82bc-82f1497c57d2
      autoconfigure:
        exclude: org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration

    3.2.2 Application 启动类配置方式

    // exclude 同样可以起到忽略的作用 ,至于这里为什么要忽略两个,继续往下看,会说到
    @SpringBootApplication(exclude = {AutoServiceRegistrationAutoConfiguration.class,ServiceRegistryAutoConfiguration.class})
    @EnableDiscoveryClient
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

    然后我们再重启项目,提示的错误还有一个地方的注册配置类,遇到了同样的问题,(请注意,下面这个报错,如果你并没有使用  spring-boot-starter-actuator 这个组件就不会有这个问题)如下:

    ***************************
    APPLICATION FAILED TO START
    ***************************
    Description:
    Field registration in org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration$ServiceRegistryEndpointConfiguration required a single bean, but 2 were found:
    	- nacosRegistration: defined by method 'nacosRegistration' in class path resource [com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.class]
    	- eurekaRegistration: defined in BeanDefinition defined in class path resource [org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration.class]
    Action:
    Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
     ******** 
    Disconnected from the target VM, address: 'localhost:63833', transport: 'socket'

    这次提示的配置类是 ServiceRegistryAutoConfiguration  , 按照老办法,直接忽略这个配置类, 但这个类不像上一个那样实际什么都没做,这个还是做了点事情的 , 这个类加载的目的是因为我们项目中使用到的 Spring的监控组件, 存在这个依赖时,即使执行了上文的操作,启动时还是报错。就是因为在启动之初这个监控组件会将Service注册,便于后续的监控,所以我们可以将这个也选择直接排除这个配置类, 至于影响嘛,无非就是监控组件中会少一个EndPoint,无伤大雅。

    /**
     * @author Spencer Gibb
     */
    @Configuration(proxyBeanMethods = false)
    public class ServiceRegistryAutoConfiguration {
    	@ConditionalOnBean(ServiceRegistry.class)
    	@ConditionalOnClass(Endpoint.class)
    	protected class ServiceRegistryEndpointConfiguration {
    		@Autowired(required = false)
    		private Registration registration;
    		@Bean
    		@ConditionalOnEnabledEndpoint
    		public ServiceRegistryEndpoint serviceRegistryEndpoint(
    				ServiceRegistry serviceRegistry) {
    			ServiceRegistryEndpoint endpoint = new ServiceRegistryEndpoint(
    					serviceRegistry);
    			endpoint.setRegistration(this.registration);
    			return endpoint;
    		}
    	}
    }

    至此,分别排除了AutoServiceRegistrationAutoConfiguration 和 ServiceRegistryAutoConfiguration 这两个自动配置类后,项目便可以正常启动,且会注册到两个注册中心

    但是请注意,这种行为并不是长久之道,只适合在项目架构升级过渡期使用,或者其他特殊场景下使用,日常使用中还是建议 使用同一种注册中心,

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]