首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring Cloud Gateway 500实例停机

Spring Cloud Gateway 500实例停机
EN

Stack Overflow用户
提问于 2020-10-20 16:04:43
回答 3查看 1.6K关注 0票数 1

我有一个使用Spring Cloud Load Balancer (Spring Cloud version: Hoxton.SR6)的Spring Cloud Gateway (eureka client)应用程序,我还有一个spring boot应用程序的实例(spring boot 2.3,支持优雅关机) (eureka client)。

当我关闭spring启动服务并通过网关执行请求时,网关会抛出500错误(连接被拒绝),而不是503。503在1-2分钟后出现。

有人能澄清这是否是一种预期的行为吗?

问题似乎来自于eureka-client (在我的例子中是1.9.21版本) AtomicReference<Applications> localRegionApps不经常更新

谢谢!

更新:我决定更深入地检查这个500错误。结果是,如果端口未被使用,我的系统(ubuntu)会给出这个错误:

代码语言:javascript
复制
curl -v localhost:9722
 Rebuilt URL to: localhost:9722/
   Trying 127.0.0.1...
 TCP_NODELAY set
 connect to 127.0.0.1 port 9722 failed: Connection refused
 Failed to connect to localhost port 9722: Connection refused
 Closing connection 0

所以我输入了我的application.yml:

代码语言:javascript
复制
spring:
  cloud:
    gateway:
      routes:
        - id: my_route
          uri: http://localhost:9722/

然后,当我的请求被路由到my_route,并且没有应用程序使用9722时,我会得到一个错误:

代码语言:javascript
复制
io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: localhost/127.0.0.1:9722
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ HTTP GET "/internal/mail/internal/health-check" [ExceptionHandlingWebHandler]
Stack trace:
Caused by: java.net.ConnectException: finishConnect(..) failed: Connection refused
    at io.netty.channel.unix.Errors.throwConnectException(Errors.java:124)
    at io.netty.channel.unix.Socket.finishConnect(Socket.java:251)
    at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.doFinishConnect(AbstractEpollChannel.java:672)
    at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.finishConnect(AbstractEpollChannel.java:649)
    at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.epollOutReady(AbstractEpollChannel.java:529)
    at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:465)
    at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:834)

这似乎是一个意想不到的异常,因为它不可能使用断路器或任何网关过滤器来处理它。

是否有可能正确处理此错误?在这种情况下,我想返回503。

EN

回答 3

Stack Overflow用户

发布于 2021-05-21 02:50:27

将特定异常映射到特定HTTP状态代码的最简单方法之一是提供org.springframework.boot.web.reactive.error.ErrorAttributes类型的自定义bean。下面是一个示例:

代码语言:javascript
复制
@Bean
public ErrorAttributes errorAttributes() {
    return new CustomErrorAttributes(httpStatusExceptionTypeMapper);
}

public class CustomErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
        Map<String, Object> attributes = super.getErrorAttributes(request, options);
        Throwable error = getError(request);
        MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations
            .from(error.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class);
        HttpStatus errorStatus = determineHttpStatus(error, responseStatusAnnotation);
        attributes.put("status", errorStatus.value());
        return attributes;
    }

    private HttpStatus determineHttpStatus(Throwable error, MergedAnnotation<ResponseStatus> responseStatusAnnotation) {
        if (error instanceof ResponseStatusException) {
            return ((ResponseStatusException) error).getStatus();
        }
        return responseStatusAnnotation.getValue("code", HttpStatus.class).orElseGet(() -> {
           if (error instanceof java.net.ConnectException) {
               return HttpStatus.SERVICE_UNAVAILABLE;
           }
           return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2020-10-22 17:11:44

请尝试定义您的自定义ErrorWebExceptionHandler。请参阅:org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler

票数 0
EN

Stack Overflow用户

发布于 2021-09-20 16:24:52

您应该使用Cloud Circuit Breaker

要做到这一点:

  1. 在您的pom中声明相应的starter:

org.springframework.cloud spring-cloud-starter-circuitbreaker-reactor-resilience4j

  1. application.yaml中声明断路器

forward:/inCaseOfFailureUseThis:cloud: gateway: routes:- id: my_route uri:http://localhost:9722/过滤器:- name: CircuitBreaker args: name: myCircuitBreaker fallbackUri: spring

  1. 声明在出现故障(例如,连接错误)时将调用的端点

@ Mono.just(ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("body (“/inCaseOfFailureUseThis”)公共Mono inCaseOfFailureUseThis() {返回服务失败案例的映射“);}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64440951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档