我正在寻找一个可以处理Callable
或Runnable
的通用异步Java作业执行框架。它类似于java.util.concurrent.ExecutorService
,(并且可能包裹ExecutorService
),但它也具有以下特征:
在作业服务期间应用程序停机时能够将作业持久保存到数据库,并能够重新启动未完成的作业。 (我知道我的工作可能必须实施Serializable
,这是可以的。)
使用UUID使客户端能够获取作业令牌并查询作业状态。 (在引擎盖下,此信息也将保留在数据库中。)
我已经开始围绕ExecutorService
开始研究这个问题了,但我更喜欢开箱即用的开源解决方案(如果存在的话)。
可以在Spring Framework中运行的东西是理想的。
答案 0 :(得分:8)
您可能需要查看Quartz。
Quartz是一个功能齐全的开源作业调度系统,可以与最小的独立应用程序集成,或者与几乎任何J2EE或J2SE应用程序一起使用 - 从最小的独立应用程序到最大的电子商务系统。 Quartz可用于创建简单或复杂的计划,以执行数十,数百甚至数万个作业;任务被定义为标准Java组件或EJB的作业。 Quartz Scheduler包含许多企业级功能,例如JTA事务和集群。
答案 1 :(得分:3)
您可以使用Quartz,并创建一个代表Runnable
或Callable
的具体Job
适配器。 Quartz'Job
接口增加了在任务调用之间维护某些状态的能力。如果需要,Quartz可以将作业及其状态持久存储在关系数据库中,并在可扩展的主机群集上执行它们。
答案 2 :(得分:2)
看看http://www.opensymphony.com/quartz/wikidocs/Features.html,看看它是否已经适合您。
从该页面开始:
使用包含的JDBCJobStore,配置为“非易失性”的所有作业和触发器都通过JDBC存储在关系数据库中
答案 3 :(得分:2)
另一个方向可能是使用Terracotta,它可以在JVM中聚集堆并保持可用性。如果从调度的角度来看,Terracotta支持与Quartz的集成。此外,还有一个主工作者和消息传递integration module也可能有用。 Terracotta是开源的。
答案 4 :(得分:2)
为了跟进Alex的观点,Terracotta解决方案不会将您的工作持久存储到数据库中,它们会在Terracotta分布式存储器中持久存在。
由于Terracotta将内存存储器保存到磁盘,因此这是将这些作业放入数据库的更高效版本。
同时,它为您提供了纯粹的POJO编程模型,因此您甚至不必处理数据库txns,ORM等 - 除非您的特定工作负载恰好与数据库通信(在这种情况下,兵马俑)在这里没有帮助或伤害你,它只是帮助分发工作)。
MasterWorker模式将帮助您在网格上分发工作,您可以非常轻松地开始使用DistributedExecutorService,提交工作如下所示:
CompletionService executor = new DistributedCompletionService(new DistributedExecutorService("myTopologyName"));
executor.submit(new MyRunnable(), null);
...
Future f = executor.take();
以下是Quickstart guide in the master-worker implementation on the Terracotta Forge的链接。
更重要的是 - Terracotta不要求你实现Serializable - 尽管你可以这样做:)