我正在尝试在Hazelcast上的DurableExecutorService上运行cron计划。 我的想法是,如果一个节点因其计划而中断,其他具有备份的节点可以拾取并恢复CRON。 这就是我正在做的事情
String cron = "0/5 * * * * *";
config.setInstanceName(name);
config.getDurableExecutorConfig("exec").setCapacity(200).setDurability(2).setPoolSize(8);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
DurableExecutorService executorService = instance.getDurableExecutorService("exec");
executorService.executeOnKeyOwner(new EchoTask(name, cron), name);
我使用Spring CRON调度程序来实际运行CRON作业。
public class EchoTask implements Runnable, Serializable {
private final String msg;
private final String cronExpression;
EchoTask(String msg, String cronExpression) {
this.msg = msg;
this.cronExpression = cronExpression;
}
public void run() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.initialize();
scheduler.schedule(new Runnable() {
@Override
public void run() {
System.out.println("Executing" + msg);
}
}, new CronTrigger(cronExpression));
}
}
现在,我跑了两次。实际上,有2个实例在运行。
现在,我的理解是,如果我去杀死一个实例,让我们说1,那么node1的CRON应该迁移到node2。 但是,这种情况并没有发生。
当我杀死节点时,我确实得到了这条消息
信息:[192.168.122.1]:5707 [dev] [3.9.3]提交/回滚活着 成员[192.168.122.1]的交易:5709 - 26ed879b-8ce5-4d58-832c-28d2df3f7f87,UUID: 26ed879b-8ce5-4d58-832c-28d2df3f7f87
我确信,我在这里遗漏了一些东西。 有人可以指导吗?
编辑1:我确认对于正常任务,此行为有效,但由于某些原因,它不适用于Spring CRON
编辑2 我怀疑的是,ThreadPoolTaskScheduler由于某种原因不可序列化。
无法序列化 org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
我怀疑,这就是为什么它不会持续存在于ringbuffer上。任何想法我怎么能使它Serializable。我检查了代码,ThreadPoolTaskScheduler已经实现了Serializable
答案 0 :(得分:1)
executorService.executeOnKeyOwner(new EchoTask(name, cron), name)
将在密钥所有者节点上运行。如果您没有启用备份并终止所有者节点,那么Hazelcast无法知道密钥曾经存在于集群中,因此没有持久性。
请参阅以下代码:
public class DurableExecutorServiceTest {
DurableExecutorServiceTest() {
Config config = new Config();
config.getDurableExecutorConfig("MyService").setDurability(2).setCapacity(200).setPoolSize(2);
HazelcastInstance hc = Hazelcast.newHazelcastInstance(config);
hc.getMap("MyMap").put("Key-1", "Value-1");
DurableExecutorService service = hc.getDurableExecutorService("MyService");
service.executeOnKeyOwner(new MyRunnable(), "Key-1");
}
public static void main(String[] args) {
new DurableExecutorServiceTest();
}
}
class MyRunnable implements Runnable, Serializable {
public void run() {
int i = 0;
while(true) {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("Printing in Durable executor service: "+i++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
首先需要在执行此代码之前启动一个Hazelcast实例。启动时,它会加入先前运行的节点,并且可以在密钥的所有者节点上执行runnable。现在终止正在打印消息的节点,看看其他剩余节点是否选择了runnable。
如果您在设置中看到其他内容,那么您可能需要深入了解Spring cron作业。
答案 1 :(得分:0)
Thomas Kountis在https://groups.google.com/forum/#!topic/hazelcast/id8AcvWyR5I
回答您好,
正如Jaromir上面所说,你基本上是在执行这条线 runnable
scheduler.schedule(...)
。一旦完成此指令, 你的Spring调度程序正在后台工作,但是从 DurableExecutor透视任务完成。任务完成后 完成后,它会被结果取代,在你的情况下没有 结果,null
。如果您杀死该所有者成员,则备份为 提升,但不再有任务,因为我们已经取代了它 前一步。备份知道任务已完成。做这个 合理?我无法以任何非滥用的方式来实现你的目标 寻找,除了可能是一个天真的
CronScheduler
里面 的IScheduledExecutor
。想象一个周期性的任务,每一个都运行 第二个左右,它包含Map<CronExpression, Runnable>
。 在run
周期内,它检查表达式是否存在断言 任何runnable ready,如果是的话,运行另一个Executor(Durable或 专线)。由于这是一项定期任务,因此它可以很好地完成IScheduledExecutor
它会在失败时持久。希望有所帮助!我们将寻求添加原生支持 将来
IScheduledExecutor
中的cron表达式。由于