Hazelcast Scheduled Executor 始终在最新成员上启动任务
Hazelcast Scheduled Executor always starts task on newest member
我正在使用 Hazelcast Scheduled Executor Service 以便 运行 仅在一个服务实例上执行特定任务。为了实现这种行为,我们利用 com.hazelcast.scheduledexecutor.TaskUtils.named(java.lang.String, java.lang.Runnable) 装饰器来避免重复任务。
使用的 Hazelcast 依赖项:
implementation "com.hazelcast:hazelcast-all:4.2"
implementation "com.hazelcast:hazelcast-kubernetes:2.2.2" // DNS Lookup
我们使用一个 hazelcast 集群,每个服务实例有一个成员
代码示例:
public void scheduleTask() {
IScheduledExecutorService es = hazelcastInstance.getScheduledExecutorService("myScheduledExecutor");
try {
es.scheduleAtFixedRate(named("taskName", task)), 0, 30, SECONDS);
} catch (DuplicateTaskException ex) {
System.out.println("Task was already scheduled!");
}
}
以上示例设法部分实现了所需的行为。唯一的问题是每次启动一个新实例时,预定的执行程序都会 运行 该特定实例上的任务。这并不理想,因为我们希望任务执行一次,例如每 6 小时一次。
有什么方法可以配置计划的执行程序,以便它在它启动的原始实例上维护运行任务,并且只有在原始实例出现故障时才转移到另一个实例?
这不是直接可能的,但有一个近似值。
IScheduledExecutorService
没有提供一种方法来为要使用的成员提供排序。
- 您可以向特定成员提交任务,但如果原始特定成员死亡,这不会故障转移到您选择的成员。
- ...各种其他选项...
- 或者您的代码中的选项
scheduleAtFixedRate
将选择一个成员,每次集群大小时这可能是一个不同的成员。它不应该总是最新的,除非巧合。
你可以做的是有一个计划任务,选择一个成员运行一个普通任务。一项任务启动另一项任务。
在计划任务中,run()
可以调用hazelcastInstance.getCluster().getMembers()
获取集群成员列表。它所需要的只是一些选择成员的逻辑,然后执行 hazelcastInstance.getExecutorService("default").executeOnMember(runnable, member)
.
您可以选择具有您配置的特定属性的成员。或具有特定IP的会员。也许最简单的是选择最老的,因为直到最老的离开之前这不会改变,在这种情况下,第二个最老的现在是最老的,容易故障转移。
我使用的解决方法是处理已经安排好的任务,并根据上次安排任务的时间计算出初始延迟,然后再次安排。
类似于:
public void scheduleTask() {
IScheduledExecutorService es = hazelcastInstance.getScheduledExecutorService("myScheduledExecutor");
try {
disposePreviousScheduledTasks(es);
es.scheduleAtFixedRate(named("taskName", task)), initialDelay, 30, SECONDS);
} catch (DuplicateTaskException ex) {
System.out.println("Task was already scheduled!");
}
}
我正在使用 Hazelcast Scheduled Executor Service 以便 运行 仅在一个服务实例上执行特定任务。为了实现这种行为,我们利用 com.hazelcast.scheduledexecutor.TaskUtils.named(java.lang.String, java.lang.Runnable) 装饰器来避免重复任务。
使用的 Hazelcast 依赖项:
implementation "com.hazelcast:hazelcast-all:4.2"
implementation "com.hazelcast:hazelcast-kubernetes:2.2.2" // DNS Lookup
我们使用一个 hazelcast 集群,每个服务实例有一个成员
代码示例:
public void scheduleTask() {
IScheduledExecutorService es = hazelcastInstance.getScheduledExecutorService("myScheduledExecutor");
try {
es.scheduleAtFixedRate(named("taskName", task)), 0, 30, SECONDS);
} catch (DuplicateTaskException ex) {
System.out.println("Task was already scheduled!");
}
}
以上示例设法部分实现了所需的行为。唯一的问题是每次启动一个新实例时,预定的执行程序都会 运行 该特定实例上的任务。这并不理想,因为我们希望任务执行一次,例如每 6 小时一次。
有什么方法可以配置计划的执行程序,以便它在它启动的原始实例上维护运行任务,并且只有在原始实例出现故障时才转移到另一个实例?
这不是直接可能的,但有一个近似值。
IScheduledExecutorService
没有提供一种方法来为要使用的成员提供排序。
- 您可以向特定成员提交任务,但如果原始特定成员死亡,这不会故障转移到您选择的成员。
- ...各种其他选项...
- 或者您的代码中的选项
scheduleAtFixedRate
将选择一个成员,每次集群大小时这可能是一个不同的成员。它不应该总是最新的,除非巧合。
你可以做的是有一个计划任务,选择一个成员运行一个普通任务。一项任务启动另一项任务。
在计划任务中,run()
可以调用hazelcastInstance.getCluster().getMembers()
获取集群成员列表。它所需要的只是一些选择成员的逻辑,然后执行 hazelcastInstance.getExecutorService("default").executeOnMember(runnable, member)
.
您可以选择具有您配置的特定属性的成员。或具有特定IP的会员。也许最简单的是选择最老的,因为直到最老的离开之前这不会改变,在这种情况下,第二个最老的现在是最老的,容易故障转移。
我使用的解决方法是处理已经安排好的任务,并根据上次安排任务的时间计算出初始延迟,然后再次安排。
类似于:
public void scheduleTask() {
IScheduledExecutorService es = hazelcastInstance.getScheduledExecutorService("myScheduledExecutor");
try {
disposePreviousScheduledTasks(es);
es.scheduleAtFixedRate(named("taskName", task)), initialDelay, 30, SECONDS);
} catch (DuplicateTaskException ex) {
System.out.println("Task was already scheduled!");
}
}