当一个实例关闭时,Spring Cloud Gateway 500



我有一个Spring Cloud Gateway(eureka客户端(应用程序,它使用Spring Cloud Load Balancer(Spring Cloud版本:Hoxton.SR6(,还有一个Spring boot应用程序的实例(启用优雅关闭的Spring boot 2.3,eureka客户机(。

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

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

问题似乎来自尤里卡客户端(在我的情况下是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

所以我提交了我的申请。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状态代码的最简单方法之一是提供org.springframework.boot.web.reactive.error.ErrorAttributes类型的自定义bean。这里有一个例子:

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

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

您应该使用云断路器。

为此:

  1. 在pom:中声明相应的启动器

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
    </dependency>
    
  2. application.yaml中宣布断路器

    spring:
    cloud:
    gateway:
    routes:
    - id: my_route
    uri: http://localhost:9722/
    filters:
    - name: CircuitBreaker
    args:
    name: myCircuitBreaker
    fallbackUri: forward:/inCaseOfFailureUseThis
    
  3. 声明在发生故障(例如连接错误(时将调用的端点

    @RequestMapping("/inCaseOfFailureUseThis")
    public Mono<ResponseEntity<String>> inCaseOfFailureUseThis() {
    return Mono.just(ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("body for service failure case"));
    }
    

相关内容

  • 没有找到相关文章

最新更新