基于Eureka、Nacos 实现双注册双订阅
本文基于SpringCloud Hoxton.RELEASE来演示,nacos部署可以参考官方。双注册双订阅模型如下:
项目列表如下:
项目 | 描述 | 端口 |
---|---|---|
spring-cloud-netflix-eureka-server | eureka server | 8761 |
spring-cloud-eureka-nacos-provider | provider 服务提供方-注册到nacos和eureka | 8082 |
spring-cloud-eureka-nacos-consumer | consumer 服务消费方-订阅nacos和eureka 服务 | 8081 |
spring-cloud-netflix-eureka-server 项目
- pom文件 核心依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 代码
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class, args);
}
}
- application.properties
spring.application.name=eureka-server
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring-cloud-eureka-nacos-provider 项目
- pom.xml
<properties>
<java.version>1.8</java.version>
<spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<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>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 代码
@SpringBootApplication
// 关键点:排除ServiceRegistryAutoConfiguration、AutoServiceRegistrationAutoConfiguration后,需要扫描到AutoServiceRegistrationProperties属性配置
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
public class EurekaNacosProvider {
public static void main(String[] args) {
SpringApplication.run(EurekaNacosProvider.class, args);
}
@RestController
class EchoController {
@GetMapping("/echo")
public String echo(HttpServletRequest request) {
return "echo: " + request.getParameter("name");
}
}
}
- application.properties
spring.application.name=my-provider
server.port=8082
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 关键点:不排除会报错
spring.autoconfigure.exclude=org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
spring-cloud-eureka-nacos-consumer
- pom.xml
<properties>
<java.version>1.8</java.version>
<spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
</properties>
<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>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 代码
@SpringBootApplication
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
public class EurekaNacosConsumer {
public static void main(String[] args) {
SpringApplication.run(EurekaNacosConsumer.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@RestController
class HelloController {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
private String serviceName = "my-provider";
@GetMapping("/hello")
public String hello() {
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
ServiceInstance serviceInstance = serviceInstances.stream()
.findAny().orElseThrow(() ->
new IllegalStateException("no " + serviceName + " instance available"));
return restTemplate.getForObject(
"http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() +
"/echo?name=nacos", String.class);
}
}
}
- application.properties
spring.application.name=my-consumer
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 关键点:不排除会报错
spring.autoconfigure.exclude=org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
ServiceInstanceChooser
三个项目启动成功
- nacos截图如下:
- eureka 截图如下:
此时已实现Eureka、Nacos 双注册双订阅
遇到的坑
- ServiceRegistryAutoConfiguration$ServiceRegistryEndpointConfiguration required a single bean, but 2 were found 错误
***************************
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]
出现这个原因是因为RegistryEndpointConfiguration 在实例化的时候,发现两个registration bean。如果要解决这个问题就要排除ServiceRegistryAutoConfiguration、AutoServiceRegistrationAutoConfiguration这两个类。大家可以会疑问为啥还要排除AutoServiceRegistrationAutoConfiguration
,这是因为AutoServiceRegistrationAutoConfiguration 依赖ServiceRegistryAutoConfiguration。
从SpringCloud.Greenwich.RELEASE版本后就不需要用@EnableDiscoveryClient来启用DiscoveryClient服务发现和注册。