SpringBoot异步重试机制

探讨 Spring 对异步和重试操作的支持。

假设我们需要构建一个简单的微服务来调用下游服务来处理一些数据。

1、需要包含spring-boot-starter-web maven 依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

将spring-retry添加到 Maven 依赖项中:

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

2、包含@EnableAsync和@EnableRetry 注释:

@Configuration
@ComponentScan("com.baeldung.asyncwithretry")
@EnableRetry
@EnableAsync
public class AsyncConfig {
}

3、要异步执行方法,我们需要使用@Async注释。同样,我们将使用@Retryable注释来注释该方法以重试执行。

@Async
@Retryable(retryFor = RuntimeException.class, maxAttempts = 4, backoff = @Backoff(delay = 100))
public Future<String> processEvents(List<String> events) {
    LOGGER.info("Processing asynchronously with Thread {}", Thread.currentThread().getName());
    downstreamService.publishEvents(events);
    CompletableFuture<String> future = new CompletableFuture<>();
    future.complete(
"Completed");
    LOGGER.info(
"Completed async method with Thread {}", Thread.currentThread().getName());
    return future;
}

在上面的代码中,我们在发生RuntimeException的情况下重试该方法,并将结果作为Future对象返回。
我们应该注意,我们应该使用Future来包装来自任何异步方法的响应。 
我们应该注意,@Async注解仅适用于公共方法,不应该在同一个类中自调用。自调用方法将绕过 SpringBoot 代理调用并在同一线程中运行。