首页 > 解决方案 > 带有 Hystrix 断路器超时的 Spring Cloud Feign 客户端默认为 2 秒

问题描述

可通过 GitHub 上的项目重现:spring-cloud-feign-hystrix-timeout-problem


我正在将 Spring Boot2.3.1.RELEASE与 Spring Cloud 一起使用Hoxton.SR6。即没有 Zuul 和 Eureka 的 Feign 客户端和 Hystrix 来获取 REST 响应。

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-dependencies</artifactId>
   <version>Hoxton.SR6</version>
   <type>pom</type>
   <scope>import</scope>
</dependency>

然后我在 Spring Boot 之上使用以下依赖项2.3.1.RELEASESpring Cloud Hoxton.SR6

我启用@EnableFeignClients@EnableCircuitBreaker使用@FeignClient带有简单回退的 a 来记录和重新抛出异常:

@FeignClient(name="my-feign", url = "${feign.url}", fallbackFactory = MyFallbackFactory.class) {
public interface MyFeignClient {

    @PostMapping(value = "/api/dto")
    postDto(@RequestBody Dto dto);
}

使用以下application.yml超时时间约为1 秒,因为 Hystrix 默认为相同的值:

feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

11:52:05.493 INFO 10200 --- [nio-8060-exec-2] com.mycompany.rest.MyController:现在调用 REST!

11:52:06.538 错误 24044 --- [nio-8060-exec-1] oaccC[.[.[/].[dispatcherServlet]:Servlet.service() 用于路径 [] 上下文中的 servlet [dispatcherServlet] 引发异常[请求处理失败;嵌套异常是 com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient#postDto(Dto) timed-out and fallback failed.] 根本原因


我试过什么?

只要我添加以下几行将超时时间增加到 60 秒,超时就会有效地变为2 秒左右

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 60000

11:53:33.590 INFO 16052 --- [nio-8060-exec-2] com.mycompany.rest.MyController:现在调用 REST!

11:53:35.614 错误 16052 --- [nio-8060-exec-2] oaccC[.[.[/].[dispatcherServlet] :Servlet.service() 用于路径 [] 上下文中的 servlet [dispatcherServlet] 引发异常[请求处理失败;嵌套异常是 com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient#postDto(Dto) failed and fallback failed.] 根本原因

只要增加了 Hystrix 读取/连接超时,该调用就会在2 秒内立即进入回退状态。但是,只要我在超时中声明它,我希望达到5 秒。feign.client.config.default...我觉得我缺少另一个配置。

问:如何增加超时?


编辑:

标签: javaspring-bootspring-cloudhystrixspring-cloud-feign

解决方案


您的配置是正确的,您所描述的是预期的行为。这里的问题是Connection refused在您配置的超时后不会抛出异常 - 10 秒。相反,它会在 Java 的内部套接字实现发现服务器主机不可访问后立即抛出。在最简单的情况下,您调用的服务器没有启动并运行。

至于为什么设置 hystrix 超时后会有第二次增加,你可以调试 hystrix 的调用堆栈,发现HystrixRuntimeException不是以相同的顺序抛出。

在您的自定义 hystrix 超时之前,hystrix 的默认超时时间为 1 秒,这意味着此运行时异常总是在执行结束后一秒抛出一次,无论请求是成功还是失败。所以在你的情况下,Connection refused很可能发生在HystrixTimeoutException. 在您将超时设置为比 feign 客户端更长的时间后,HystrixTimeoutException仅在抛出 feign 异常创建(由于“连接被拒绝”),因此延迟。

// 'cause' should be different due to timing
public HystrixRuntimeException(... Exception cause, Throwable fallbackException)

为了模拟超时,我想说您可以在服务器上强制超时,例如Thread.sleep(6000)在服务器端停止执行,或者在调试器上简单地做一个断点。


推荐阅读