xxl-job源码解读:执行器Excutor调用链路

本文基于xxl-job的2.3.1版本

执行器,即任务逻辑代码所在的服务,也就是你的业务项目,由调度中心的触发器通过网络请求,调用执行的任务执行

1. 执行器客户端加载

在获取执行器客户端时,会根据指定的地址获取执行器客户端,如果执行器未初始化,会初始化一个执行器

com.xxl.job.admin.core.scheduler.XxlJobScheduler

       public static ExecutorBiz getExecutorBiz(String address) {
            // valid
            if (address == null || address.trim().length() == 0) {
                return null;
            }
    
            // load-cache
            address = address.trim();
            ExecutorBiz executorBiz = executorBizRepository.get(address);
            if (executorBiz != null) {
                return executorBiz;
            }
    
            // set-cache
            executorBiz = new ExecutorBizClient(address, XxlJobAdminConfig.getAdminConfig().getAccessToken());
    
            executorBizRepository.put(address, executorBiz);
            return executorBiz;
        }

2. 执行器调用

2.1 客户端方法介绍

通过该接口定义调度中心对客户端发起的一系列请求,其中run方法就是执行任务。

com.xxl.job.core.biz.ExecutorBiz

    /**
     * 执行器心跳
     * <p>用于 路由策略-故障转移 的执行器心跳检查</p>
     *
     * @return 处理结果
     */
    ReturnT<String> beat();

    /**
     * 闲置心跳检查(执行中或在队列中属于非闲置状态)
     * <p>用于 路由策略-忙碌转移 检查非闲置节点</p>
     *
     * @param idleBeatParam 参数(仅任务ID)
     * @return 是否闲置
     */
    ReturnT<String> idleBeat(IdleBeatParam idleBeatParam);

    /**
     * 任务执行
     * <p>调度中心任务触发</p>
     *
     * @param triggerParam 执行参数
     * @return 处理结果
     */
    ReturnT<String> run(TriggerParam triggerParam);

    /**
     * 终止任务执行(删除任务的执行线程)
     * <p>用于页面操作终止任务</p>
     *
     * @param killParam 参数(仅任务ID)
     * @return 处理结果
     */
    ReturnT<String> kill(KillParam killParam);

    /**
     * 日志内容读取
     * <p>用于页面读取日志</p>
     *
     * @param logParam 读取参数(日志ID, 起始行, 日志日期)
     * @return 日志读取结果(日志内容, 结束行等)
     */
    ReturnT<LogResult> log(LogParam logParam);

该接口有两个实现类:

com.xxl.job.core.biz.client.ExecutorBizClient 调度中心使用的执行器客户端

com.xxl.job.core.biz.impl.ExecutorBizImpl 执行器所在应用处理任务调度请求的实现类

2.2 调度中心发起请求

调度器Trigger中根据配置选定执行器客户端之后,调用客户端的run方法,发出http请求

com.xxl.job.admin.core.trigger.XxlJobTrigger

        /**
         * 触发任务执行
         *
         * @param triggerParam 任务参数
         * @param address      执行器地址
         * @return 执行结果
         */
        public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address) {
            ReturnT<String> runResult;
            try {
                ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
                runResult = executorBiz.run(triggerParam);
            } catch (Exception e) {
                logger.error(">>>>>>>>>>> xxl-job trigger error, please check if the executor[{}] is running.", address, e);
                runResult = new ReturnT<>(ReturnT.FAIL_CODE, ThrowableUtil.toString(e));
            }
    
            String runResultSB = I18nUtil.getString("jobconf_trigger_run") + ":" + "<br>address:" + address +
                    "<br>code:" + runResult.getCode() +
                    "<br>msg:" + runResult.getMsg();
    
            runResult.setMsg(runResultSB);
            return runResult;
        }

com.xxl.job.core.biz.client.ExecutorBizClient

        @Override
        public ReturnT<String> run(TriggerParam triggerParam) {
            return XxlJobRemotingUtil.postBody(addressUrl + "run", accessToken, DEFAULT_TIMEOUT, triggerParam, String.class);
        }

这里 XxlJobRemotingUt 通过HttpURLConnection 发起HTTP请求到执行中,由执行器中的 EmbedServer 接受请求

2.3 执行器接收请求

接收调度中心发送的请求的 rpc客户端也是由作者依赖netty实现 https://github.com/xuxueli/xxl-rpc

这里不细究具体的客户端实现,看下请求的分发调用。

接受到请求之后,根据路由区分调用 ExecutorBizImpl 的方法

com.xxl.job.core.server.EmbedServer

          private Object process(HttpMethod httpMethod, String uri, String requestData, String accessTokenReq) {
                // valid
                if (HttpMethod.POST != httpMethod) {
                    return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, HttpMethod not support.");
                }
                if (uri == null || uri.trim().length() == 0) {
                    return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping empty.");
                }
                if (accessToken != null
                        && accessToken.trim().length() > 0
                        && !accessToken.equals(accessTokenReq)) {
                    return new ReturnT<String>(ReturnT.FAIL_CODE, "The access token is wrong.");
                }
    
                // services mapping
                try {
                    switch (uri) {
                        case "/beat":
                            return executorBiz.beat();
                        case "/idleBeat":
                            IdleBeatParam idleBeatParam = GsonTool.fromJson(requestData, IdleBeatParam.class);
                            return executorBiz.idleBeat(idleBeatParam);
                        case "/run":
                            TriggerParam triggerParam = GsonTool.fromJson(requestData, TriggerParam.class);
                            return executorBiz.run(triggerParam);
                        case "/kill":
                            KillParam killParam = GsonTool.fromJson(requestData, KillParam.class);
                            return executorBiz.kill(killParam);
                        case "/log":
                            LogParam logParam = GsonTool.fromJson(requestData, LogParam.class);
                            return executorBiz.log(logParam);
                        default:
                            return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping(" + uri + ") not found.");
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                    return new ReturnT<String>(ReturnT.FAIL_CODE, "request error:" + ThrowableUtil.toString(e));
                }
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值