4. 获取运行在本作业实例的分片项集合
public List<Integer> getLocalShardingItems() {
if (JobRegistry.getInstance().isShutdown(jobName) || !serverService.isAvailableServer(JobRegistry.getInstance().getJobInstance(jobName).getIp())) {
return Collections.emptyList();
}
return getShardingItems(JobRegistry.getInstance().getJobInstance(jobName).getJobInstanceId());
}
public List<Integer> getShardingItems(final String jobInstanceId) {
JobInstance jobInstance = new JobInstance(jobInstanceId);
if (!serverService.isAvailableServer(jobInstance.getIp())) {
return Collections.emptyList();
}
List<Integer> result = new LinkedList<>();
int shardingTotalCount = configService.load(true).getTypeConfig().getCoreConfig().getShardingTotalCount();
for (int i = 0; i < shardingTotalCount; i++) {
if (jobInstance.getJobInstanceId().equals(jobNodeStorage.getJobNodeData(ShardingNode.getInstanceNode(i)))) {
result.add(i);
}
}
return result;
}
public boolean isAvailableServer(final String ip) {
return isEnableServer(ip) && hasOnlineInstances(ip);
}
private boolean hasOnlineInstances(final String ip) {
for (String each : jobNodeStorage.getJobNodeChildrenKeys(InstanceNode.ROOT)) {
if (each.startsWith(ip)) {
return true;
}
}
return false;
}
public boolean isEnableServer(final String ip) {
return !ServerStatus.DISABLED.name().equals(jobNodeStorage.getJobNodeData(serverNode.getServerNode(ip)));
}
如果开启了失效转移需要移除运行在本作业服务器的被失效转移的序列号,节点为sharding/%s/failover
public List<Integer> getLocalTakeOffItems() {
List<Integer> shardingItems = shardingService.getLocalShardingItems();
List<Integer> result = new ArrayList<>(shardingItems.size());
for (int each : shardingItems) {
if (jobNodeStorage.isJobNodeExisted(FailoverNode.getExecutionFailoverNode(each))) {
result.add(each);
}
}
return result;
}
再移除禁用的任务分片项,节点sharding/%s/disabled
public List<Integer> getDisabledItems(final List<Integer> items) {
List<Integer> result = new ArrayList<>(items.size());
for (int each : items) {
if (jobNodeStorage.isJobNodeExisted(ShardingNode.getDisabledNode(each))) {
result.add(each);
}
}
return result;
}
获取当前作业服务器分片上下文ShardingContexts
public ShardingContexts getJobShardingContext(final List<Integer> shardingItems) {
LiteJobConfiguration liteJobConfig = configService.load(false);
removeRunningIfMonitorExecution(liteJobConfig.isMonitorExecution(), shardingItems);
if (shardingItems.isEmpty()) {
return new ShardingContexts(buildTaskId(liteJobConfig, shardingItems), liteJobConfig.getJobName(), liteJobConfig.getTypeConfig().getCoreConfig().getShardingTotalCount(),
liteJobConfig.getTypeConfig().getCoreConfig().getJobParameter(), Collections.<Integer, String>emptyMap());
}
Map<Integer, String> shardingItemParameterMap = new ShardingItemParameters(liteJobConfig.getTypeConfig().getCoreConfig().getShardingItemParameters()).getMap();
return new ShardingContexts(buildTaskId(liteJobConfig, shardingItems), liteJobConfig.getJobName(), liteJobConfig.getTypeConfig().getCoreConfig().getShardingTotalCount(),
liteJobConfig.getTypeConfig().getCoreConfig().getJobParameter(), getAssignedShardingItemParameterMap(shardingItems, shardingItemParameterMap));
}
如果允许监视器执行则需要移除正在执行的分片
private void removeRunningIfMonitorExecution(final boolean monitorExecution, final List<Integer> shardingItems) {
if (!monitorExecution) {
return;
}
List<Integer> runningShardingItems = new ArrayList<>(shardingItems.size());
for (int each : shardingItems) {
if (isRunning(each)) {
runningShardingItems.add(each);
}
}
shardingItems.removeAll(runningShardingItems);
}
private boolean isRunning(final int shardingItem) {
return jobNodeStorage.isJobNodeExisted(ShardingNode.getRunningNode(shardingItem));
}
组装任务id,jobName@-@1,2,3@-@READY@-@jobInstanceId,jobInstanceId是由IpUtils.getIp()@-@ManagementFactory.getRuntimeMXBean().getName().split("@")[0]组成
private String buildTaskId(final LiteJobConfiguration liteJobConfig, final List<Integer> shardingItems) {
JobInstance jobInstance = JobRegistry.getInstance().getJobInstance(jobName);
return Joiner.on("@-@").join(liteJobConfig.getJobName(), Joiner.on(",").join(shardingItems), "READY",
null == jobInstance.getJobInstanceId() ? "127.0.0.1@-@1" : jobInstance.getJobInstanceId());
}
5. 发布作业状态追踪事件,最后通过监听器插入到数据库中。
public void postJobStatusTraceEvent(final String taskId, final State state, final String message) {
TaskContext taskContext = TaskContext.from(taskId);
jobEventBus.post(new JobStatusTraceEvent(taskContext.getMetaInfo().getJobName(), taskContext.getId(),
taskContext.getSlaveId(), Source.LITE_EXECUTOR, taskContext.getType(), taskContext.getMetaInfo().getShardingItems().toString(), state, message));
if (!Strings.isNullOrEmpty(message)) {
log.trace(message);
}
}
如果当前分片项仍在运行则设置任务被错过执行的标记,错过节点sharding/%s/misfire,执行节点sharding/%s/running
public boolean misfireIfHasRunningItems(final Collection<Integer> items) {
if (!hasRunningItems(items)) {
return false;
}
setMisfire(items);
return true;
}
public boolean hasRunningItems(final Collection<Integer> items) {
LiteJobConfiguration jobConfig = configService.load(true);
if (null == jobConfig || !jobConfig.isMonitorExecution()) {
return false;
}
for (int each : items) {
if (jobNodeStorage.isJobNodeExisted(ShardingNode.getRunningNode(each))) {
return true;
}
}
return false;
}
public void setMisfire(final Collection<Integer> items) {
for (int each : items) {
jobNodeStorage.createJobNodeIfNeeded(ShardingNode.getMisfireNode(each));
}
}
6. 作业执行前的执行的方法,调用各个监听器
public void beforeJobExecuted(final ShardingContexts shardingContexts) {
for (ElasticJobListener each : elasticJobListeners) {
each.beforeJobExecuted(shardingContexts);
}
}
public final void beforeJobExecuted(final ShardingContexts shardingContexts) {
guaranteeService.registerStart(shardingContexts.getShardingItemParameters().keySet());
if (guaranteeService.isAllStarted()) {
doBeforeJobExecutedAtLastStarted(shardingContexts);
guaranteeService.clearAllStartedInfo();
return;
}
long before = timeService.getCurrentMillis();
try {
synchronized (startedWait) {
startedWait.wait(startedTimeoutMilliseconds);
}
} catch (final InterruptedException ex) {
Thread.interrupted();
}
if (timeService.getCurrentMillis() - before >= startedTimeoutMilliseconds) {
guaranteeService.clearAllStartedInfo();
handleTimeout(startedTimeoutMilliseconds);
}
}
根据分片项注册任务开始运行,创建保障开始节点guarantee/started/%s
public void registerStart(final Collection<Integer> shardingItems) {
for (int each : shardingItems) {
jobNodeStorage.createJobNodeIfNeeded(GuaranteeNode.getStartedNode(each));
}
}
判断是否所有的任务均启动完毕
public boolean isAllStarted() {
return jobNodeStorage.isJobNodeExisted(GuaranteeNode.STARTED_ROOT)
&& configService.load(false).getTypeConfig().getCoreConfig().getShardingTotalCount() == jobNodeStorage.getJobNodeChildrenKeys(GuaranteeNode.STARTED_ROOT).size();
}
分布式环境中最后一个作业执行前的执行的方法,最后清理所有任务启动信息,刚开始的任务都阻塞在synchronized里,有一个节点变更监听器GuaranteeListenerManager会通知该线程恢复执行,这个时候判断是否超时来决定是否抛异常以及清除完成节点
class StartedNodeRemovedJobListener extends AbstractJobListener {
@Override
protected void dataChanged(final String path, final Type eventType, final String data) {
if (Type.NODE_REMOVED == eventType && guaranteeNode.isStartedRootNode(path)) {
for (ElasticJobListener each : elasticJobListeners) {
if (each instanceof AbstractDistributeOnceElasticJobListener) {
((AbstractDistributeOnceElasticJobListener) each).notifyWaitingTaskStart();
}
}
}
}
}
public void notifyWaitingTaskStart() {
synchronized (startedWait) {
startedWait.notifyAll();
}
}