[英]Spring Boot Resilience4J Annotation Not Opening Circuit
I've checked the questions on the site about Resilience4J, but have not had any luck with their answers.我已经检查了网站上有关 Resilience4J 的问题,但他们的答案没有任何运气。 I'm trying to implement
@CircuitBreaker
annotation from Resilience4J in my Spring Boot 2.x project.我正在尝试在我的 Spring Boot 2.x 项目中实现来自 Resilience4J 的
@CircuitBreaker
注释。 The circuit breaker is implemented around a pretty straightforward function.断路器是围绕一个非常简单的 function 实现的。 However, when I supply a bad URL, the circuit is not opening, no matter how many times I send the request.
但是,当我提供一个坏的 URL 时,无论我发送多少次请求,电路都不会打开。 I've gone so far as to extract everything into a standalone application and run it 100 times and observe it just endlessly failing.
我什至将所有内容提取到一个独立的应用程序中并运行 100 次,然后观察它只是无休止地失败。 Any idea what I'm doing wrong?
知道我做错了什么吗?
@CircuitBreaker(name = "backendA")
@Component
public class ResilientClient {
private HttpClient httpClient;
private static final Logger log = LoggerFactory.getLogger(ResilientClient.class);
public ResilientClient() {
httpClient = HttpClient.newBuilder().build();
}
@Bulkhead(name = "backendA")
public String processPostRequest(String body, String[] headers, String url) {
HttpResponse<String> response = null;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.POST(HttpRequest.BodyPublishers.ofString(body))
.headers(headers)
.build();
try {
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "This is a remote exception");
} catch (InterruptedException e) {
e.printStackTrace();
log.error("Interrupted Exception: " + e.getLocalizedMessage(), e);
}
return response != null ? response.body() : null;
};
// None of these functions ever get invoked
private String fallback(Throwable e){
log.info("generic throwable caught");
return "generic result";
}
private String fallback(String param1, String[] headers, String url, Throwable e) {
log.info("Fallback method invoked for Throwable: " + param1);
return null;
}
private String fallback(String param1, String[] headers, String url, ConnectException e) {
log.info("Fallback method invoked for ConnectException: " + param1);
return null;
}
}
The config file is taken directly from the Github example配置文件直接取自 Github 示例
resilience4j.circuitbreaker:
configs:
default:
registerHealthIndicator: false
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 2s
failureRateThreshold: 50
eventConsumerBufferSize: 10
recordExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.io.IOException
ignoreExceptions:
- io.github.robwin.exception.BusinessException
shared:
registerHealthIndicator: true
slidingWindowSize: 100
permittedNumberOfCallsInHalfOpenState: 30
waitDurationInOpenState: 1s
failureRateThreshold: 50
eventConsumerBufferSize: 10
ignoreExceptions:
- io.github.robwin.exception.BusinessException
instances:
backendA:
baseConfig: default
backendB:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 10
permittedNumberOfCallsInHalfOpenState: 3
waitDurationInOpenState: 1s
failureRateThreshold: 50
eventConsumerBufferSize: 10
recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate
resilience4j.retry:
configs:
default:
maxRetryAttempts: 2
waitDuration: 100
retryExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.io.IOException
ignoreExceptions:
- io.github.robwin.exception.BusinessException
instances:
backendA:
maxRetryAttempts: 3
backendB:
maxRetryAttempts: 3
resilience4j.bulkhead:
configs:
default:
maxConcurrentCalls: 100
instances:
backendA:
maxConcurrentCalls: 10
backendB:
maxWaitDuration: 10ms
maxConcurrentCalls: 20
resilience4j.thread-pool-bulkhead:
configs:
default:
maxThreadPoolSize: 4
coreThreadPoolSize: 2
queueCapacity: 2
instances:
backendA:
baseConfig: default
backendB:
maxThreadPoolSize: 1
coreThreadPoolSize: 1
queueCapacity: 1
resilience4j.ratelimiter:
configs:
default:
registerHealthIndicator: false
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 0
eventConsumerBufferSize: 100
instances:
backendA:
baseConfig: default
backendB:
limitForPeriod: 6
limitRefreshPeriod: 500ms
timeoutDuration: 3s
Code to try testing it尝试测试它的代码
SpringBootApplication
public class CircuitsApplication {
private static final Logger logger = LoggerFactory.getLogger(CircuitsApplication.class);
static ResilientClient resilientClient = new ResilientClient();
public static void main(String[] args) {
//SpringApplication.run(CircuitsApplication.class, args);
for (int i = 0; i < 100; i++){
try {
String body = "body content";
String[] headers = new String[]{"header", "value"};
String url = "http://a.bad.url";
String result = resilientClient.processPostRequest(body, headers, url);
logger.info(result);
} catch (Exception ex){
logger.info("Error caught in main loop");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
I've tried adding the Circuitbreaker annotation to the method itself.我尝试将 Circuitbreaker 注释添加到方法本身。 I've tried creating a supplier and decorating it.
我尝试过创建供应商并对其进行装饰。 I've tried adding the Bulkhead, removing the Bulkhead.
我试过添加隔板,移除隔板。 I've tried adding additional fallback methods with different signatures.
我尝试添加具有不同签名的其他后备方法。 I've tried with and without
@Component
.我尝试过使用和不使用
@Component
。
All I end up getting in my logs is this 100 times:我最终在日志中得到的只有 100 次:
14:33:10.348 [main] INFO c.t.circuits.CircuitsApplication - Error caught in main loop
I'm not sure what I'm missing.我不确定我错过了什么。 Any help would be greatly appreciated.
任何帮助将不胜感激。
I don't think this will work.我认为这行不通。 Firstly, you are instantiating your
ResilientClient
as new ResilientClient()
.首先,您将
ResilientClient
实例化为new ResilientClient()
。 You have to use the created Bean not instantiate it yourselves.您必须使用创建的 Bean 而不是自己实例化它。 The
@CircuitBreaker
annotation uses spring-aop. @CircuitBreaker
注释使用 spring-aop。 So you will have to run you class as SpringBootApplicaiton.因此,您必须将 class 作为 SpringBootApplicaiton 运行。
Secondly, you are only recording HttpServerErrorException
and IOException
as failures.其次,您仅将
HttpServerErrorException
和IOException
记录为失败。 So circuit breaker treats all other exceptions (except the ones mentioned above and their children) as success.因此断路器将所有其他异常(除了上面提到的异常及其子异常)视为成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.