java 重试任务框架

cpjpxq1n  于 2022-12-21  发布在  Java
关注(0)|答案(8)|浏览(380)

我遇到过许多情况,如果任务失败,我需要重试n次(有时使用某种形式的重试前后退逻辑)。通常,如果抛出异常,任务应该重试到最大重试次数。
我可以很容易地写一些东西来做这个相当一般,但不想重新发明的车轮,我想知道是否有人可以推荐任何框架。我唯一能找到的是:Ant Retry,但我不想在应用程序中直接使用Ant任务。
谢啦,谢啦

vxf3dgd4

vxf3dgd41#

看看Failsafe(我编写的),它是一个简单的、零依赖的库,用于执行重试,支持同步和异步重试、Java 8集成、事件监听器、与其他异步API的集成等:

RetryPolicy retryPolicy = new RetryPolicy()
  .handle(ConnectException.class, SocketException.class);
  .withMaxRetries(3);

Connection connection = Failsafe.with(retryPolicy).get(() -> connect());

不会变得更容易的。

rsl1atfo

rsl1atfo2#

你可以按照这篇文章中的概述来使用RetriableTasksRetrying Operations in Java。如果愿意,可以很容易地更改它的等待算法。
样本代码:

//creates a task which will retry 3 times with an interval of 5 seconds
RetriableTask r = new RetriableTask(3, 5000, new Callable(){
    public Object call() throws Exception{
        //put your code here
    }
});
r.call();
nnt7mjpx

nnt7mjpx3#

如果使用Spring:

//import the necessary classes
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
import org.springframework.batch.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
import org.springframework.batch.retry.support.RetryTemplate;
...

// create the retry template
final RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(new SimpleRetryPolicy(5));
final ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000L);
template.setBackOffPolicy(backOffPolicy);

// execute the operation using the retry template
template.execute(new RetryCallback<Remote>() {
  @Override
  public Remote doWithRetry(final RetryContext context) throws Exception {
    return (Remote) Naming.lookup("rmi://somehost:2106/MyApp");
  }
});

Original blog post

h4cxqtbf

h4cxqtbf4#

如果您正在使用Spring,那么使用Spring Retry非常简单
现在,Spring Retry是一个单独的库(早期它是Spring Batch框架的一部分)。

**步骤1:**添加Spring重试相关性。

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.1.2.RELEASE</version>
</dependency>

步骤2:@EnableRetry注解添加到包含应用程序的main()方法的类添加到任何@Configuration类中。
步骤3:@Retryable注解添加到您的方法中,如果出现异常,您将重试/再次调用该方法。

@Retryable(maxAttempts=5,backoff = @Backoff(delay = 3000))
public void retrySomething() throws Exception{
    logger.info("printSomething{} is called");
    throw new SQLException();
}

@Retryable注解将重试/调用retrySomething() 5次(包括第一次失败)。
当前线程将在下次重试之间等待3000毫秒或3秒

2o7dmzc5

2o7dmzc55#

我已经有了一个答案,但那是三年前的事了,我必须补充一点,现在我绝对喜欢guava-retrying项目。

Callable<Boolean> callable = new Callable<Boolean>() {
    public Boolean call() throws Exception {
        return true; // do something useful here
    }
};

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfResult(Predicates.<Boolean>isNull())
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withStopStrategy(StopStrategies.stopAfterAttempt(3))
        .build();
try {
    retryer.call(callable);
} catch (RetryException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}
yb3bgrhw

yb3bgrhw6#

将此从代码库中分离出来的一个选项是在应用程序的组件之间使用命令模式。一旦将对业务方法的调用转换为对象,就可以轻松地传递调用,并拥有一个抽象的RetryHandler,它接受命令并重试该命令。这应该独立于实际调用,并且可以重用。

gt0wga4j

gt0wga4j7#

我实现了一个非常灵活的重试实用程序here
您可以使用以下命令重试任何Callable:

public static <T> T executeWithRetry(final Callable<T> what, final int nrImmediateRetries,
        final int nrTotalRetries, final int retryWaitMillis, final int timeoutMillis,
        final Predicate<? super T> retryOnReturnVal, final Predicate<Exception> retryOnException)

具有立即+延迟重试、具有最大超时、以及基于结果或异常的决定的重试。
此函数还有其他几个版本,具有或多或少的灵活性。
我还编写了一个方面,可以与注解一起应用RetryRetry Aspect

cbjzeqam

cbjzeqam8#

您可以使用Quartz。请查看this堆栈溢出答案。

相关问题