首页 > 解决方案 > 实例关闭时的 Spring Cloud Gateway 500

问题描述

我有一个使用 Spring Cloud 负载均衡器(Spring Cloud 版本:Hoxton.SR6)的 Spring Cloud Gateway(eureka 客户端)应用程序,并且我有一个 spring boot 应用程序实例(启用了正常关闭的 spring boot 2.3,(eureka 客户端)。

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

谁能澄清这是否是预期的行为?

似乎问题来自eureka-client(在我的情况下为1.9.21版本) AtomicReference<Applications> localRegionApps不经常更新

谢谢!

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

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:

spring:
  cloud:
    gateway:
      routes:
        - id: my_route
          uri: http://localhost:9722/

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

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

标签: spring-cloudspring-cloud-gateway

解决方案


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

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

推荐阅读