Spring 带有 Hystrix 断路器超时的 Cloud Feign 客户端默认为 2 秒
Spring Cloud Feign client with Hystrix circuit-breaker timeout defaults in 2 seconds
可通过 GitHub 上的项目重现:spring-cloud-feign-hystrix-timeout-problem
我正在使用 Spring 引导 2.3.1.RELEASE
和 Spring 云 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.RELEASE
和 Spring 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 INFO 10200 --- [nio-8060-exec-2] com.mycompany.rest.MyController : Calling REST right now!
11:52:06.538 ERROR 24044 --- [nio-8060-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient#postDto(Dto) timed-out and fallback failed.] with root cause
我尝试了什么?
只要我添加以下行以将超时增加到 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 : Calling REST right now!
11:53:35.614 ERROR 16052 --- [nio-8060-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient#postDto(Dto) failed and fallback failed.] with root cause
只要 Hystrix read/connect 超时增加,调用就会在 2 秒 后进入后备状态。但是,只要我在 feign.client.config.default...
超时中声明它,我希望达到 5 秒 。我觉得我缺少另一个配置。
问:如何增加超时时间?
编辑:
mvn dependency:tree
: https://pastebin.com/LJFGaMTc
pom.xml
: https://pastebin.com/98uXHTaR
- 堆栈跟踪:https://pastebin.com/7rQweC8w
你可以尝试的一件事是在一行中定义 Hystrix 超时的配置 属性(我知道它应该等同于你在 YAML 文件中提出的嵌套定义,但有时我遇到仅以这种方式加载的属性)。正如您可以在他们的测试中see,这是Spring Cloud 本身配置Hystrix 超时的方式:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
此外,虽然您表示您没有使用 Zuul 或 Eureka,但请验证您是否以任何方式使用 Ribbon,Hystrix 和 Ribbon 超时之间存在一些依赖关系(请参阅 https://github.com/Netflix/Hystrix/issues/1778 and https://github.com/spring-cloud/spring-cloud-netflix/issues/1324)。
如果是这样,你必须配置两个库的超时:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
您的配置是正确的,您所描述的是预期的行为。这里的问题是 Connection refused
的异常不会在您配置的超时后抛出 - 10 秒。相反,它会在 Java 的内部套接字实现发现服务器主机不可访问后立即抛出。在最简单的情况下,您调用的服务器未启动并且 运行.
至于为什么设置了hystrix timeout后会第二次增加,可以debug hystrix的调用栈发现HystrixRuntimeException
不是按顺序抛出的
在你自定义的hystrix超时之前,hystrix有一个默认的1秒超时,这意味着这个运行时异常总是在执行失效后一秒抛出一次,不管请求是成功还是失败。所以在你的情况下,Connection refused
很可能发生在 HystrixTimeoutException
之后。将超时设置为比假装客户端的超时时间长后,HystrixTimeoutException
仅在 之后创建 假装异常被抛出(由于“连接被拒绝”),因此延迟.
// 'cause' should be different due to timing
public HystrixRuntimeException(... Exception cause, Throwable fallbackException)
为了模拟超时,我想说你可以在服务器上强制超时,例如 Thread.sleep(6000)
停止服务器端的执行,或者只是在调试器上做一个断点。
可通过 GitHub 上的项目重现:spring-cloud-feign-hystrix-timeout-problem
我正在使用 Spring 引导 2.3.1.RELEASE
和 Spring 云 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.RELEASE
和 Spring 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 INFO 10200 --- [nio-8060-exec-2] com.mycompany.rest.MyController : Calling REST right now!
11:52:06.538 ERROR 24044 --- [nio-8060-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient#postDto(Dto) timed-out and fallback failed.] with root cause
我尝试了什么?
只要我添加以下行以将超时增加到 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 : Calling REST right now!
11:53:35.614 ERROR 16052 --- [nio-8060-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient#postDto(Dto) failed and fallback failed.] with root cause
只要 Hystrix read/connect 超时增加,调用就会在 2 秒 后进入后备状态。但是,只要我在 feign.client.config.default...
超时中声明它,我希望达到 5 秒 。我觉得我缺少另一个配置。
问:如何增加超时时间?
编辑:
mvn dependency:tree
: https://pastebin.com/LJFGaMTcpom.xml
: https://pastebin.com/98uXHTaR- 堆栈跟踪:https://pastebin.com/7rQweC8w
你可以尝试的一件事是在一行中定义 Hystrix 超时的配置 属性(我知道它应该等同于你在 YAML 文件中提出的嵌套定义,但有时我遇到仅以这种方式加载的属性)。正如您可以在他们的测试中see,这是Spring Cloud 本身配置Hystrix 超时的方式:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
此外,虽然您表示您没有使用 Zuul 或 Eureka,但请验证您是否以任何方式使用 Ribbon,Hystrix 和 Ribbon 超时之间存在一些依赖关系(请参阅 https://github.com/Netflix/Hystrix/issues/1778 and https://github.com/spring-cloud/spring-cloud-netflix/issues/1324)。
如果是这样,你必须配置两个库的超时:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
您的配置是正确的,您所描述的是预期的行为。这里的问题是 Connection refused
的异常不会在您配置的超时后抛出 - 10 秒。相反,它会在 Java 的内部套接字实现发现服务器主机不可访问后立即抛出。在最简单的情况下,您调用的服务器未启动并且 运行.
至于为什么设置了hystrix timeout后会第二次增加,可以debug hystrix的调用栈发现HystrixRuntimeException
不是按顺序抛出的
在你自定义的hystrix超时之前,hystrix有一个默认的1秒超时,这意味着这个运行时异常总是在执行失效后一秒抛出一次,不管请求是成功还是失败。所以在你的情况下,Connection refused
很可能发生在 HystrixTimeoutException
之后。将超时设置为比假装客户端的超时时间长后,HystrixTimeoutException
仅在 之后创建 假装异常被抛出(由于“连接被拒绝”),因此延迟.
// 'cause' should be different due to timing
public HystrixRuntimeException(... Exception cause, Throwable fallbackException)
为了模拟超时,我想说你可以在服务器上强制超时,例如 Thread.sleep(6000)
停止服务器端的执行,或者只是在调试器上做一个断点。