路由策略新增 "忙碌转移" 模式:按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;

v1.8.2
xuxueli 8 years ago
parent 1ad6950ed7
commit 7e35088764

@ -857,6 +857,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 1、任务Cron更新逻辑优化改为rescheduleJob同时防止cron重复设置 - 1、任务Cron更新逻辑优化改为rescheduleJob同时防止cron重复设置
- 2、优化API回调服务失败状态码优化方便问题排查 - 2、优化API回调服务失败状态码优化方便问题排查
- 3、XxlJobLogger的日志多参数支持 - 3、XxlJobLogger的日志多参数支持
- 4、路由策略新增 "忙碌转移" 模式:按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
#### TODO LIST #### TODO LIST
- 1、任务权限管理执行器为粒度分配权限核心操作校验权限 - 1、任务权限管理执行器为粒度分配权限核心操作校验权限
@ -868,7 +869,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 7、调度任务优先级 - 7、调度任务优先级
- 8、移除quartz依赖重写调度模块新增或恢复任务时将下次执行记录插入delayqueue调度中心集群竞争分布式锁成功节点批量加载到期delayqueue数据批量执行。 - 8、移除quartz依赖重写调度模块新增或恢复任务时将下次执行记录插入delayqueue调度中心集群竞争分布式锁成功节点批量加载到期delayqueue数据批量执行。
- 9、任务线程轮空30次后自动销毁降低低频任务的无效线程消耗。 - 9、任务线程轮空30次后自动销毁降低低频任务的无效线程消耗。
- 10、路由策略新增 "忙碌转移" 模式,发现执行器运行中,主动转移下一个执行器调度任务;
## 七、其他 ## 七、其他

@ -114,76 +114,82 @@ public class RemoteHttpJobBean extends QuartzJobBean {
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString()); return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
} }
// trigger remote executor // executor route strategy
if (addressList.size() == 1) { ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null);
String address = addressList.get(0); if (executorRouteStrategyEnum == null) {
jobLog.setExecutorAddress(address); triggerSb.append("<br>----------------------<br>").append("调度失败:").append("执行器路由策略为空");
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
ReturnT<String> runResult = runExecutor(triggerParam, address); }
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg()); triggerSb.append("<br>路由策略:").append(executorRouteStrategyEnum.name() + "-" + executorRouteStrategyEnum.getTitle());
return new ReturnT<String>(runResult.getCode(), triggerSb.toString()); // trigger remote executor
} else { if (executorRouteStrategyEnum == ExecutorRouteStrategyEnum.FAILOVER) {
// executor route strategy for (String address : addressList) {
ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null); // beat
triggerSb.append("<br>路由策略:").append(executorRouteStrategyEnum!=null?(executorRouteStrategyEnum.name() + "-" + executorRouteStrategyEnum.getTitle()):null); ReturnT<String> beatResult = null;
if (executorRouteStrategyEnum == null) { try {
triggerSb.append("<br>----------------------<br>").append("调度失败:").append("执行器路由策略为空"); ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString()); beatResult = executorBiz.beat();
} } catch (Exception e) {
logger.error("", e);
beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
}
triggerSb.append("<br>----------------------<br>")
.append("心跳检测:")
.append("<br>address").append(address)
.append("<br>code").append(beatResult.getCode())
.append("<br>msg").append(beatResult.getMsg());
if (executorRouteStrategyEnum != ExecutorRouteStrategyEnum.FAILOVER) { // beat success
// get address if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {
String address = executorRouteStrategyEnum.getRouter().route(jobInfo.getId(), addressList); jobLog.setExecutorAddress(address);
jobLog.setExecutorAddress(address);
// run ReturnT<String> runResult = runExecutor(triggerParam, address);
ReturnT<String> runResult = runExecutor(triggerParam, address); triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
return new ReturnT<String>(runResult.getCode(), triggerSb.toString()); return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
} else { }
for (String address : addressList) { }
// beat return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
ReturnT<String> beatResult = beatExecutor(address); } else if (executorRouteStrategyEnum == ExecutorRouteStrategyEnum.BUSYOVER) {
triggerSb.append("<br>----------------------<br>").append(beatResult.getMsg()); for (String address : addressList) {
// beat
ReturnT<String> idleBeatResult = null;
try {
ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
idleBeatResult = executorBiz.idleBeat(triggerParam.getJobId());
} catch (Exception e) {
logger.error("", e);
idleBeatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
}
triggerSb.append("<br>----------------------<br>")
.append("空闲检测:")
.append("<br>address").append(address)
.append("<br>code").append(idleBeatResult.getCode())
.append("<br>msg").append(idleBeatResult.getMsg());
if (beatResult.getCode() == ReturnT.SUCCESS_CODE) { // beat success
jobLog.setExecutorAddress(address); if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) {
jobLog.setExecutorAddress(address);
ReturnT<String> runResult = runExecutor(triggerParam, address); ReturnT<String> runResult = runExecutor(triggerParam, address);
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg()); triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
return new ReturnT<String>(runResult.getCode(), triggerSb.toString()); return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
}
} }
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
} }
} return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
} } else {
// get address
/** String address = executorRouteStrategyEnum.getRouter().route(jobInfo.getId(), addressList);
* run executor jobLog.setExecutorAddress(address);
* @param address
* @return
*/
public ReturnT<String> beatExecutor(String address){
ReturnT<String> beatResult = null;
try {
ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
beatResult = executorBiz.beat();
} catch (Exception e) {
logger.error("", e);
beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
}
StringBuffer sb = new StringBuffer("心跳检测:"); // run
sb.append("<br>address").append(address); ReturnT<String> runResult = runExecutor(triggerParam, address);
sb.append("<br>code").append(beatResult.getCode()); triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
sb.append("<br>msg").append(beatResult.getMsg());
beatResult.setMsg(sb.toString());
return beatResult; return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
}
} }
/** /**

@ -14,7 +14,8 @@ public enum ExecutorRouteStrategyEnum {
CONSISTENT_HASH("一致性HASH", new ExecutorRouteConsistentHash()), CONSISTENT_HASH("一致性HASH", new ExecutorRouteConsistentHash()),
LEAST_FREQUENTLY_USED("最不经常使用", new ExecutorRouteLFU()), LEAST_FREQUENTLY_USED("最不经常使用", new ExecutorRouteLFU()),
LEAST_RECENTLY_USED("最近最久未使用", new ExecutorRouteLRU()), LEAST_RECENTLY_USED("最近最久未使用", new ExecutorRouteLRU()),
FAILOVER("故障转移", null); FAILOVER("故障转移", null),
BUSYOVER("忙碌转移", null);
ExecutorRouteStrategyEnum(String title, ExecutorRouter router) { ExecutorRouteStrategyEnum(String title, ExecutorRouter router) {
this.title = title; this.title = title;

@ -15,6 +15,14 @@ public interface ExecutorBiz {
*/ */
public ReturnT<String> beat(); public ReturnT<String> beat();
/**
* idle beat
*
* @param jobId
* @return
*/
public ReturnT<String> idleBeat(int jobId);
/** /**
* kill * kill
* @param jobId * @param jobId

@ -29,6 +29,22 @@ public class ExecutorBizImpl implements ExecutorBiz {
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} }
@Override
public ReturnT<String> idleBeat(int jobId) {
// isRunningOrHasQueue
boolean isRunningOrHasQueue = false;
JobThread jobThread = XxlJobExecutor.loadJobThread(jobId);
if (jobThread != null && jobThread.isRunningOrHasQueue()) {
isRunningOrHasQueue = true;
}
if (isRunningOrHasQueue) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "job thread is running or has trigger queue.");
}
return ReturnT.SUCCESS;
}
@Override @Override
public ReturnT<String> kill(int jobId) { public ReturnT<String> kill(int jobId) {
// kill handlerThread, and create new one // kill handlerThread, and create new one

@ -46,7 +46,8 @@ public class ExecutorRegistryThread extends Thread {
try { try {
RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appName, executorAddress); RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appName, executorAddress);
ReturnT<String> registryResult = AdminApiUtil.callApiFailover(AdminApiUtil.REGISTRY, registryParam); ReturnT<String> registryResult = AdminApiUtil.callApiFailover(AdminApiUtil.REGISTRY, registryParam);
logger.info(">>>>>>>>>>> xxl-job registry, RegistryParam:{}, registryResult:{}", new Object[]{registryParam.toString(), registryResult.toString()}); logger.info(">>>>>>>>>>> xxl-job Executor registry {}, RegistryParam:{}, registryResult:{}",
new Object[]{(registryResult.getCode()==ReturnT.SUCCESS_CODE?"success":"fail"), registryParam.toString(), registryResult.toString()});
} catch (Exception e) { } catch (Exception e) {
logger.error(">>>>>>>>>>> xxl-job ExecutorRegistryThread Exception:", e); logger.error(">>>>>>>>>>> xxl-job ExecutorRegistryThread Exception:", e);
} }

Loading…
Cancel
Save