简体   繁体   English

想要在 Spring Batch 中为事务实现指数退避

[英]Want to implement exponentialbackoff for a transaction in Spring Batch

Basically the title.基本上是标题。 I am using a JDBC item reader and JDBC item writer and I'm changing a particular status through the processor by using an API, if the API fails to change the status, I want to use exponential backoff to retry this at a later instant.我正在使用 JDBC 项目读取器和 JDBC 项目编写器,并且我正在使用 API 通过处理器更改特定状态,如果 API 无法更改状态,我想使用指数退避来稍后重试。 I'm not able to figure out how to implement this我无法弄清楚如何实现这一点

You have two options:你有两个选择:

1. Handle the retry operation manually in your item processor 1. 在您的项目处理器中手动处理重试操作

There are basically two ways to do that, either programmatically or in a declarative way.基本上有两种方法可以做到这一点,以编程方式或以声明方式。

1.1 Programmatic approach 1.1 程序化方法

You first define your retry template with a backoff policy as needed:您首先根据需要使用退避策略定义重试模板:

@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;
}

Then use that retry template in your item processor:然后在您的项目处理器中使用该重试模板:

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 Declarative approach using annotations 1.2 使用注解的声明式方法

Here is an example:这是一个例子:

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. Let Spring Batch handle the retry for you by using a fault-tolerant step 2. 让 Spring Batch 使用容错步骤为您处理重试

In this case, you can set a custom RetryPolicy in your fault-tolerant step:在这种情况下,您可以在容错步骤中设置自定义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();
}

Note that in this case, whenever your processor throws an exception for an item, the entire chunk is retried item by item (and each item will be re-processed in its own transaction).请注意,在这种情况下,每当您的处理器为某个项目抛出异常时,都会逐项重试整个块(并且每个项目将在其自己的事务中重新处理)。


The examples above use spring-retry since you mentioned you have a preference for that.上面的示例使用 spring-retry ,因为您提到您对此有偏好。 But the same ideas can be applied with any other fault-tolerance library.但是相同的想法可以应用于任何其他容错库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM