3

我在我的项目中使用了弹簧声明式重试,例如

@Service
class Service {
  @Async  @Retryable(maxAttempts=12, backoff=@Backoff(delay=100, maxDelay=500))
    public service() {
        // ... do something
    }
}

现在,我有两个问题。

  1. 使用异步重试是否可以,我没有任何问题,只是想确定一下。

  2. 第二个要求是,如果进程失败,我想将其记录到日志文件中,包括剩余重试次数。那么,有没有办法通过,或者从方法内部获取剩余重试次数?

4

2 回答 2

4

无法使用注释,@Recover 注释方法仅在最后一次失败重试后执行,而不是在每次失败后执行。

参考这个 github 文档

上面链接的摘录-“调用“服务”方法,如果它因 RemoteAccessException 而失败,那么它将重试(默认情况下最多 3 次),如果不成功,则执行“恢复”方法。”

即使使用 RetryTemplate,只有在所有重试都用尽后才会调用 Retry 回调。

同一链接的另一个摘录-“当重试用尽时,RetryOperations 可以将控制权传递给不同的回调,即 RecoveryCallback。要使用此功能,客户端只需将回调一起传递给相同的方法”

于 2017-08-19T08:38:58.877 回答
3

您应该使用@Recover注释对每次失败执行操作,并在方法之外的对象内保留计数。确保没有其他方法与此计数器交互。这是基本前提:

@Service
class Service {


private int attemptsLeft=12;

@Retryable(maxAttempts=12, backoff=@Backoff(delay=100, maxDelay=500))
public service() {
    // ... do something that throws a KnownException you create to catch later on.
}

@Recover
public void connectionException(KnownException e) {
            this.attemptsLeft = this.attemptsLeft-1; //decrease your failure counter
            Logger.warn("Retry attempts left:{}",attemptsLeft);
        }
}

如果您不想要成员变量跟踪计数,则可能需要放弃注释并声明RetryTemplate以使用该方法访问上下文getRetryCount()

public String serviceWithRetry() {
    RetryTemplate retryTemplate = new RetryTemplate();
    final SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
    retryPolicy.setMaxAttempts(12);
    retryTemplate.setRetryPolicy(retryPolicy);
    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setInterval(100L);
    retryTemplate.setBackOffPolicy(backOffPolicy);
    retryTemplate.execute(new RetryCallback<Void, RuntimeException>() 
        return retryTemplate.execute(new RetryCallback<Void, RuntimeException>() {
        @Override
        public void doWithRetry(RetryContext context) {
            LOG.info("Retry of connection count: {}", context.getRetryCount());
            return //something with your connection logic
        }
    });
}
于 2017-08-01T18:11:15.337 回答