Spring Cloud Feign客户端的Hystrix断路器超时默认为2秒



可通过GitHub上的项目进行复制:spring-cloud foreign-hystrix超时问题


我使用Spring Boot2.3.1.RELEASE和Spring CloudHoxton.SR6。即Feign客户端和Hystrix没有Zuul和Eureka来获取REST响应。

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

然后在Spring Boot2.3.1.RELEASESpring Cloud Hoxton.SR6之上使用以下依赖项:

  • org.springframework.boot:spring-boot-starter
  • org.springframework.boot:spring-boot-starter-web
  • org.springframework.cloud:spring-cloud-starter-openfeign
  • org.springframework.cloud:spring-cloud-starter-netflix-hystrix

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

@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信息10200-[nio-8060-exec-2]com.mycompany.rest.MyController:正在调用rest!

11:52:06.538错误24044---[nio-8060-exec-1]o.a.c.c.c.[.[./].[dispatcherServlet]:Servlet[dispatcherServlet的Servlet.service((在路径为[]的上下文中引发异常[请求处理失败;嵌套异常为com.netflix.hystrix.exception.HystrixRuntimeException:MyFeignClient#postDto(Dto(超时,回退失败。]


我尝试了什么

只要我添加以下几行将超时时间增加到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]o.a.c.c.c.[.[./].[dispatcherServlet]的Servlet.service((在路径为[]的上下文中抛出异常[请求处理失败;嵌套异常为com.netflix。hystrix.exception.HystrixRuntimeException:MyFeignClient#postDto(Dto(失败,回退失败。]

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

问:如何增加超时


编辑:

  • mvn dependency:tree:https://pastebin.com/LJFGaMTc
  • pom.xml:https://pastebin.com/98uXHTaR
  • 堆栈跟踪:https://pastebin.com/7rQweC8w

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

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

在您的自定义hystrix超时之前,hystrix的默认超时为1秒,这意味着无论请求成功还是失败,自执行失效以来,此运行时异常总是在1秒内抛出一次。所以在你的情况下,Connection refused很可能发生在HystrixTimeoutException之后。将超时时间设置为比外部客户端的超时时间长后,只有在引发外部异常(由于"拒绝连接"(后才会创建HystrixTimeoutException,因此会延迟。

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

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

您可以尝试在一行中定义Hystrix超时的配置属性(我知道它应该相当于您在YAML文件中提出的嵌套定义,但有时我会遇到仅以这种方式加载的属性(。正如你在他们的测试中看到的,这就是Spring Cloud自己配置Hystrix超时的方式:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

此外,尽管您表示没有使用Zuul或Eureka,请验证您是否以任何方式使用Ribbon,是否存在一些依赖关系(请参阅https://github.com/Netflix/Hystrix/issues/1778和https://github.com/spring-cloud/spring-cloud-netflix/issues/1324)在Hystrix和Ribbon超时之间。

如果是这种情况,您必须配置两个库的超时:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000

最新更新