我正在尝试在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
- 在另一个实例上执行实例-2
现在,我的理解是,如果我去杀死一个实例,比如说 1,那么节点 1 的 CRON 应该迁移到节点 2。 但是,这并没有发生。
当我杀死节点时,我确实收到此消息
信息: [192.168.122.1]:5707 [开发] [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
我怀疑,这就是为什么它没有在环形缓冲区上持久化。任何想法如何使它可序列化。我检查了代码,ThreadPoolTaskScheduler已经实现了可序列化
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 实例。当您启动它时,它会加入先前运行的节点,并且可运行的节点在密钥的所有者节点上执行。现在杀死正在打印消息的节点,看看剩下的另一个节点是否拾取可运行的节点。
如果你在你的设置中看到其他东西,那么你可能需要深入研究你的 Spring cron 作业。
正如Thomas Kountis在 https://groups.google.com/forum/#!topic/hazelcast/id8AcvWyR5I 回答
的那样你好
正如Jaromir上面所说,你基本上在你的 可运行
scheduler.schedule(...)
.完成此指令后, 您的 Spring 调度程序在后台工作,但从 持久执行器透视图 任务已完成。一旦任务是 完成,它被其结果替换,在您的情况下没有 结果,所以null
.如果您杀死该所有者成员,则备份是 提升了,但是没有任务了,因为我们在 上一步。备份知道任务已完成。这样做吗 有意义?我不能用任何非滥用的方式来完成你是什么 寻找,除了内心天真的
CronScheduler
IScheduledExecutor
.想象一个定期任务,它运行 第二个左右,它里面有Map<CronExpression, Runnable>
。 在其run
周期中,它会检查表达式以断言是否存在 任何可运行的就绪,如果是,则运行它的另一个执行器(持久或 已安排)。 由于这是一个周期性任务,因此无需IScheduledExecutor
,并且在发生故障时将持久耐用。希望对您有所帮助!我们将寻求添加本机支持 将来
IScheduledExecutor
中的 cron 表达式。谢谢