Retry Task Framework
У меня есть ряд ситуаций, когда мне нужно повторить задачу n-раз, если она не сработает (иногда с некоторой формой логики возврата к повторной попытке). Как правило, если генерируется исключение, задача должна быть повторена до максимального количества попыток.
Я могу легко написать что-то, чтобы сделать это достаточно в целом, но не желая изобретать колесо, мне было интересно, может ли кто-нибудь рекомендовать какие-либо рамки для этого. Единственное, что я смог найти, это: Ant Повторить, но я не хочу использовать задачи Ant непосредственно в моем приложении.
Спасибо
Ответы
Ответ 1
Вы можете использовать RetriableTasks
, как указано в этом сообщении: Повторная операция в 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();
Ответ 2
Проверьте Failsafe. Это простая библиотека с нулевой зависимостью для выполнения повторных попыток; она поддерживает синхронные и асинхронные повторные попытки, интеграцию Java 8, прослушиватели событий, интеграцию с другими асинхронными API-интерфейсами и т. Д.:
RetryPolicy retryPolicy = new RetryPolicy()
.handle(ConnectException.class, SocketException.class);
.withMaxRetries(3);
Connection connection = Failsafe.with(retryPolicy).get(() -> connect());
Не становится намного проще.
Ответ 3
Если вы используете 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");
}
});
Оригинальное сообщение в блоге
Ответ 4
Если вы используете Spring, он очень прост, используя Spring Повторить Библиотека.
Теперь Spring Retry - это отдельная библиотека (ранее, она была частью рамки Spring Пакет).
Шаг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 секунды между следующей попыткой.
Ответ 5
У меня есть один ответ, но это было три года назад, и я должен добавить, что теперь я абсолютно люблю проект 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();
}
Ответ 6
Один из вариантов, чтобы исключить это из вашей кодовой базы, - использовать шаблон команды между компонентами вашего приложения.
После того, как вы перейдете к бизнес-методу в объект, вы можете легко передать вызов и иметь абстрактный RetryHandler, который принимает команду и повторяет ее. Это должно быть независимым от фактического вызова и повторного использования.
Ответ 7
Вы можете использовать Quartz. Посмотрите этот ответ на переполнение стека.
Ответ 8
Я реализовал довольно гибкую утилиту повтора здесь
Вы можете повторить любую 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)
с немедленными + задержанными повторами с максимальным временем ожидания и повторением либо решений, основанных на результате или исключении.
Существует несколько других версий этой функции с большей или меньшей гибкостью.
Я написал также аспект, который может быть применен с аннотациями Retry Retry Aspect