【问题标题】:Spring Cloud Gateway - Return 503 when no Service Instance AvailableSpring Cloud Gateway - 没有可用的服务实例时返回 503
【发布时间】:2018-04-23 22:05:39
【问题描述】:

尝试使用通过 Eureka 服务器注册/发现的 Spring Boot 微服务的 Spring Cloud Gateway。设置工作正常,客户端可以毫无问题地通过网关调用发现的服务。

现在,我正在尝试测试客户端调用服务(通过网关)的场景,当前没有可用于服务调用的实例(即服务已关闭)。当我们测试这个场景时,默认行为是客户端收到 500 Internal Server Error 响应。更改此默认行为以返回 503 Service Unavilable 响应的最简单方法是什么?

当前堆栈:

Java 8
Spring Boot 2.0.0.M6 
Spring Cloud 2.0.0.M3
Spring Cloud Starter Eureka 2.0.0.M2 (in Gateway JVM)
Spring Cloud Starter Netflix Ribbon 2.0.0.M3 (in Gateway JVM)
Spring Cloud Starter Netflix Eureka Server 2.0.0.M3 (in Eureka Server JVM)

【问题讨论】:

  • 引发 500 响应的具体异常是什么?
  • @iLikeBreakfast,具体例外是:org.springframework.cloud.gateway.support.NotFoundException: Unable to find instance for test-service-name

标签: spring spring-boot spring-cloud netflix-eureka


【解决方案1】:

最后我们决定保持错误响应不变。即HTTP 500 - Unable to find instance for test-service-name。然而,我们为网关的路由机制添加了功能,在每个路由中包含一个enabled: true|false 标志,现在允许我们根据需要临时启用/禁用对这些微服务的访问。我们正在通过重新构建标有enabled: false 的路线来实现这一点,以在其中包含GatewayFilter 并返回:

Mono.error(new WebRequestException(HttpStatus.SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE",
            "Service is down for maintenance"));

每当调用该 enabled: false 路由时。

WebRequestException 是我们自己的Throwable 类,然后我们在自己的WebExceptionHandler 中截获它,它会根据需要处理ServerWebExchange 的ServerHttpResponse。

注意 1:网关在内部使用spring-boot-starter-webflux。

注意 2:每当我们改变 Route 的 enabled 标志的状态时,我们:1) 重新构建 Route,2) 调用 CachingRouteLocator Bean 的 .refresh() 方法以获取 Route在没有GatewayFilter 的情况下重新缓存。

【讨论】:

    【解决方案2】:

    这个问题很相似:

    https://stackoverflow.com/a/69257852/12952273

    但以不同的方式询问。

    有一种称为断路器的模式,它有助于避免级联故障(如果被调用的服务没有响应,则可能发生级联故障)

    https://martinfowler.com/bliki/CircuitBreaker.html

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    【解决方案3】:

    这可能有点老套,但为什么不添加controller advice?像这样的东西应该能让你到达那里。

    @ControllerAdvice
    public class ServiceNotFoundHandler {
        @ExceptionHandler(NotFoundException.class)
        @ResponseBody
        @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
        public String handleUnavailableService(NotFoundException e) {
            return "service unavailable";
        }
    }
    

    【讨论】:

    • ControllerAdvice 不适用于 Spring Cloud Gateway。
    猜你喜欢
    • 2019-12-26
    • 2021-05-10
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2019-07-04
    • 1970-01-01
    相关资源
    最近更新 更多