注册中心迁移
-
- 双注册双订阅中心
- 注册中心迁移
- Eureka到Nacos
-
- 1. 初始阶段:Eureka单注册中心环境
- 2.双注册中心阶段
- 3.最终状态
双注册双订阅中心
注册中心迁移
Eureka到Nacos
- 场景:业务升级,需要将注册中心从eureka转到Nacos。nacos功能更强大,响应更快!
- 要求:需要在不影响业务的情况下完成注册中心的转换。即不影响代码调用的情况下完成注册中心的替换!!!!
是不是听着都很高大上!!!
先用文字描述一下整个过程然后开始实操!!
- 初始阶段。eureka作为注册中心,provider完成服务注册并对外提供访问。consumer完成调用provider的相关服务。(consumer可注册可不注册,但是需要连接注册中心)
- 双注册中心阶段。用来做过渡
- 为服务provider上线一个新的实例,该实例即注册到eureka又注册到nacos。provider在eureka有两个实例。
- 下线旧的provider实例,即之注册到eureka的那个实例。这是consumer依旧可以访问到provider存活的另一个实例。
- 为服务consumer上线一个新的实例,该实例即注册到eureka又注册到nacos。consumer在eureka有两个实例。
- 下线旧的consumer。此时依旧可以使用存活的双注册实例访问provider服务。
- 完成转换:下线eureka服务中心。使用nacos完成替换。此时可以provider和consumer服务只和nacos进行交互
- 至此完成注册中心的替换!注意:关于服务之间的调用模式使用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端口
- 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>
- 配置文件
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
- 启动类
@SpringBootApplication
public class AApp {
public static void main(String[] args) {
SpringApplication.run(AApp.class,args);
}
}
- 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端口
- 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>
- 配置文件
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
- 启动类
@EnableFeignClients
@SpringBootApplication
public class BApp {
public static void main(String[] args) {
SpringApplication.run(BApp.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 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;
}
}
- 查看eureka的服务状态
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服务:
- 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>
- 配置文件
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
- 启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigurationProperties({AutoServiceRegistrationProperties.class})//所有自动注册服务的实现类在构造过程中都需要该Bean。所以配置使其生效
//该注解的作用使使用 @ConfigurationProperties 注解的类生效。
public class AApp {
public static void main(String[] args) {
SpringApplication.run(AApp.class,args);
}
}
- 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端口
- 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>
- 配置文件。
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
- 启动类
@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();
}
}
- 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;
}
}
- 查看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.最终状态
- 下线端口为9007的provider服务
- 下线端口为9200的consumer服务
- 关闭Eureka服务端
- 访问http://localhost:9021/demos
-
结果:bbb::9201::aaa::9008
至此注册中心替换完成,且没有影响正常代码的执行,不需要重启或者关闭服务就可以实现双注册中心做法。
game over!