由于工作需要,无法使用elastic job提供的控制台进行操作,需要提供给其他平台API供其调用,所以只能使用elastic提供的JobOperateAPI来操作zookeeper手动触发,实际上JobOperateAPI是将相关job下instances节点下的所有实例的内容改为TRIGGER。但实际通过API调用却是没办法实现,job一点反应都没有。原因就是使用的这个版本的代码是有问题的,我使用的elastic job版本是3.0.0,监听的节点和JobOperateAPI创建的节点没办法对应上,就会出现这个问题,解决也很简单,只需要将elasticjob-lite-lifecycle这个包的版本提升上去就好了。
我的pom版本
<dependency>
<artifactId>elasticjob-lite-lifecycle</artifactId>
<groupId>org.apache.shardingsphere.elasticjob</groupId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere.elasticjob</groupId>
<artifactId>elasticjob-lite-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
问题原因:
这个版本的JobOperateAPI操作的节点是修改job下的instances节点下的所有节点的内容为TRIGGER,主要代码如下
public final class JobOperateAPIImpl implements JobOperateAPI {
private final CoordinatorRegistryCenter regCenter;
public JobOperateAPIImpl(final CoordinatorRegistryCenter regCenter) {
this.regCenter = regCenter;
}
@Override
public void trigger(final String jobName) {
Preconditions.checkNotNull(jobName, "Job name cannot be null");
JobNodePath jobNodePath = new JobNodePath(jobName);
for (String each : regCenter.getChildrenKeys(jobNodePath.getInstancesNodePath())) {
regCenter.persist(jobNodePath.getInstanceNodePath(each), "TRIGGER");
}
}
// .......省略
}
主要起作用的是 TriggerListenerManager里面的JobTriggerStatusJobListener,他会监听节点的变动,然后判断是否是trigger,后面选择是否去立即启动作业。问题出现在这里,这里监听的节点不是instances节点下的所有实例节点的内容,判断的反而是job下的trigger节点下的内容,所以这里会直接跳过,关键代码如下
class JobTriggerStatusJobListener extends AbstractJobListener {
@Override
protected void dataChanged(final String path, final Type eventType, final String data) {
if (!triggerNode.isLocalTriggerPath(path) || Type.NODE_CREATED != eventType) {
return;
}
triggerService.removeTriggerFlag();
if (!JobRegistry.getInstance().isShutdown(jobName) && !JobRegistry.getInstance().isJobRunning(jobName)) {
// TODO At present, it cannot be triggered when the job is running, and it will be changed to a stacked trigger in the future.
JobRegistry.getInstance().getJobScheduleController(jobName).triggerJob();
}
}
}
private static final String TRIGGER = ROOT + "/%s";
public static final String ROOT = "trigger";
public boolean isLocalTriggerPath(final String path) {
JobInstance jobInstance = JobRegistry.getInstance().getJobInstance(jobName);
return null != jobInstance && path.equals(jobNodePath.getFullPath(String.format(TRIGGER, jobInstance.getJobInstanceId())));
}
这里 的节点必须要创建的了,而且是具体job下的trigger节点,后面看是不是在运行,再去立马执行。所以spring-boot-starter的3.0.0版本和elasticjob-lite-lifecycle这个实际是不兼容的,只需要将elasticjob-lite-lifecycle这个包的版本升一下就可以了,操作的相关节点就会保持一致。
我这里将elasticjob-lite-lifecycle版本升级到3.0.2
代码就正常了
public final class JobOperateAPIImpl implements JobOperateAPI {
private final CoordinatorRegistryCenter regCenter;
public JobOperateAPIImpl(final CoordinatorRegistryCenter regCenter) {
this.regCenter = regCenter;
}
@Override
public void trigger(final String jobName) {
Preconditions.checkNotNull(jobName, "Job name cannot be null");
new InstanceService(regCenter, jobName).triggerAllInstances();
}
// 省略
}
public void triggerAllInstances() {
jobNodeStorage.removeJobNodeIfExisted(triggerNode.getTriggerRoot());
jobNodeStorage.getJobNodeChildrenKeys(InstanceNode.ROOT).forEach(each -> jobNodeStorage.createJobNodeIfNeeded(triggerNode.getTriggerPath(each)));
}