Java @使用@CircuitBreaker时,一旦使用了所有重试,则不会调用Recover(回退方法)
尽管对于其他返回类型,Spring重试回退机制似乎工作得很好,但在调用返回类型为void的API时。恢复方法根本没有被调用,我尝试了所有可能的方法参数类型,并更改了回退方法的返回类型。。。。有办法吗?我不明白为什么@CircuitBReaker注释没有一个参数来接受作为值传递给它的回退方法名称Java @使用@CircuitBreaker时,一旦使用了所有重试,则不会调用Recover(回退方法),java,rest,spring-boot,microservices,spring-retry,Java,Rest,Spring Boot,Microservices,Spring Retry,尽管对于其他返回类型,Spring重试回退机制似乎工作得很好,但在调用返回类型为void的API时。恢复方法根本没有被调用,我尝试了所有可能的方法参数类型,并更改了回退方法的返回类型。。。。有办法吗?我不明白为什么@CircuitBReaker注释没有一个参数来接受作为值传递给它的回退方法名称 @CircuitBreaker(maxAttempts = 3, openTimeout = 8000, resetTimeout = 15000) public Void calling
@CircuitBreaker(maxAttempts = 3, openTimeout = 8000, resetTimeout = 15000)
public Void callingXYZ(final Abc abc, final Cdf cdf) {
return retryTemplate.execute(context -> {
log.info("Retry count={} when calling ******", context.getRetryCount());
AbcServiceImpl.this.update*****Settings(OrgId.fromString(abc.getUUID(), cdf.getData());
return null;
});
}
//Recover method that should get invoked
@Recover
public Void fallbackUpdate*****(Throwable e, Abc abc) throws Throwable{
log.info("Inside fallback");
if (e instanceof ClientException) {
log.warn("Fallback method is called when trying to call ******** from ****** because of {}", e.getCause());
//Rollback in the db based on the method attributes
throw SpecificException.forTask(HttpStatus.SERVICE_UNAVAILABLE.value(),
Enum.NAME.getErrorCode(),
Enum.NAME.getMEssage(), true);
}
throw e;
}
试着使用@Retryable,它对我很有用
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
@Retryable(value = { NullPointerException.class},maxAttempts = 2)
public void retry() throws NullPointerException{
throw new NullPointerException("something went wrong");
}
@Recover
public void recover(NullPointerException ex)
{
System.out.println("iniside recover");
}
org.springframework.retry
我在代码中解决了这个问题,它与spring重试项目无关。我无法找到问题的解决方案,因为我对AOP的Spring实现缺乏理解。由于Spring的方面应用于围绕bean的代理,而不是实际的类,因此如果从同一个类/服务调用带有@circuitbreaker的方法,则调用该方法将不起作用。您是否曾经用@Transactional(或例如@Async)注释过一个方法,但它不起作用?好像它被春天完全忽略了?这是因为这样的注释不能(至少在默认情况下)仅放在任何方法上,必须满足以下两个条件才能让Spring执行操作:
方法可见性只能是public。
调用必须来自bean的外部。
这是由于Spring代理在默认情况下的工作方式(使用CGLIB代理)。我不会深入讨论细节,因为这是一个足够广泛的主题,可以写另一篇文章,但一般来说,当您自动连接Sample类型的bean时,Spring实际上并没有为您提供Sample的实例。相反,它注入了一个生成的代理类,该类扩展了Sample(这就是为什么不能将springbean类设置为final),并重写了它的公共方法,以便能够添加额外的行为(比如事务支持)
这就是为什么带有@Transactional的方法必须是公共的(因此Spring可以轻松地重写它们),也就是为什么调用必须来自外部(只有这样它才能通过代理,Spring才能用代理引用替换此引用)
摘自,但它不允许我使用断路器模式…我希望在上次重试和重置之间有一个间隙,以便让相应的服务调用恢复。我希望同时使用重试和断路器。如果有人面临相同的问题,但仍在解决方案中遇到困难,请在此处发表评论,我将尝试用简短的文字解释代码示例。在排序中,如果您正在使用内置Spring的AOP,那么如果您不将所有断路器方法移动到新的或不同的服务中,您可以使其工作。