想要在 Spring 批处理中为事务实现指数退避

Want to implement exponentialbackoff for a transaction in Spring Batch

基本上是标题。我正在使用 JDBC 项目 reader 和 JDBC 项目编写器,我正在使用 API 通过处理器更改特定状态,如果 API无法更改状态,我想稍后使用指数退避重试。我不知道如何实现这个

你有两个选择:

1。在您的项目处理器中手动处理重试操作

基本上有两种方法可以通过编程方式或声明方式实现。

1.1 程序化方法

您首先根据需要使用退避策略定义重试模板:

@Bean
public RetryTemplate retryTemplate() {
    // configure backoff policy
    ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
    exponentialBackOffPolicy.setInitialInterval(1000);
    exponentialBackOffPolicy.setMultiplier(2.0);
    exponentialBackOffPolicy.setMaxInterval(10000);

    // configure retry policy
    SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
    simpleRetryPolicy.setMaxAttempts(5);

    // configure retry template
    RetryTemplate retryTemplate = new RetryTemplate();
    retryTemplate.setBackOffPolicy(exponentialBackOffPolicy);
    retryTemplate.setRetryPolicy(simpleRetryPolicy);

    return retryTemplate;
}

然后在您的项目处理器中使用该重试模板:

import org.springframework.batch.item.ItemProcessor;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.support.RetryTemplate;

public class MyRetryableItemProcessor implements ItemProcessor {

    RetryTemplate retryTemplate;

    public MyRetryableItemProcessor(RetryTemplate retryTemplate) {
        this.retryTemplate = retryTemplate;
    }

    @Override
    public Object process(Object item) throws Exception {
        return retryTemplate.execute(new RetryCallback<Object, Exception>() {
            @Override
            public Object doWithRetry(RetryContext retryContext) throws Exception {
                // API call
                return item;
            }
        });
    }
}
1.2 使用注释的声明式方法

这是一个例子:

import org.springframework.batch.item.ItemProcessor;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyAnnotationBasedRetryableItemProcessor implements ItemProcessor {

    @Override
    @Retryable(backoff = @Backoff(delay = 1000L, maxDelay = 10000, multiplier = 2.0))
    public Object process(Object item) throws Exception {
        // Do API call
        return item;
    }

}

2。使用 fault-tolerant 步骤

让 Spring 批处理为您处理重试

在这种情况下,您可以在 fault-tolerant 步骤中设置自定义 RetryPolicy

@Bean
public Step step(StepBuilderFactory stepBuilderFactory) {
    // configure backoff policy
    ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
    exponentialBackOffPolicy.setInitialInterval(1000);
    exponentialBackOffPolicy.setMultiplier(2.0);
    exponentialBackOffPolicy.setMaxInterval(10000);

    // configure retry policy
    SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
    simpleRetryPolicy.setMaxAttempts(5);
    
    return stepBuilderFactory.get("myStep")
            .<Integer, Integer>chunk(5)
            .reader(itemReader())
            .processor(itemProcessor())
            .writer(itemWriter())
            .faultTolerant()
            .retryPolicy(simpleRetryPolicy)
            .build();
}

请注意,在这种情况下,每当您的处理器为某个项目抛出异常时,整个块都会逐项重试(每个项目将 re-processed 在其自己的事务中)。


上面的示例使用了 spring-retry,因为您提到过您对此有偏好。但同样的想法可以应用于任何其他 fault-tolerance 库。