我们有一个需要
的应用程序每晚重新处理大量数据,
按需重新处理大量数据。
在这两种情况下,大约10,000个石英作业产生然后运行。在每晚的情况下,我们有一个石英cron
作业产生10,000个作业,每个作业分别处理数据。
我们遇到的问题是我们运行了大约30个线程,因此石英作业自然会失败,并且在处理完所有内容之前继续失火。处理最多可能需要6个小时。这10,000个作业中的每一个都属于可以并行处理且完全独立的特定域对象。 10,000个工作中的每一个都可能花费不同的时间(从半秒到一分钟)。
我的问题是:
有更好的方法吗?
如果没有,我们安排/设置石英作业的最佳方式是什么,以便花费最少的时间来捶打和处理失火?
关于或体系结构的说明:我们正在运行两个集群,每个集群有三个节点。 quartz的版本有点旧(2.0.1),并且在quartz.properties文件中启用了聚类。
答案 0 :(得分:7)
在这两种情况下,大约有10,000个石英作业产生
无需生成新的石英作业。 Quartz是一个调度程序 - 而不是任务管理器。
在夜间重新处理中 - 您只需要一个石英cron
作业来调用一些负责管理和运行10,000个任务的服务。在“按需”场景中,石英根本不应该涉及。只需直接调用该服务。
该服务如何管理10,000个任务?
通常,只有一个JVM可用时,您只需使用一些ExecutorService
。在这里,由于您的手指有6个节点,因此您可以轻松使用Hazelcast 。 Hazelcast是一个java库,使您可以集群节点,相互有效地共享资源。 Hazelcast有一个简单的解决方案来分发您的ExecutorService
,即Distributed Executor Service。它就像创建Hazelcast ExecutorService
和submitting the task on all members一样简单。以下是the documentation用于调用单个成员的示例:
Callable<String> task = new Echo(input); // Echo is just some Callable
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
IExecutorService executorService = hz.getExecutorService("default");
Future<String> future = executorService.submitToMember(task, member);
String echoResult = future.get();
答案 1 :(得分:4)
我会通过使用队列(RabbitMQ / ActiveMQ)来做到这一点。 cron作业(或任何你的按需触发器)用表示10,000个工作指令的消息(即重新处理给定域对象的数据的指令)填充队列。
在每个节点上都有一个执行器池,它从队列中拉出并执行工作指令。此解决方案意味着每个执行程序尽可能保持忙碌,同时队列中仍有工作项,这意味着整个处理过程尽快完成。
答案 2 :(得分:2)
最好的方法是使用Quartz实例集群。这将共享许多群集节点之间的作业: http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJDBCJobStoreClustering
答案 3 :(得分:0)
我会使用一个计划的石英作业来启动10k任务,但它是通过将任务细节附加到JMS队列(10k消息)来实现的。该队列由消息驱动的bean(Java-EE EJB MDB)监视。 MDB可以在集群中的多个节点上同时运行,每个节点可以运行多个实例...不要为分布式任务负载重新发明轮子:让Java-EE这样做。