Ответ 1
Выйти из одной библиотеки стоит Sarge, которая автоматически выполняет повторы в соответствии с определенным планом.
Я пишу некоторую логику повторного подключения, чтобы периодически пытаться установить соединение с удаленной конечной точкой, которая опустилась. По сути, код выглядит следующим образом:
public void establishConnection() {
try {
this.connection = newConnection();
} catch (IOException e) {
// connection failed, try again.
try { Thread.sleep(1000); } catch (InterruptedException e) {};
establishConnection();
}
}
Я решил эту общую проблему с кодом, подобным вышеизложенному, во многих случаях, но я чувствую себя в значительной степени неудовлетворенным результатом. Существует ли шаблон проектирования, предназначенный для решения этой проблемы?
Выйти из одной библиотеки стоит Sarge, которая автоматически выполняет повторы в соответствии с определенным планом.
Бесстыдный плагин: я реализовал некоторые классы, чтобы разрешить повторные операции. Библиотека еще не доступна, но вы можете развить ее на github..
И существует вилка.
Он позволяет создавать Retryer с различными гибкими стратегиями. Например:
Retryer retryer =
RetryerBuilder.newBuilder()
.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECOND))
.withStopStrategy(StopStrategies.stopAfterAttempt(3))
.retryIfExceptionOfType(IOException.class)
.build();
И затем вы можете выполнить вызываемый (или несколько) с помощью Retryer:
retryer.call(new Callable<Void>() {
public Void call() throws IOException {
connection = newConnection();
return null;
}
}
Вы можете попробовать Idempotent Retry Pattern.
Я использую аннотации AOP и Java. Существует готовый механизм в jcabi-аспекты (я разработчик):
@RetryOnFailure(attempts = 3, delay = 1, unit = TimeUnit.SECONDS)
public void establishConnection() {
this.connection = newConnection();
}
пс. Вы также можете попробовать RetryScalar
из Cactoos.
Используя Failsafe (автор здесь):
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(IOException.class)
.withMaxRetries(5)
.withDelay(1, TimeUnit.SECONDS);
Failsafe.with(retryPolicy).run(() -> newConnection());
Никаких аннотаций, без магии, не обязательно быть приложением Spring и т.д. Просто и просто.
нет ничего особенного в повторной попытке - возьмите этот класс в качестве примера http://www.docjar.com/html/api/org/springframework/jms/listener/DefaultMessageListenerContainer.java.html Как вы можете видеть даже spring разработчики все еще пишут код для повторной попытки - строка 791... нет такой особой картины AFAIK..
Что я могу посоветовать для работы с ресурсами, это взять библиотеку пула apache commons - проверьте http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html и посетите http://commons.apache.org/pool
Вы можете попробовать spring-retry, он имеет чистый интерфейс и прост в использовании.
Пример:
@Retryable(maxAttempts = 4, backoff = @Backoff(delay = 500))
public void establishConnection() {
this.connection = newConnection();
}
В случае исключения он будет повторять (вызывать) до 4 раз метод установить соединение() с политикой отсрочки 500 мс
Это может быть что-то вроде этого:
try {
// logic
} re-try {
// retry logic
} re-re-try {
// reretry logic
} catch(Exception ex) {
// log
}