Background
I'm using Spring Batch to fetch data from our customer sites through HTTP API. The progress contains 2 main steps:
- Fetch the total documents from API, then calculate the total pages using a configurable page size. Each page will be assigned to one partition step using custom
Paritioner. - A partition step will send a request to fetch page of data (a list of documents), process and write to our storage.
Customer sites might be "fragile". They could have rate limit or their sites might not respond after some heavy requests.
What I have done so far
I'm using spring-retry to re-run a request which is failed because of rate limit or server error. For e.g:
// the partition step's item reader
@StepScope
public class CustomItemReader extends ItemReader<Object> {
private List<Object> items;
@Override
public Object read() {
if (Objects.isNull(items)) {
this.items = ImportService.getPage(pageId);
}
if (Objects.nonNull(items) && !items.isEmpty()) {
return items.remove(0);
}
return null;
}
}
// config retry for fetching function
public class ImportService {
@Retryable(
value = RetryableException.class,
maxAttempts = 3,
backoff = @Backoff(
delay = 1000
)
)
public static List<Object> getPage(String pageId) throws RetryableException {
return ...;
}
}
The retry config contains Backoff policy, which has an incremental delay (1000 ms). I used this Retryable to handle both retry and rate limit.
Problem
Retryablewill repeatedly wait and re-execute the function, which hold the thread for the whole time. The instance might crash when things get bigger.- Because each customer will have its own rate limit, using
RetryablewithBackoffis not an ideal way to control the rate. Eventhough I configcore_pool_sizefor each customer sites,core_pool_size=1is not enough for some.
Question
- Is there any proper way to throttle the execution rate of Spring Batch, especially with Partitioning? For e.g: I want to config to send 2 requests in 10 seconds, and this will not be achieved by using
sleepin step listener. - I have used
scrapyfor some crawlers, and it has pretty cool retry and rate limit features. With RetryMiddleware, it will enqueue the failed pages and has aRETRY_LIMITin settings. With AutoThrottle, it can automatically throttle speed based on load on server. Is there any way to achieve kind of those features in Spring Batch? Or I have to rewrite my project withscrapy?
Thanh you very much!