xuxueli / xxl-job

A distributed task scheduling framework.(分布式任务调度平台XXL-JOB)
http://www.xuxueli.com/xxl-job/
GNU General Public License v3.0
27.46k stars 10.86k forks source link

请教下各位大佬,如果任务执行成功后,需要产出一个result。子任务的执行依赖父任务的这个result。xxl-job应该怎么去修改,能不能给个思路。 #2965

Open Dawenxes opened 2 years ago

Dawenxes commented 2 years ago

Please answer some questions before submitting your issue. Thanks!

Which version of XXL-JOB do you using?

2.3.1

Expected behavior

目前对于执行结果只是打印日志。

Actual behavior

任务执行结束后,结果的处理。希望可以持久化。这个result,可能是json字符串,也可能是一个文件(这个业务可能不一定,json应该已经够用了)。并且子任务的入参希望能带上父任务的执行结果。

Steps to reproduce the behavior

Other information

RongieZeng commented 2 years ago

找到 XxlJobJobCompleter类下面的这个方法 finishJob方法,在入参的XxlJobLog对象中加多个字段,把父任务的执行结果通过该字段传进来,然后你可以通过把结果通过 JobTriggerPoolHelper.trigger方法的executorParam参数继续传递下去,最终executorParam会被传递到执行器,通过XxlJobHelper.getJobParam()就可以拿到这个参数了

    private static void finishJob(XxlJobLog xxlJobLog){  // 1、加字段
        // 1、handle success, to trigger child job
        String triggerChildMsg = null;
        if (XxlJobContext.HANDLE_CODE_SUCCESS == xxlJobLog.getHandleCode()) {
            XxlJobInfo xxlJobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(xxlJobLog.getJobId());
            if (xxlJobInfo!=null && xxlJobInfo.getChildJobId()!=null && xxlJobInfo.getChildJobId().trim().length()>0) {
                triggerChildMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_child_run") +"<<<<<<<<<<< </span><br>";

                String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
                for (int i = 0; i < childJobIds.length; i++) {
                    int childJobId = (childJobIds[i]!=null && childJobIds[i].trim().length()>0 && isNumeric(childJobIds[i]))?Integer.valueOf(childJobIds[i]):-1;
                    if (childJobId > 0) {
                        // 2、把参数传递下去
                        JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null, xxlJobLog.getTriggerTimeZoneId());
                        ReturnT<String> triggerChildResult = ReturnT.SUCCESS;

                        // add msg
                        triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg1"),
                                (i+1),
                                childJobIds.length,
                                childJobIds[i],
                                (triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?I18nUtil.getString("system_success"):I18nUtil.getString("system_fail")),
                                triggerChildResult.getMsg());
                    } else {
                        triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg2"),
                                (i+1),
                                childJobIds.length,
                                childJobIds[i]);
                    }
                }

            }
        }

        if (triggerChildMsg != null) {
            xxlJobLog.setHandleMsg( xxlJobLog.getHandleMsg() + triggerChildMsg );
        }

        // 2、fix_delay trigger next
        // on the way

    }
Dawenxes commented 2 years ago

明白了,感谢作者分享。非常期待你的2.4版本上线!

------------------ 原始邮件 ------------------ 发件人: RongieZeng @.> 发送时间: 2022年9月2日 09:56 收件人: xuxueli/xxl-job @.> 抄送: Dawenxes @.>, Author @.> 主题: Re: [xuxueli/xxl-job] 请教下各位大佬,如果任务执行成功后,需要产出一个result。子任务的执行依赖父任务的这个result。xxl-job应该怎么去修改,能不能给个思路。 (Issue #2965)

找到 XxlJobJobCompleter类下面的这个方法 finishJob方法,在入参的XxlJobLog对象中加多个字段,把父任务的执行结果通过该字段传进来,然后你可以通过把结果通过 JobTriggerPoolHelper.trigger方法的executorParam参数继续传递下去,最终executorParam会被传递到执行器,通过XxlJobHelper.getJobParam()就可以拿到这个参数了

` /**

LiangJiechao commented 1 year ago

你好,我想问问 怎么调用到 finishJob(XxlJobLog xxlJobLog) 方法呢,我已经修改了XxlJobLog 的字段,也修改了finishJob(),但在任务中怎么将结果传递到这里呢?

LiangJiechao commented 1 year ago

你好,我想问问 怎么调用到 finishJob(XxlJobLog xxlJobLog) 方法呢,我已经修改了XxlJobLog 的字段,也修改了finishJob(),但在任务中怎么将结果传递到这里呢?

直接引入 admin 依赖, 然后在父任务中这样传递吗

// 设置结果,传递给子任务
XxlJobLog xxlJobLog = new XxlJobLog();
xxlJobLog.setResult("返回结果:传给子任务");
XxlJobCompleter.updateHandleInfoAndFinish(xxlJobLog);
RongieZeng commented 1 year ago

你好,我想问问 怎么调用到 finishJob(XxlJobLog xxlJobLog) 方法呢,我已经修改了XxlJobLog 的字段,也修改了finishJob(),但在任务中怎么将结果传递到这里呢?

直接引入 admin 依赖, 然后在父任务中这样传递吗

// 设置结果,传递给子任务
XxlJobLog xxlJobLog = new XxlJobLog();
xxlJobLog.setResult("返回结果:传给子任务");
XxlJobCompleter.updateHandleInfoAndFinish(xxlJobLog);

代码没错。不过这个不是在客户端(即 JobHandler)引入admin依赖,而是要去改xxl-job调度中心(xxl-job-admin模块),然后重新打包xxl-job-admin部署调度中心

Dawenxes commented 1 year ago

还需要改executor端callback 的时候,把result塞到callbackParam中去

LiangJiechao commented 1 year ago

你好,我想问问 怎么调用到 finishJob(XxlJobLog xxlJobLog) 方法呢,我已经修改了XxlJobLog 的字段,也修改了finishJob(),但在任务中怎么将结果传递到这里呢?

直接引入 admin 依赖, 然后在父任务中这样传递吗

// 设置结果,传递给子任务
XxlJobLog xxlJobLog = new XxlJobLog();
xxlJobLog.setResult("返回结果:传给子任务");
XxlJobCompleter.updateHandleInfoAndFinish(xxlJobLog);

代码没错。不过这个不是在客户端(即 JobHandler)引入admin依赖,而是要去改xxl-job调度中心(xxl-job-admin模块),然后重新打包xxl-job-admin部署调度中心

com.xxl.job.admin.core.thread.JobCompleteHelper#callback(com.xxl.job.core.biz.model.HandleCallbackParam)
是在这个方法里塞结果吗,但我还是不知道怎么获取父的结果,怎么塞到 log 里
LiangJiechao commented 1 year ago

finishJob

这个父 job 的参数传递不是已经在 com.xxl.job.admin.core.complete.XxlJobCompleter#finishJob 方法中的 JobTriggerPoolHelper.trigger() 这里传递下去了吗,在父完成后触发子的时候

Dawenxes commented 1 year ago

是的,在trigger子任务的时候,把父任务的result作为executeParam传下去

LiangJiechao commented 1 year ago

是的,在trigger子任务的时候,把父任务的result作为executeParam传下去

但往前一步,在哪里怎么把父的结果塞入 log 里面呢

Dawenxes commented 1 year ago

可以在executor端,任务执行的时候将结果设置到jobContext,例如XxlJobContext.getXxlJobContext().setXxlJobResult(xxlJobResult);。然后jobThread调用callback的时候,从jobContext取出jobResult设置到callbackParam中去

LiangJiechao commented 1 year ago

可以在executor端,任务执行的时候将结果设置到jobContext,例如XxlJobContext.getXxlJobContext().setXxlJobResult(xxlJobResult);。然后jobThread调用callback的时候,从jobContext取出jobResult设置到callbackParam中去

你好,这里我调试了一下,父任务中的 executor 确实保存了运行后的结果,是存到了 XxlJobContext 中,但这个XxlJobContext 是一个 ThreadLocal 对象,但是子任务的运行 不会在 父任务运行的线程中执行,所以在子任务中拿到不父任务的 threadlocal 存放的结果

虽然XxlJobContext 是一个 InheritableThreadLocal 对象,但是因为任务的运行是从线程池中拿的,所以也无法继承父线程的 threadlocal 对象

LiangJiechao commented 1 year ago

还有一个问题,我好像没找到父任务和子任务的关联,就是父任务执行完后怎么触发子任务的执行的

Dawenxes commented 1 year ago

在triggercallbackthread中触发回调,用的netty通信的,这个得跟源码了。

------------------ 原始邮件 ------------------ 发件人: LiangJiechao @.> 发送时间: 2022年10月17日 16:17 收件人: xuxueli/xxl-job @.> 抄送: Dawenxes @.>, Author @.> 主题: Re: [xuxueli/xxl-job] 请教下各位大佬,如果任务执行成功后,需要产出一个result。子任务的执行依赖父任务的这个result。xxl-job应该怎么去修改,能不能给个思路。 (Issue #2965)

还有一个问题,我好像没找到父任务和子任务的关联,就是父任务执行完后怎么触发子任务的执行的

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

LiangJiechao commented 1 year ago

是,我也调试到这里了,但是看调试的变量中,都看不到子任务的 id 的相关信息,怎么就触发了呢, 假如父任务的 id 是 5,子任务的 id 是 6,在admin管理页面设置好了子任务 id 为 6,但在父任务的调试过程中,都看不到子任务 id=6的踪迹

Dawenxes commented 1 year ago

com.xxl.job.admin.core.complete.XxlJobCompleter#updateHandleInfoAndFinish

是,我也调试到这里了,但是看调试的变量中,都看不到子任务的 id 的相关信息,怎么就触发了呢, 假如父任务的 id 是 5,子任务的 id 是 6,在admin管理页面设置好了子任务 id 为 6,但在父任务的调试过程中,都看不到子任务 id=6的踪迹 最终调用子任务,在这个方法里面com.xxl.job.admin.core.complete.XxlJobCompleter#updateHandleInfoAndFinish。你可以断点跟下

Dawenxes commented 1 year ago

最终调用子任务,在这个方法里面com.xxl.job.admin.core.complete.XxlJobCompleter#updateHandleInfoAndFinish。你可以断点跟下

是,我也调试到这里了,但是看调试的变量中,都看不到子任务的 id 的相关信息,怎么就触发了呢, 假如父任务的 id 是 5,子任务的 id 是 6,在admin管理页面设置好了子任务 id 为 6,但在父任务的调试过程中,都看不到子任务 id=6的踪迹

LiangJiechao commented 1 year ago

最终调用子任务,在这个方法里面com.xxl.job.admin.core.complete.XxlJobCompleter#updateHandleInfoAndFinish。你可以断点跟下

是,我也调试到这里了,但是看调试的变量中,都看不到子任务的 id 的相关信息,怎么就触发了呢, 假如父任务的 id 是 5,子任务的 id 是 6,在admin管理页面设置好了子任务 id 为 6,但在父任务的调试过程中,都看不到子任务 id=6的踪迹

com.xxl.job.admin.core.complete.XxlJobCompleter#finishJob
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");

看到了,这里有子任务的 id 信息,谢谢