简体   繁体   中英

Spring @Async with rate per second

What is the best way to implement @Async method that will be executed X number of time per Y number of milliseconds/seconds.

I have requirement set by Amazon SES to send only 14 emails per second, which I'm doing asynchronously using Spring's @Async annotation but as I know I can only set max pool and max queue size and not rate.

Here is what I have:

@Bean(name = "emailSenderThreadPoolTaskExecutor")
public Executor emailSenderThreadPoolTaskExecutor() {

    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(14); // send 14 at once
    executor.setMaxPoolSize(14);
    executor.setThreadNamePrefix("EmailThreadPool-");
    executor.initialize();
    return executor;
}

and then

@Async(value = "emailSenderThreadPoolTaskExecutor")
public void sendEmail(String emailTo, String subject) {
    //...
}

The @Async annotation only implies asynchronous execution of a method, it doesn't provide any rate limitation or other functionality.

A clumsy way would be to use a pool of size 1, and have a 72 millisecond delay in the method itself. A better way would be to forget @Async and use something that's meant for rate limiting.

With a bit out of the box thinking more focusing on your requirement let me put this on the table as a very effective option I've used in similar situations in the past where I had time-counter limitations.

The Enterprise Integration Pattern ( EIP ) called Throttler can perfectly solve this rate-limitation problem.

The Apache Camel Throttler implementation let you specify:

  • maximumRequestsPerPeriod = Maximum number of requests per period to throttle in your case 14
  • timePeriodMillis = The time period in milliseconds, in which the throttler will allow at most maximumRequestsPerPeriod number of messages in your case 1000 (which is the default by the way)

This can be defined either in XML or Java way and it also provides Async non-blocking option (if emails don't make it this iteration schedule them to occur next available slot).

Spring Integration , the Spring solution offering EIP, should also have the Throttler option available but I haven't used Spring Integration myself to know.

Again, I understand the overhead of learning something new that probably won't happen in your case here but I wanted to outline it anyway for future reference and a standalone solution to your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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