Статьи

Повторите обработку с помощью Spring-Retry

Всякий раз, когда программные компоненты взаимодействуют друг с другом, существует вероятность временных самокорректирующихся ошибок. Такие сбои включают временную недоступность службы, кратковременную потерю подключения к сети или тайм-ауты, которые возникают, когда служба занята. В таких ситуациях правильная обработка повторных попыток может уменьшить проблемы, которые могут вызвать эти неисправности.

В этой статье мы увидим, как Spring Retry можно использовать для добавления надежной логики повторов в приложения Spring. Spring Retry, вероятно, не так хорошо известен, потому что он не указан в обзоре документации Spring . Однако вы можете найти его на странице Spring Initializr .

Настроить

Чтобы использовать Spring Retry, нам нужно добавить следующую зависимость в наш проект:

1
2
3
4
5
<dependency>
  <groupid>org.springframework.retry</groupid>
  <artifactid>spring-retry</artifactid>
  <version>1.1.2.RELEASE</version>
</dependency>

Spring Retry использует AOP, поэтому убедитесь, что Spring AOP доступен:

01
02
03
04
05
06
07
08
09
10
<dependency>
  <groupid>org.springframework</groupid>
  <artifactid>spring-aop</artifactid>
  <version>4.2.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.8</version>
</dependency>

Если вы используете Spring Boot , вы можете использовать вместо этого spring-boot-starter-aop:

1
2
3
4
<dependency>
  <groupid>org.springframework.boot</groupid>
  <artifactid>spring-boot-starter-aop</artifactid>
</dependency>

Чтобы включить Spring Retry, нам просто нужно добавить @EnableRetry в наш класс конфигурации приложения:

1
2
3
4
5
@EnableRetry
@SpringBootApplication // or @Configuration if you are not using Spring Boot
public class RetryExampleApplication {
  // ...
}

Добавление повторной обработки с аннотациями

Теперь мы готовы добавить обработку повторов в методы. Для этого нам просто нужно аннотировать соответствующие методы с помощью @Retryable:

1
2
3
4
5
6
7
8
@Service
public class MyService {
 
  @Retryable
  public void simpleRetry() {
    // perform operation that is likely to fail
  }
}

Методы, аннотированные @Retryable, можно вызывать, как и любые другие методы. Однако всякий раз, когда выполнение повторяющегося метода завершается неудачей с исключением, Spring автоматически повторяет попытку метода до трех раз. По умолчанию Spring использует задержку в 1 секунду между вызовами методов. Обратите внимание, что вызывающий поток блокируется во время повторной обработки.

Поведение повтора может быть настроено различными способами. Например:

01
02
03
04
05
06
07
08
09
10
11
12
13
@Service
public class MyService {
 
  @Retryable(value = {FooException.class, BarException.class}, maxAttempts = 5)
  public void retryWithException() {
    // perform operation that is likely to fail
  }
 
  @Recover
  public void recover(FooException exception) {
    // recover from FooException
  }
}

Здесь мы говорим Spring применять обработку повторов, только если выброшено исключение типа FooException или BarException. Другие исключения не приведут к повторной попытке. maxAttempts = 5 сообщает Spring повторить метод до 5 раз в случае сбоя.

С помощью @Recover мы определяем отдельный метод восстановления для FooException. Это позволяет нам запускать специальный код восстановления в случае сбоя повторяющегося метода с FooException.

Добавление обработки повторов с RetryTemplate

Помимо аннотаций Spring Retry предлагает RetryTemplate, который можно использовать для определения обработки повторов в коде Java. Как и любой другой компонент, RetryTemplate можно просто настроить в нашем классе конфигурации:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
@EnableRetry
@SpringBootApplication // or @Configuration if you are not using Spring Boot
public class RetryExampleApplication {
 
  @Bean
  public RetryTemplate retryTemplate() {
    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
    retryPolicy.setMaxAttempts(5);
 
    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setBackOffPeriod(1500); // 1.5 seconds
 
    RetryTemplate template = new RetryTemplate();
    template.setRetryPolicy(retryPolicy);
    template.setBackOffPolicy(backOffPolicy);
 
    return template;
  }
   
  // ...
}

RetryPolicy определяет, когда операция должна быть повторена. SimpleRetryPolicy — это реализация RetryPolicy, которая повторяет попытки фиксированное количество раз.

BackOffPolicy — это интерфейс стратегии, позволяющий контролировать откат между попытками. FixedBackOffPolicy делает паузу на фиксированный период времени, прежде чем продолжить. Некоторыми другими реализациями BackOffPolicy по умолчанию являются ExponentialBackOffPolicy (увеличивает период отката для каждой повторной попытки) или NoBackOffPolicy (без задержки между повторными попытками).

Теперь мы можем внедрить RetryTemplate в наш сервис. Чтобы запустить код с повторной обработкой, нам просто нужно вызвать RetryTemplate.execute ():

01
02
03
04
05
06
07
08
09
10
11
12
13
14
@Service
public class RetryService {
 
  @Autowired
  private RetryTemplate retryTemplate;
 
  public void withTemplate() {
    retryTemplate.execute(context -> {
      // perform operation that is likely to fail
    });
  }
 
  // ...
}

RetryTemplate.exeucte () принимает RetryCallback <T, E> в качестве параметра. RetryCallback — это функциональный интерфейс, поэтому его можно реализовать с помощью лямбда-выражения Java 8 (как показано выше).

Резюме

Пружинный повтор обеспечивает простой способ добавить обработку повторов в приложения пружин. Обработка повторных попыток может быть добавлена ​​с использованием аннотаций (@Retryable и @Recover) или путем передачи RetryCallback в RetryTemplate.

  • Вы можете найти полный пример исходного кода на GitHub .