天天看点

注册中心迁移Eureka到Nacos

注册中心迁移

    • 双注册双订阅中心
    • 注册中心迁移
    • Eureka到Nacos
      • 1. 初始阶段:Eureka单注册中心环境
      • 2.双注册中心阶段
      • 3.最终状态

双注册双订阅中心

注册中心迁移

Eureka到Nacos

  • 场景:业务升级,需要将注册中心从eureka转到Nacos。nacos功能更强大,响应更快!
  • 要求:需要在不影响业务的情况下完成注册中心的转换。即不影响代码调用的情况下完成注册中心的替换!!!!

是不是听着都很高大上!!!

先用文字描述一下整个过程然后开始实操!!

  1. 初始阶段。eureka作为注册中心,provider完成服务注册并对外提供访问。consumer完成调用provider的相关服务。(consumer可注册可不注册,但是需要连接注册中心)
  2. 双注册中心阶段。用来做过渡
    • 为服务provider上线一个新的实例,该实例即注册到eureka又注册到nacos。provider在eureka有两个实例。
    • 下线旧的provider实例,即之注册到eureka的那个实例。这是consumer依旧可以访问到provider存活的另一个实例。
    • 为服务consumer上线一个新的实例,该实例即注册到eureka又注册到nacos。consumer在eureka有两个实例。
    • 下线旧的consumer。此时依旧可以使用存活的双注册实例访问provider服务。
  3. 完成转换:下线eureka服务中心。使用nacos完成替换。此时可以provider和consumer服务只和nacos进行交互
  4. 至此完成注册中心的替换!注意:关于服务之间的调用模式使用ribbon和openFeign都可以。本文以ribbon为例子。

注意:两个模块有一个父项目。下边模块的依赖省略了父模块的依赖。父项目pom依赖如下。注意版本间对应关系。如果需要更换版本可以去SpringCloudAlibaba的GitHub上查看对应关系。地址:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>
	<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
           

1. 初始阶段:Eureka单注册中心环境

provider服务: 9007端口

  1. pom依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
           
  1. 配置文件
server:
  port: 9007
spring:
  application:
    name: aaa
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
           
  1. 启动类
@SpringBootApplication
public class AApp {
    public static void main(String[] args) {
        SpringApplication.run(AApp.class,args);
    }
}
           
  1. Controller
/**测试网关路由*/
@RestController
@RequestMapping("/demos")
public class DemoController {
    @Value("${server.port}")
    private Integer port;
    @Value("${spring.application.name}")
    private String name;

    @GetMapping
    public String demos(){
        return name+"::"+port;
    }
}
           

consumer服务: 9020端口

  1. pom依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
           
  1. 配置文件
server:
  port: 9200
spring:
  application:
    name: bbb
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
           
  1. 启动类
@EnableFeignClients
@SpringBootApplication
public class BApp {
    public static void main(String[] args) {
        SpringApplication.run(BApp.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
           
  1. Controller
@RestController
@RequestMapping("/demos")
public class DemoController {
    @Value("${server.port}")
    private Integer port;
    @Value("${spring.application.name}")
    private String name;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping
    public String demos(){
        String aaa = restTemplate.getForObject("http://aaa/demos", String.class);
        return name+"::"+port+"::"+aaa;
    }
    @GetMapping("/bbb")
    public String demo(){
        return name+"::"+port;
    }
}
           
  1. 查看eureka的服务状态
    注册中心迁移Eureka到Nacos

    aaa和bbb服务各一个实例!

    访问http://localhost:9200/demos/

    结果打印:bbb::9200::aaa::9007

2.双注册中心阶段

一个服务添加为双注册双订阅中心需要两步:

1.配置中添加额外配置

spring:
  # 过滤自动化配置类.多注册中心时需要配置。因为两者都是SpringCloud规范的解决方案,在注入相应的接口实现类时候会出现冲突。所以需要配置
  autoconfigure:
    exclude: org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
           

2.启动类添加注解

//所有自动注册服务的实现类在构造过程中都需要该Bean。所以配置使其生效
@EnableConfigurationProperties({AutoServiceRegistrationProperties.class})
           

3.至此这个服务就变成了双注册中心双订阅的服务。注意:订阅状态时需要添加对应注册中心实现类的Bean,不然不知道注入的是哪个注册中心的实现类。

@Bean//该Bean声明是为了指定Ribbon发现服务时确定从那个注册中心。如果不配置将会报错说理想需要一个,但是却发现了两个
    public ServerIntrospector serverIntrospector(){
        return new NacosServerIntrospector();
    }
           

provider服务:

  1. pom依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
           
  1. 配置文件
server:
  port: 9008
spring:
  application:
    name: aaa
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
  # 过滤自动化配置类.多注册中心时需要配置。因为两者都是SpringCloud规范的解决方案,在注入相应的接口实现类时候会出现冲突。所以需要配置
  autoconfigure:
    exclude: org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
  cloud:
    nacos:
      discovery:
        server-addr: http://localhost:8848/
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
           
  1. 启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigurationProperties({AutoServiceRegistrationProperties.class})//所有自动注册服务的实现类在构造过程中都需要该Bean。所以配置使其生效
//该注解的作用使使用 @ConfigurationProperties 注解的类生效。
public class AApp {
    public static void main(String[] args) {
        SpringApplication.run(AApp.class,args);
    }
}
           
  1. Controller
@RestController
@RequestMapping("/demos")
public class DemoController {
    @Value("${server.port}")
    private Integer port;
    @Value("${spring.application.name}")
    private String name;

    @GetMapping
    public String demos(){
        return name+"::"+port;
    }
}
           

consumer服务: 9021端口

  1. pom依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
           
  1. 配置文件。
server:
  port: 9201
spring:
  application:
    name: bbb
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
  autoconfigure:
    exclude: org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
  cloud:
    nacos:
      discovery:
        server-addr: http://localhost:8848/
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
           
  1. 启动类
@EnableFeignClients
@SpringBootApplication
//@EnableDiscoveryClient(autoRegister = false)//是否将该服务注册到注册中心
@EnableConfigurationProperties({AutoServiceRegistrationProperties.class})
public class BApp {
    public static void main(String[] args) {
        SpringApplication.run(BApp.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    @Bean//该Bean声明是为了指定Ribbon发现服务时确定从那个注册中心。如果不配置将会报错说理想需要一个,但是却发现了两个
    public ServerIntrospector serverIntrospector(){
        return new NacosServerIntrospector();
    }
}
           
  1. Controller
@RestController
@RequestMapping("/demos")
public class DemoController {
    @Value("${server.port}")
    private Integer port;
    @Value("${spring.application.name}")
    private String name;

    @Autowired
    private RestTemplate restTemplate;
//通过使用了Ribbon的RestTemplate模板通过服务名称进行RPC远程调用
    @GetMapping
    public String demos(){
        String aaa = restTemplate.getForObject("http://aaa/demos", String.class);
        return name+"::"+port+"::"+aaa;
    }
    @GetMapping("/bbb")
    public String demo(){
        return name+"::"+port;
    }
}
           
  1. 查看eureka服务状态和nacos服务状态。
    注册中心迁移Eureka到Nacos
    注册中心迁移Eureka到Nacos

访问路径:http://localhost:9021/demos

结果:bbb::9201::aaa::9007 或者bbb::9201::aaa::9008

访问路径:http://localhost:9020/demos

结果:bbb::9200::aaa::9008 或者bbb::9200::aaa::9007

结论:双注册中心已经生效

3.最终状态

  1. 下线端口为9007的provider服务
  2. 下线端口为9200的consumer服务
  3. 关闭Eureka服务端
  4. 访问http://localhost:9021/demos
  5. 结果:bbb::9201::aaa::9008

    至此注册中心替换完成,且没有影响正常代码的执行,不需要重启或者关闭服务就可以实现双注册中心做法。

game over!

继续阅读