为什么 Resilience4j 断路器不启动新线程

Why Resilience4j circuit breaker does not spin up new threads

我正在尝试从 Hystrix 迁移到 Resilience4j 并尝试使用使用 resilience4j-spring-boot2 依赖项的注释 (https://resilience4j.readme.io/docs/getting-started-3) 配置 resilience4j 的选项。

当我测试使用它并分析日志时,即使是用@CircuitBreaker 修饰的方法也在同一个 http-nio 线程中 运行:

带有 CircuitBreaker 注释的日志:


2020-01-10 10:31:15,996 [http-nio-8080-exec-1] INFO APP=test-app |环境=本地 | REQUEST_ID=1 | TRACE_ID=eb88d5c53ab97a40 | SPAN_ID=eb88d5c53ab97a40 | CLIENT_ID=1 | CLIENT_VERSION=1 | a.c.s.i.m.p.dependent.DependentApi - 请求:http://example.api.com/api/customers/John

2020-01-10 10:31:15,997 [http-nio-8080-exec-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID=1 | TRACE_ID=eb88d5c53ab97a40 | SPAN_ID=eb88d5c53ab97a40 | CLIENT_ID=1 | CLIENT_VERSION=1 | a.c.s.i.myservice.aop.LogingAspect - 输入:au.com.suncorp.insurance.myservice.config.DependentApiRestOperation.getRestOperations() with argument[s] = []

2020-01-10 10:31:15,999 [http-nio-8080-exec-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID=1 | TRACE_ID=eb88d5c53ab97a40 | SPAN_ID=eb88d5c53ab97a40 | CLIENT_ID=1 | CLIENT_VERSION=1 | a.c.s.i.myservice.aop.LoggingAspect - 退出:au.com.suncorp.insurance.myservice.config.DependentApiRestOperation.getRestOperations() 结果 = org.springframework.web.client.RestTemplate@1f3111d1

2020-01-10 10:31:16,065 [http-nio-8080-exec-1] 错误 APP=test-app |环境=本地 | REQUEST_ID=1 | TRACE_ID=eb88d5c53ab97a40 | SPAN_ID=eb88d5c53ab97a40 | CLIENT_ID=1 | CLIENT_VERSION=1 | a.c.s.i.myservice.aop.LoggingAspect


相反,当我在这种情况下从 CircuitBreakerFactory 创建 CircuitBreaker 时,当方法内部的控件受断路器保护时,我可以看到新的断路器线程正在旋转。

CircuitBreakerFactory 的日志:


2020-01-10 10:50:04,178 [hystrix-HystrixCircuitBreakerFactory-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID= | TRACE_ID=bde6e74d65833730 | SPAN_ID=d5dc68689645201a | CLIENT_ID= | CLIENT_VERSION= | a.c.s.i.myservice.aop.LoggingAspect - 输入:au.com.suncorp.insurance.myservice.config.properties.DependentApiProperties.getAddress() with argument[s] = []

2020-01-10 10:50:04,178 [hystrix-HystrixCircuitBreakerFactory-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID= | TRACE_ID=bde6e74d65833730 | SPAN_ID=d5dc68689645201a | CLIENT_ID= | CLIENT_VERSION= | a.c.s.i.myservice.aop.LoggingAspect - 退出:au.com.suncorp.insurance.myservice.config.properties.DependentApiProperties.getAddress() 结果 = au.com.suncorp.insurance.myservice.config.properties.DependentApiProperties$Address@1928e7f3

2020-01-10 10:50:04,179 [hystrix-HystrixCircuitBreakerFactory-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID= | TRACE_ID=bde6e74d65833730 | SPAN_ID=d5dc68689645201a | CLIENT_ID= | CLIENT_VERSION= | a.c.s.i.myservice.aop.LoggingAspect - 输入:au.com.suncorp.insurance.myservice.config.properties.DependentApiProperties.getAddress() with argument[s] = []

2020-01-10 10:50:04,179 [hystrix-HystrixCircuitBreakerFactory-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID= | TRACE_ID=bde6e74d65833730 | SPAN_ID=d5dc68689645201a | CLIENT_ID= | CLIENT_VERSION= | a.c.s.i.myservice.aop.LoggingAspect - 退出:au.com.suncorp.insurance.myservice.config.properties.DependentApiProperties.getAddress() 结果 = au.com.suncorp.insurance.myservice.config.properties.DependentApiProperties$Address@1928e7f3

2020-01-10 10:50:04,184 [hystrix-HystrixCircuitBreakerFactory-1] INFO APP=测试应用 |环境=本地 | REQUEST_ID= | TRACE_ID=bde6e74d65833730 | SPAN_ID=d5dc68689645201a | CLIENT_ID= | CLIENT_VERSION= | a.c.s.i.m.p.dependent.DependentApi - 请求:http://example.api.com/api/customers/John

2020-01-10 10:50:04,186 [hystrix-HystrixCircuitBreakerFactory-1] DEBUG APP=测试应用 |环境=本地 | REQUEST_ID= | TRACE_ID=bde6e74d65833730 | SPAN_ID=d5dc68689645201a | CLIENT_ID= | CLIENT_VERSION= | a.c.s.i.myservice.aop.LoggingAspect - 输入:au.com.suncorp.insurance.myservice.config.DependentApiRestOperation.getRestOperations() with argument[s] = []


Resilience4j Spring Boot Starter 和 Spring Cloud CircuitBreaker 是两个 different/seperate 项目。

Spring Cloud CircuitBreaker 在单独的线程池中运行方法。请参阅 -> https://github.com/spring-cloud/spring-cloud-circuitbreaker/blob/master/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java#L68

在 Resilience4j 和 Spring Boot Starter 中,CircuitBreaker 和基于 Threadpool 的 Bulkhead 是两种不同的弹性模式,您可能想要将它们组合或不组合。如果你想组合它们,你必须在你的方法中应用两个注释 -> @CircuitBreaker@Bulkhead(type = Type.THREADPOOL).

看看演示 -> https://github.com/resilience4j/resilience4j-spring-boot2-demo