how to do background computing in Spring 3.0?

自古美人都是妖i 提交于 2019-12-06 05:34:48
Pascal Thivent

If you "only" need asynchronous execution, then the JMS approach suggested by duffymo is definitely a good solution (message delivery is guaranteed, it's fault-tolerant, transactional, etc). However, in case of failure, messages will be rolled back and immediately delivered, unless you configure a Redelivery Delay and a Redelivery limit. But while some JMS providers do offer such features (e.g. MQ, WebLogic, JBoss), this is not a standard thing AFAIK (for example, GlassFish OpenMQ doesn't offer this). You need to take this into account.

Another approach would be to use a scheduler (especially if you also want to delay or schedule the jobs execution) - and I'm thinking to Quartz here - and to reschedule jobs on failure (this is fully supported by Quartz). And Spring also provides nice integration of Quartz.

I'd use JMS and Spring message-driven POJOs. Use a guaranteed deliver queue to ensure that the message is put back on the queue in the event of a failure. Supply an error queue to handle max retry problems.

Of the technologies you mentioned, JMX isn't relevant to the problem, and while JMS would probably work, it is likely to be overkill (the amount of effort in setting it up can be considerable, depending on your platform). Quartz is also an option, although Quartz's strengths lie in cron-type scheduling and clustered scheduling, neither of which seems to be a requirement for you.

Your requirement seems to be to submit a task to a queue, execute those queued tasks one at a time, and if one of them fails for a specific reason, then hold up further processing for a certain amount of time, and then try again with the previous task.

The simplest approach I can think of is pretty similar to the other question you mentioned, which is to use the Spring TaskExecutor abstraction, but with a twist.

If your requirement is just that the queue should be "held up" for a fixed period of time if a web service failure is detected, then you can handle that entirely within the executing task, e.g.

public class MyTask implements Runnable {
   public void run() {
      while (true) {
         try {
            performWork();
            return;
         } catch (WebServiceFailure f) {
            sleepForFixedPeriod();
         }
      } 
   }
}

The configure a ThreadPoolTaskExecutor is Spring, with a maxPoolSize set to 1. Your client code then submits worker task objects (like the one above) to the executor.

If you were to increase the corePoolSize of the executor to a value higher than 1, then you could take advantage of multiple cores to improve throughput by allowing the executor use multiple threads, but the "catch-and-retry" logic would only apply on a per-thread basis.

It's not the most elegant of solutions, but it's very simple, easy to understand and setup.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!