如何在Spring 3.0中进行后台计算?

在spring应用程序中,我想做一些背景计算。 我的任务是保存一个实体(比方说GPS坐标),然后我想查询一个Web服务以获得所有坐标之间的距离并将它们存储在数据库中供以后使用。 在存储实体之后,可能无法与将用于计算距离的web服务建立连接。

我认为这可以通过在系统中引入一个工作来完成(有些事情就像一个cron工作)。 一旦我们想要在后台发生一些事情,我们就把它放在一个工作队列中。 队列将尝试执行它接收的第一个作业,作业将转到并连接到Web服务,如果由于某种原因它失败,它将保留在队列中并告诉队列它失败了。 然后,队列可以在指定的重试时间后执行。当它成功完成作业时,它将从作业队列中取出。

我很清楚要求,但我不确定使用哪种技术。 JMX,JMS,Spring Task Scheduler,Spring Integration,混合/匹配或全部。

这看起来类似于如何在spring webapp中创建后台进程? 但并非完全如此

编辑让我们进一步添加它。 还可以为每个CSV文件批量添加这些GPS坐标(通过CSV文件),每个条目将在文件中处理(顺序将是先到先服务文件和每个条目)。 删除案例可以更简单,因为预计不会删除任何内容(但可以在以后使用deatl)

如果你“只”需要异步执行,那么duffymo建议的JMS方法绝对是一个很好的解决方案(保证消息传递,它是容错的,事务性的等)。 但是,如果失败,除非您配置“重新传递延迟”和“重新传递”限制 ,否则将回滚并立即传递邮件。 但是虽然一些JMS提供商确实提供了这样的function(例如MQ,WebLogic,JBoss),但这不是AFAIK的标准事物(例如,GlassFish OpenMQ不提供此function)。 您需要考虑到这一点。

另一种方法是使用调度程序(特别是如果你还想延迟或安排作业执行) – 我在这里考虑Quartz – 并在失败时重新安排作业(这完全由Quartz支持)。 而Spring也提供了很好的Quartz集成。

我将使用JMS和Spring消息驱动的POJO。 使用有保证的传递队列以确保在发生故障时将消息放回队列。 提供错误队列以处理最大重试问题。

在您提到的技术中,JMX与问题无关,虽然JMS可能会起作用,但它可能过度(设置它的工作量可能相当大,具体取决于您的平台)。 Quartz也是一种选择,虽然Quartz的优势在于cron类型的调度和集群调度,但这两者似乎都不是你的要求。

您的要求似乎是将任务提交到队列,一次执行一个排队任务,如果其中一个因特定原因而失败,则在一段时间内保持进一步处理,然后再次尝试上一个任务。

我能想到的最简单的方法与你提到的另一个问题非常相似,即使用Spring TaskExecutor抽象 ,但有一个转折点。

如果您的要求只是在检测到Web服务故障时队列应该“保持”一段固定的时间,那么您可以完全在执行任务中处理该队列,例如

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

配置ThreadPoolTaskExecutor是Spring, maxPoolSize设置为1 。 然后,您的客户端代码将工作者任务对象(如上所述)提交给执行程序。

如果要将执行程序的corePoolSize增加到大于1的值,那么您可以通过允许执行程序使用多个线程来利用多个内核来提高吞吐量,但“catch-and-retry”逻辑仅适用于每个线程的基础。

它不是最优雅的解决方案,但它非常简单,易于理解和设置。