场景:业务升级,需要将注册中心从eureka转到Nacos。nacos功能更强大,响应更快!
要求:需要在不影响业务的情况下完成注册中心的转换。即不影响代码调用的情况下完成注册中心的替换!!!!
是不是听着都很高大上!!!
先用文字描述一下整个过程然后开始实操!!
注意:两个模块有一个父项目。下边模块的依赖省略了父模块的依赖。父项目pom依赖如下。注意版本间对应关系。如果需要更换版本可以去SpringCloudAlibaba的GitHub上查看对应关系。地址:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.4.RELEASEversion>
parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Greenwich.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
provider服务: 9007端口
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
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);
}
}
/**测试网关路由*/
@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端口
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
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();
}
}
@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.配置中添加额外配置
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服务:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<version>2.1.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
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);
}
}
@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端口
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<version>2.1.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
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();
}
}
@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;
}
}
访问路径:http://localhost:9021/demos
结果:bbb::9201::aaa::9007 或者bbb::9201::aaa::9008
访问路径:http://localhost:9020/demos
结果:bbb::9200::aaa::9008 或者bbb::9200::aaa::9007
结论:双注册中心已经生效
game over!