使用 Eureka 向 WebFlux 注册微服务时遇到问题
Trouble using Eureka to register a microservice with WebFlux
在 Java
+ Spring
应用程序上使用 Netflix Eureka 作为服务发现并获得 HTTP: 503
。
当地址固定在代码上时,应用程序可以正常工作。
我试过:
SpringDeveloper - Spring 开发者视频
Secure Reactive Microservices - Spring 来自 Okta Developers 的云网关
Spring Cloud Hands On - 来自 Packt
的实践 Spring
由于我使用的是 WebFlux
我需要在 WebClient
上使用 @LoadBalanced
服务发现pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<properties>
<java.version>11</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.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
服务发现属性:
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
服务发现main
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class ServiceDiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceDiscoveryApplication.class, args);
}
}
网关pom.xml
(相同,来自服务发现pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
</dependencies>
网关application.properties
:
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.application.name=gateway
server.port=8080
spring.cloud.loadbalancer.ribbon.enabled=false
网关的配置 Class:
@Component
public class LoadBalancers {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
return routeLocatorBuilder.routes()
.route("customer-service", route -> route.path("/customers")
.uri("lb://customer-service"))
.route("property-service", route -> route.path("/property")
.uri("lb://property-service"))
.build();
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder(){
return WebClient.builder();
}
}
服务class:
@Service
public class CustomerWebService {
private static final String CUSTOMERS_WITH_ID = "/customers/{id}";
private static final String CUSTOMER_ROOT_ENDPOINT = "/customers";
private String baseUrl = "lb://customer-service/customers";
@LoadBalanced
private final WebClient.Builder webClient;
public CustomerWebService(WebClient.Builder webClient) {
this.webClient = webClient;
}
public Mono<Customer> findById(String id){
return webClient.build()
.get()
.uri(baseUrl, id)
.retrieve()
.bodyToMono(Customer.class);
}
}
当我尝试从提供商服务执行 GET
时,我得到以下信息:
2019-12-25 20:23:13.737 INFO 9552 --- [main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2019-12-25 20:23:13.738 INFO 9552 --- [main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8080
2019-12-25 20:23:14.082 INFO 9552 --- [main] b.c.i.webportal.WebportalApplication : Started WebportalApplication in 4.582 seconds (JVM running for 5.051)
2019-12-25 20:23:35.015 WARN 9552 --- [ctor-http-nio-3] o.s.c.l.core.RoundRobinLoadBalancer : No servers available for service: customer-service
2019-12-25 20:23:35.016 WARN 9552 --- [ctor-http-nio-3] eactorLoadBalancerExchangeFilterFunction : Load balancer does not contain an instance for the service customer-service
2019-12-25 20:23:35.077 ERROR 9552 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [e3de4777] 500 Server Error for HTTP GET "/v1/customers"
org.springframework.web.reactive.function.client.WebClientResponseException$ServiceUnavailable: 503 Service Unavailable from UNKNOWN
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:207) ~[spring-webflux-5.2.1.RELEASE.jar:5.2.1.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ? 503 from GET lb://customer-service/customers [DefaultWebClient]
|_ checkpoint ? Handler br.com.imobiliariaype.webportal.controller.CustomerController#findAll() [DispatcherHandler]
|_ checkpoint ? org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ? HTTP GET "/v1/customers" [ExceptionHandlingWebHandler]
Stack trace:
这是来自的输出:http://localhost:8761/eureka/apps
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>CUSTOMER-SERVICE</name>
<instance>
<instanceId>WORKSTATION.mshome.net:customer-service:8060</instanceId>
<hostName>WORKSTATION.mshome.net</hostName>
<app>CUSTOMER-SERVICE</app>
<ipAddr>SOMEIP</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8060</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1577402896307</registrationTimestamp>
<lastRenewalTimestamp>1577403016236</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1577402895709</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8060</management.port>
</metadata>
<homePageUrl>http://WORKSTATION.mshome.net:8060/</homePageUrl>
<statusPageUrl>http://WORKSTATION.mshome.net:8060/actuator/info</statusPageUrl>
<healthCheckUrl>http://WORKSTATION.mshome.net:8060/actuator/health</healthCheckUrl>
<vipAddress>customer-service</vipAddress>
<secureVipAddress>customer-service</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1577402896307</lastUpdatedTimestamp>
<lastDirtyTimestamp>1577402895638</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
还有一张来自 http://localhost:8761/
的图片
更改后:
来自服务发现的日志:
2019-12-26 22:46:14.690 INFO 20140 --- [ Thread-10] e.s.EurekaServerInitializerConfiguration : Started Eureka Server
2019-12-26 22:46:14.718 INFO 20140 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8761 (http) with context path ''
2019-12-26 22:46:14.719 INFO 20140 --- [ main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8761
2019-12-26 22:46:14.897 INFO 20140 --- [ main] b.c.i.s.ServiceDiscoveryApplication : Started ServiceDiscoveryApplication in 4.839 seconds (JVM running for 5.348)
2019-12-26 22:46:26.374 INFO 20140 --- [nio-8761-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-12-26 22:46:26.374 INFO 20140 --- [nio-8761-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-12-26 22:46:26.379 INFO 20140 --- [nio-8761-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
2019-12-26 22:46:26.530 INFO 20140 --- [nio-8761-exec-2] c.n.e.registry.AbstractInstanceRegistry : Registered instance CUSTOMER-SERVICE/customer-service with status UP (replication=false)
2019-12-26 22:46:27.111 INFO 20140 --- [nio-8761-exec-3] c.n.e.registry.AbstractInstanceRegistry : Registered instance CUSTOMER-SERVICE/customer-service with status UP (replication=true)
我正在处理的原始项目也可以在 GitHub 存储库中找到:
消费者
Microservice Customer
服务发现
Service Discovery
网关
API Gateway
它对我有用。不确定您的实施出了什么问题。
这是我尝试过的:
由于我不确定您的 customer-service
项目,我使用以下文件创建了自己的项目:
CustomerServiceApplication
@SpringBootApplication
@EnableDiscoveryClient
public class CustomerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerServiceApplication.class, args);
}
}
CustomerServiceController
@RestController("/customers")
public class CustomerServiceController {
@GetMapping("/{id}")
public String getId(@PathVariable("id") String id) {
return "Customer";
}
}
application.properties
server.port=8081
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
spring.application.name=customer-service
eureka.instance.appname=customer-service
来到网关应用程序,我添加了以下文件:
CustomerWebService
@Service
public class CustomerWebService {
private static final String CUSTOMERS_WITH_ID = "/customers/{id}";
private static final String CUSTOMER_ROOT_ENDPOINT = "/customers";
private String baseUrl = "lb://customer-service/customers";
@LoadBalanced
private final WebClient.Builder webClient;
public CustomerWebService(WebClient.Builder webClient) {
this.webClient = webClient;
}
public Mono<String> findById(String id) {
return webClient.build()
.get()
.uri(baseUrl, id)
.retrieve()
.bodyToMono(String.class);
}
}
LoadBalancers
@Component
public class LoadBalancers {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder) {
return routeLocatorBuilder.routes()
.route("customer-service", route -> route.path("/customers")
.uri("lb://customer-service"))
.build();
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
InstanceListener
- 在 eureka 心跳上每 30 秒运行一次
@Component
public class InstanceListener implements ApplicationListener<HeartbeatEvent> {
@Autowired
private CustomerWebService customerWebService;
@Override
public void onApplicationEvent(HeartbeatEvent event) {
Mono<String> result = customerWebService.findById("id");
result.subscribe(
value -> System.out.println(value),
error -> error.printStackTrace()
);
}
}
application.properties
eureka.client.enabled=true
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
每隔 30 秒,我就能看到对 customer-service
和 Gateway
的调用在控制台中显示 Customer
值。
完全按照我的方法进行尝试,看看它是否有效。让我知道。谢谢
我遇到了同样的问题,发现它恰好是因为 WebClient.Builder bean 中缺少 @LoadBalanced 注释。我在应用程序 Class 中定义如下:
@SpringBootApplication
@EnableEurekaClient
public class MovieCatalogueServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MovieCatalogueServiceApplication.class, args);
}
@Bean
@LoadBalanced
public WebClient.Builder getWebClientBuilder() {
return WebClient.builder();
}
}
在 Java
+ Spring
应用程序上使用 Netflix Eureka 作为服务发现并获得 HTTP: 503
。
当地址固定在代码上时,应用程序可以正常工作。
我试过:
SpringDeveloper - Spring 开发者视频
Secure Reactive Microservices - Spring 来自 Okta Developers 的云网关
Spring Cloud Hands On - 来自 Packt
的实践 Spring由于我使用的是 WebFlux
我需要在 WebClient
@LoadBalanced
服务发现pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<properties>
<java.version>11</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.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
服务发现属性:
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
服务发现main
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class ServiceDiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceDiscoveryApplication.class, args);
}
}
网关pom.xml
(相同,来自服务发现pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
</dependencies>
网关application.properties
:
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.application.name=gateway
server.port=8080
spring.cloud.loadbalancer.ribbon.enabled=false
网关的配置 Class:
@Component
public class LoadBalancers {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
return routeLocatorBuilder.routes()
.route("customer-service", route -> route.path("/customers")
.uri("lb://customer-service"))
.route("property-service", route -> route.path("/property")
.uri("lb://property-service"))
.build();
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder(){
return WebClient.builder();
}
}
服务class:
@Service
public class CustomerWebService {
private static final String CUSTOMERS_WITH_ID = "/customers/{id}";
private static final String CUSTOMER_ROOT_ENDPOINT = "/customers";
private String baseUrl = "lb://customer-service/customers";
@LoadBalanced
private final WebClient.Builder webClient;
public CustomerWebService(WebClient.Builder webClient) {
this.webClient = webClient;
}
public Mono<Customer> findById(String id){
return webClient.build()
.get()
.uri(baseUrl, id)
.retrieve()
.bodyToMono(Customer.class);
}
}
当我尝试从提供商服务执行 GET
时,我得到以下信息:
2019-12-25 20:23:13.737 INFO 9552 --- [main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2019-12-25 20:23:13.738 INFO 9552 --- [main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8080
2019-12-25 20:23:14.082 INFO 9552 --- [main] b.c.i.webportal.WebportalApplication : Started WebportalApplication in 4.582 seconds (JVM running for 5.051)
2019-12-25 20:23:35.015 WARN 9552 --- [ctor-http-nio-3] o.s.c.l.core.RoundRobinLoadBalancer : No servers available for service: customer-service
2019-12-25 20:23:35.016 WARN 9552 --- [ctor-http-nio-3] eactorLoadBalancerExchangeFilterFunction : Load balancer does not contain an instance for the service customer-service
2019-12-25 20:23:35.077 ERROR 9552 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [e3de4777] 500 Server Error for HTTP GET "/v1/customers"
org.springframework.web.reactive.function.client.WebClientResponseException$ServiceUnavailable: 503 Service Unavailable from UNKNOWN
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:207) ~[spring-webflux-5.2.1.RELEASE.jar:5.2.1.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ? 503 from GET lb://customer-service/customers [DefaultWebClient]
|_ checkpoint ? Handler br.com.imobiliariaype.webportal.controller.CustomerController#findAll() [DispatcherHandler]
|_ checkpoint ? org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ? HTTP GET "/v1/customers" [ExceptionHandlingWebHandler]
Stack trace:
这是来自的输出:http://localhost:8761/eureka/apps
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>CUSTOMER-SERVICE</name>
<instance>
<instanceId>WORKSTATION.mshome.net:customer-service:8060</instanceId>
<hostName>WORKSTATION.mshome.net</hostName>
<app>CUSTOMER-SERVICE</app>
<ipAddr>SOMEIP</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8060</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1577402896307</registrationTimestamp>
<lastRenewalTimestamp>1577403016236</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1577402895709</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8060</management.port>
</metadata>
<homePageUrl>http://WORKSTATION.mshome.net:8060/</homePageUrl>
<statusPageUrl>http://WORKSTATION.mshome.net:8060/actuator/info</statusPageUrl>
<healthCheckUrl>http://WORKSTATION.mshome.net:8060/actuator/health</healthCheckUrl>
<vipAddress>customer-service</vipAddress>
<secureVipAddress>customer-service</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1577402896307</lastUpdatedTimestamp>
<lastDirtyTimestamp>1577402895638</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
还有一张来自 http://localhost:8761/
的图片
来自服务发现的日志:
2019-12-26 22:46:14.690 INFO 20140 --- [ Thread-10] e.s.EurekaServerInitializerConfiguration : Started Eureka Server
2019-12-26 22:46:14.718 INFO 20140 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8761 (http) with context path ''
2019-12-26 22:46:14.719 INFO 20140 --- [ main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8761
2019-12-26 22:46:14.897 INFO 20140 --- [ main] b.c.i.s.ServiceDiscoveryApplication : Started ServiceDiscoveryApplication in 4.839 seconds (JVM running for 5.348)
2019-12-26 22:46:26.374 INFO 20140 --- [nio-8761-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-12-26 22:46:26.374 INFO 20140 --- [nio-8761-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-12-26 22:46:26.379 INFO 20140 --- [nio-8761-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
2019-12-26 22:46:26.530 INFO 20140 --- [nio-8761-exec-2] c.n.e.registry.AbstractInstanceRegistry : Registered instance CUSTOMER-SERVICE/customer-service with status UP (replication=false)
2019-12-26 22:46:27.111 INFO 20140 --- [nio-8761-exec-3] c.n.e.registry.AbstractInstanceRegistry : Registered instance CUSTOMER-SERVICE/customer-service with status UP (replication=true)
我正在处理的原始项目也可以在 GitHub 存储库中找到:
消费者 Microservice Customer 服务发现 Service Discovery 网关 API Gateway
它对我有用。不确定您的实施出了什么问题。
这是我尝试过的:
由于我不确定您的 customer-service
项目,我使用以下文件创建了自己的项目:
CustomerServiceApplication
@SpringBootApplication
@EnableDiscoveryClient
public class CustomerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerServiceApplication.class, args);
}
}
CustomerServiceController
@RestController("/customers")
public class CustomerServiceController {
@GetMapping("/{id}")
public String getId(@PathVariable("id") String id) {
return "Customer";
}
}
application.properties
server.port=8081
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
spring.application.name=customer-service
eureka.instance.appname=customer-service
来到网关应用程序,我添加了以下文件:
CustomerWebService
@Service
public class CustomerWebService {
private static final String CUSTOMERS_WITH_ID = "/customers/{id}";
private static final String CUSTOMER_ROOT_ENDPOINT = "/customers";
private String baseUrl = "lb://customer-service/customers";
@LoadBalanced
private final WebClient.Builder webClient;
public CustomerWebService(WebClient.Builder webClient) {
this.webClient = webClient;
}
public Mono<String> findById(String id) {
return webClient.build()
.get()
.uri(baseUrl, id)
.retrieve()
.bodyToMono(String.class);
}
}
LoadBalancers
@Component
public class LoadBalancers {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder) {
return routeLocatorBuilder.routes()
.route("customer-service", route -> route.path("/customers")
.uri("lb://customer-service"))
.build();
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
InstanceListener
- 在 eureka 心跳上每 30 秒运行一次
@Component
public class InstanceListener implements ApplicationListener<HeartbeatEvent> {
@Autowired
private CustomerWebService customerWebService;
@Override
public void onApplicationEvent(HeartbeatEvent event) {
Mono<String> result = customerWebService.findById("id");
result.subscribe(
value -> System.out.println(value),
error -> error.printStackTrace()
);
}
}
application.properties
eureka.client.enabled=true
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
每隔 30 秒,我就能看到对 customer-service
和 Gateway
的调用在控制台中显示 Customer
值。
完全按照我的方法进行尝试,看看它是否有效。让我知道。谢谢
我遇到了同样的问题,发现它恰好是因为 WebClient.Builder bean 中缺少 @LoadBalanced 注释。我在应用程序 Class 中定义如下:
@SpringBootApplication
@EnableEurekaClient
public class MovieCatalogueServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MovieCatalogueServiceApplication.class, args);
}
@Bean
@LoadBalanced
public WebClient.Builder getWebClientBuilder() {
return WebClient.builder();
}
}