路由策略新增 "忙碌转移" 模式:按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
This commit is contained in:
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,40 +114,33 @@ 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
|
|
||||||
if (addressList.size() == 1) {
|
|
||||||
String address = addressList.get(0);
|
|
||||||
jobLog.setExecutorAddress(address);
|
|
||||||
|
|
||||||
ReturnT<String> runResult = runExecutor(triggerParam, address);
|
|
||||||
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
|
|
||||||
|
|
||||||
return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
|
|
||||||
} else {
|
|
||||||
// executor route strategy
|
// executor route strategy
|
||||||
ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null);
|
ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null);
|
||||||
triggerSb.append("<br>路由策略:").append(executorRouteStrategyEnum!=null?(executorRouteStrategyEnum.name() + "-" + executorRouteStrategyEnum.getTitle()):null);
|
|
||||||
if (executorRouteStrategyEnum == null) {
|
if (executorRouteStrategyEnum == null) {
|
||||||
triggerSb.append("<br>----------------------<br>").append("调度失败:").append("执行器路由策略为空");
|
triggerSb.append("<br>----------------------<br>").append("调度失败:").append("执行器路由策略为空");
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
||||||
}
|
}
|
||||||
|
triggerSb.append("<br>路由策略:").append(executorRouteStrategyEnum.name() + "-" + executorRouteStrategyEnum.getTitle());
|
||||||
|
|
||||||
if (executorRouteStrategyEnum != ExecutorRouteStrategyEnum.FAILOVER) {
|
// trigger remote executor
|
||||||
// get address
|
if (executorRouteStrategyEnum == ExecutorRouteStrategyEnum.FAILOVER) {
|
||||||
String address = executorRouteStrategyEnum.getRouter().route(jobInfo.getId(), addressList);
|
|
||||||
jobLog.setExecutorAddress(address);
|
|
||||||
|
|
||||||
// run
|
|
||||||
ReturnT<String> runResult = runExecutor(triggerParam, address);
|
|
||||||
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
|
|
||||||
|
|
||||||
return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
|
|
||||||
} else {
|
|
||||||
for (String address : addressList) {
|
for (String address : addressList) {
|
||||||
// beat
|
// beat
|
||||||
ReturnT<String> beatResult = beatExecutor(address);
|
ReturnT<String> beatResult = null;
|
||||||
triggerSb.append("<br>----------------------<br>").append(beatResult.getMsg());
|
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 );
|
||||||
|
}
|
||||||
|
triggerSb.append("<br>----------------------<br>")
|
||||||
|
.append("心跳检测:")
|
||||||
|
.append("<br>address:").append(address)
|
||||||
|
.append("<br>code:").append(beatResult.getCode())
|
||||||
|
.append("<br>msg:").append(beatResult.getMsg());
|
||||||
|
|
||||||
|
// beat success
|
||||||
if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
||||||
jobLog.setExecutorAddress(address);
|
jobLog.setExecutorAddress(address);
|
||||||
|
|
||||||
|
@ -158,32 +151,45 @@ public class RemoteHttpJobBean extends QuartzJobBean {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
||||||
}
|
} else if (executorRouteStrategyEnum == ExecutorRouteStrategyEnum.BUSYOVER) {
|
||||||
}
|
for (String address : addressList) {
|
||||||
}
|
// beat
|
||||||
|
ReturnT<String> idleBeatResult = null;
|
||||||
/**
|
|
||||||
* run executor
|
|
||||||
* @param address
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<String> beatExecutor(String address){
|
|
||||||
ReturnT<String> beatResult = null;
|
|
||||||
try {
|
try {
|
||||||
ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
|
ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
|
||||||
beatResult = executorBiz.beat();
|
idleBeatResult = executorBiz.idleBeat(triggerParam.getJobId());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("", e);
|
logger.error("", e);
|
||||||
beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+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());
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer("心跳检测:");
|
// beat success
|
||||||
sb.append("<br>address:").append(address);
|
if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
||||||
sb.append("<br>code:").append(beatResult.getCode());
|
jobLog.setExecutorAddress(address);
|
||||||
sb.append("<br>msg:").append(beatResult.getMsg());
|
|
||||||
beatResult.setMsg(sb.toString());
|
|
||||||
|
|
||||||
return beatResult;
|
ReturnT<String> runResult = runExecutor(triggerParam, address);
|
||||||
|
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
|
||||||
|
|
||||||
|
return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
||||||
|
} else {
|
||||||
|
// get address
|
||||||
|
String address = executorRouteStrategyEnum.getRouter().route(jobInfo.getId(), addressList);
|
||||||
|
jobLog.setExecutorAddress(address);
|
||||||
|
|
||||||
|
// run
|
||||||
|
ReturnT<String> runResult = runExecutor(triggerParam, address);
|
||||||
|
triggerSb.append("<br>----------------------<br>").append(runResult.getMsg());
|
||||||
|
|
||||||
|
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…
Reference in New Issue