本文介绍了使用 Eureka 向 WebFlux 注册微服务时遇到问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java + Spring 应用程序上使用 Netflix Eureka 作为服务发现并获取 HTTP: 503.当地址在代码上固定时,应用程序工作正常.

我试过了:

更改后:

来自服务发现的日志:

2019-12-26 22:46:14.690 INFO 20140 --- [ Thread-10] e.s.EurekaServerInitializerConfiguration :启动尤里卡服务器2019-12-26 22:46:14.718 INFO 20140 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer:Tomcat 在端口上启动:8761 (http),上下文路径为"2019-12-26 22:46:14.719 INFO 20140 --- [主要] .s.c.n.e.s.EurekaAutoServiceRegistration:将端口更新为 87612019-12-26 22:46:14.897 INFO 20140 --- [main] b.c.i.s.ServiceDiscoveryApplication:在 4.839 秒内启动 ServiceDiscoveryApplication(JVM 运行 5.348)2019-12-26 22:46:26.374 INFO 20140 --- [nio-8761-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : 初始化 Spring DispatcherServlet 'dispatcherServlet'2019-12-26 22:46:26.374 INFO 20140 --- [nio-8761-exec-1] o.s.web.servlet.DispatcherServlet:初始化 Servlet 'dispatcherServlet'2019-12-26 22:46:26.379 INFO 20140 --- [nio-8761-exec-1] o.s.web.servlet.DispatcherServlet:在 5 毫秒内完成初始化2019-12-26 22:46:26.530 INFO 20140 --- [nio-8761-exec-2] c.n.e.registry.AbstractInstanceRegistry:注册实例CUSTOMER-SERVICE/customer-service,状态为UP(复制=假)2019-12-26 22:46:27.111 INFO 20140 --- [nio-8761-exec-3] c.n.e.registry.AbstractInstanceRegistry :注册实例 CUSTOMER-SERVICE/customer-service 状态为 UP (replication=true)

我正在处理的原始项目也可以在 GitHub 存储库中找到:

消费者微服务客户服务发现服务发现网关API 网关

解决方案

它对我有用.不确定您的实施中出了什么问题.

这是我尝试过的:

由于我不确定您的 customer-service 项目,我使用以下文件创建了自己的项目:

客户服务申请

@SpringBootApplication@EnableDiscoveryClient公共类客户服务应用{公共静态无效主(字符串 [] args){SpringApplication.run(CustomerServiceApplication.class, args);}}

CustomerServiceController

@RestController("/customers")公共类 CustomerServiceController {@GetMapping("/{id}")public String getId(@PathVariable("id") String id) {返回客户";}}

application.properties

server.port=8081eureka.client.register-with-eureka=trueeureka.client.fetch-registry=truespring.application.name=客户服务eureka.instance.appname=客户服务

来到网关应用程序,我添加了以下文件:

CustomerWebService

@Service公共类 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";@负载均衡私有最终 WebClient.Builder webClient;公共 CustomerWebService(WebClient.Builder webClient) {this.webClient = webClient;}公共单声道findById(字符串ID){返回 webClient.build().得到().uri(baseUrl, id).取回().bodyToMono(String.class);}}

负载均衡器

@Component公共类负载均衡器 {@豆角,扁豆公共 RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder) {返回 routeLocatorBuilder.routes().route("customer-service", route -> route.path("/customers").uri("lb://客户服务")).建造();}@豆角,扁豆@负载均衡公共 WebClient.Builder loadBalancedWebClientBuilder() {返回 WebClient.builder();}}

InstanceListener - 在 eureka heartbeat 上每 30 秒运行一次

@Component公共类 InstanceListener 实现了 ApplicationListener{@自动连线私人 CustomerWebService customerWebService;@覆盖public void onApplicationEvent(HeartbeatEvent 事件) {单声道result = customerWebService.findById("id");结果.订阅(价值 ->System.out.println(值),错误 ->error.printStackTrace());}}

application.properties

eureka.client.enabled=trueeureka.client.register-with-eureka=trueeureka.client.fetch-registry=true

每 30 秒,我就能看到 customer-serviceGateway 发生的呼叫在控制台中显示 Customer 值.

完全按照我所做的尝试,看看它是否有效.让我知道.谢谢

Using Netflix Eureka as a Service Discovery on a Java + Spring application and getting a HTTP: 503.When the address is fixed on the code the application works fine.

I've tried:

SpringDeveloper - Spring Developer Video

Secure Reactive Microservices - Spring Cloud Gateway from Okta Developers

Spring Cloud Hands On - Hands on Spring from Packt

Since I'm using WebFlux I need to use a @LoadBalanced over the WebClient

The service discovery 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>

The service discovery properties:

server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

The service discovery 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);
    }
}

The Gateway pom.xml (same , and from the Service Discovery 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>

The Gateway 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

The configuration Class for the Gateway:

@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();
    }

}

The service 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);
    }
}

When I try to execute a GET from the provider service I get the following:

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:

This is the output from: 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>

And a picture from http://localhost:8761/After Changes:

The log from Service Discovery:

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)

The original project that I'm working on can also be found on GitHub repositories:

ConsumerMicroservice CustomerService DiscoveryService DiscoveryGatewayAPI Gateway

解决方案

It is working for me. Not sure what went wrong in your implementation.

Here is what I tried:

Since I am not sure of your customer-service project, I created my own with following files:

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

Coming to Gateway application, I added the following files:

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 - runs every 30 seconds on eureka heartbeat

@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

Every 30 seconds, I was able to see call happening to customer-service and Gateway displaying Customer value in console.

Try exactly what I did and see if it is working. Let me know. thanks

这篇关于使用 Eureka 向 WebFlux 注册微服务时遇到问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-17 13:56