1. Обзор
Spring Retry обеспечивает возможность автоматического повторного вызова неудачной операции. Это полезно в тех случаях, когда ошибки могут быть временными (например, кратковременный сбой сети).
В этом уроке мы рассмотрим различные способы использования Spring Retry : аннотации, RetryTemplate и обратные вызовы.
Дальнейшее чтение:
Лучшие повторные попытки с экспоненциальным откатом и дрожанием
Руководство по устойчивости
Настройка логики повторных попыток в пакете Spring
2. Зависимости Maven
Давайте начнем с добавления зависимости spring-retry в ваш pom.xml файл :
org.springframework.retry spring-retry 1.2.5.RELEASE
Нам также необходимо добавить Spring AOP в наш проект:
org.springframework spring-aspects 5.2.8.RELEASE
Взгляните на Maven Central для последних версий зависимостей spring-retry и spring-aspects .
3. Включение Повторной Попытки Пружины
Чтобы включить повторную попытку Spring в приложении, нам нужно добавить @EnableRetry аннотацию в наш @Configuration класс:
@Configuration @EnableRetry public class AppConfig { ... }
4. Повторите Попытку С Помощью Пружины
4.1. @Retryable Без Восстановления
Чтобы добавить функциональность повторных попыток к методам, мы можем использовать @Retryable аннотация:
@Service public interface MyService { @Retryable(value = RuntimeException.class) void retryService(String sql); }
В этом примере повторная попытка предпринимается при возникновении RuntimeException .
В соответствии с поведением по умолчанию @Retryable повторная попытка может произойти до трех раз с задержкой в одну секунду между повторными попытками .
4.2. @Retryable и @Recover
Давайте теперь добавим метод восстановления с помощью @Восстановить аннотация:
@Service public interface MyService { @Retryable(value = SQLException.class) void retryServiceWithRecovery(String sql) throws SQLException; @Recover void recover(SQLException e, String sql); }
В этом примере повторная попытка предпринимается при возникновении SQLException /. Аннотация @Recover определяет отдельный метод восстановления, когда метод @Retryable завершается с указанным исключением.
Следовательно, если повторите Попытку Обслуживания С Восстановлением метод продолжает бросать SQLException после 3 попыток восстановиться() будет вызван метод.
Обработчик восстановления должен иметь первый параметр типа Выбрасываемый (необязательно) и тот же тип возврата. Следующие аргументы заполняются из списка аргументов неудачного метода в том же порядке.
4.3. Настройка поведения @Retryable
Чтобы настроить поведение повтора, мы можем использовать параметры max Attempts и back off :
@Service public interface MyService { @Retryable( value = SQLException.class, maxAttempts = 2, backoff = @Backoff(delay = 100)) void retryServiceWithCustomization(String sql) throws SQLException; }
В приведенном выше примере будет до 2 попыток и задержка в 100 миллисекунд.
4.4. Использование свойств Пружины
Мы также можем использовать свойства в аннотации @Retryable .
Чтобы продемонстрировать это, мы увидим, как экстернализировать значения delay и maxAttempts в файл свойств .
Во-первых, давайте определим свойства в файле с именем retry Config. свойства :
retry.maxAttempts=2 retry.maxDelay=100
Затем мы проинструктируем наш класс @Configuration загрузить этот файл:
// ... @PropertySource("classpath:retryConfig.properties") public class AppConfig { ... }
Наконец, мы можем ввести значения retry.max Попыток и retry.max задержки в нашем @Retryable определении:
@Service public interface MyService { @Retryable( value = SQLException.class, maxAttemptsExpression = "${retry.maxAttempts}", backoff = @Backoff(delayExpression = "${retry.maxDelay}")) void retryServiceWithExternalizedConfiguration(String sql) throws SQLException; }
Обратите внимание, что теперь мы используем выражение maxAttempts и выражение delay вместо max Attempts и delay .
5. Повторите попытку
5.1 Повторные операции
Spring Retry предоставляет RetryOperations интерфейс, который предоставляет набор методов execute() :
public interface RetryOperations {T execute(RetryCallback retryCallback) throws Exception; ... }
RetryCallback , который является параметром execute () , является интерфейсом, который позволяет вставлять бизнес-логику, которая должна быть повторена при сбое:
public interface RetryCallback{ T doWithRetry(RetryContext context) throws Throwable; }
5.2. Повторная настройка
RetryTemplate является реализацией операций повтора . Давайте настроим RetryTemplate bean в нашем @Configuration классе:
@Configuration public class AppConfig { //... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); fixedBackOffPolicy.setBackOffPeriod(2000l); retryTemplate.setBackOffPolicy(fixedBackOffPolicy); SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(2); retryTemplate.setRetryPolicy(retryPolicy); return retryTemplate; } }
RetryPolicy определяет, когда операция должна быть повторена.
/| SimpleRetryPolicy используется для повторения фиксированного числа попыток. С другой стороны, BackoffPolicy используется для управления отступлением между повторными попытками.
Наконец, a FixedBackOffPolicy делает паузу на фиксированный период времени, прежде чем продолжить.
5.3. Использование RetryTemplate
Для запуска кода с обработкой повторных попыток мы можем вызвать метод r retrytemplate.execute () :
retryTemplate.execute(new RetryCallback() { @Override public Void doWithRetry(RetryContext arg0) { myService.templateRetryService(); ... } });
Вместо анонимного класса мы можем использовать лямбда-выражение следующим образом:
retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; });
6. Слушатели
Прослушиватели предоставляют дополнительные обратные вызовы при повторных попытках. Мы можем использовать их для различных сквозных задач при различных повторных попытках.
6.1. Добавление обратных Вызовов
Обратные вызовы предоставляются в интерфейсе RetryListener :
public class DefaultListenerSupport extends RetryListenerSupport { @Override publicvoid close(RetryContext context, RetryCallback callback, Throwable throwable) { logger.info("onClose); ... super.close(context, callback, throwable); } @Override public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { logger.info("onError"); ... super.onError(context, callback, throwable); } @Override public boolean open(RetryContext context, RetryCallback callback) { logger.info("onOpen); ... return super.open(context, callback); } }
Обратные вызовы open и close выполняются до и после всей повторной попытки, в то время как onError применяется к отдельным вызовам RetryCallback .
6.2. Регистрация Слушателя
Затем мы регистрируем наш прослушиватель ( Поддержка прослушивателя по умолчанию) в нашем RetryTemplate bean:
@Configuration public class AppConfig { ... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); ... retryTemplate.registerListener(new DefaultListenerSupport()); return retryTemplate; } }
7. Проверка результатов
Чтобы завершить наш пример, давайте проверим результаты:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) public class SpringRetryIntegrationTest { @Autowired private MyService myService; @Autowired private RetryTemplate retryTemplate; @Test(expected = RuntimeException.class) public void givenTemplateRetryService_whenCallWithException_thenRetry() { retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; }); } }
Как мы видим из журналов тестирования, RetryTemplate и RetryListener были правильно настроены:
2020-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onOpen 2020-01-09 20:04:10 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2020-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onError 2020-01-09 20:04:12 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2020-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onError 2020-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onClose
8. Заключение
В этой статье мы рассмотрели, как использовать Spring Retry с помощью аннотаций, прослушивателей RetryTemplate, и обратных вызовов.
Исходный код примеров доступен на GitHub .