spring-cloud - 实例关闭时的 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
解决方案
将特定异常映射到特定 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;
}
}
}
推荐阅读
- c - 选择静态而不是全局。为什么?
- c# - 如何将字符串传递给 UWP 应用并从 Windows 窗体应用启动它
- reactjs - 更新 react-dates 的状态
- java - 立即流式下载 csv 文件,无需等待
- jasmine - 在量角器中使用 Winston 记录器实现测试失败
- salesforce - 无法登录沙盒 Salesforce 系统 - 错误:检查 SAML 断言中的无效断言
- haskell - 智能构造函数的 Haskell 编译时检查
- javascript - 如何将指定的值放入相应的位置
- javascript - JavaScript 可以编译成二进制文件吗?
- c# - LocalDb“管道末端没有进程”