LTS分布式任务调度在项目中的实际应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zyjcxc/article/details/82685682

公司项目是分布式的,所以定时任务用lts框架,简单的看看代码,分析了一下,找到调用流程。

注意:不了解lts的先看下这个文档,我也是看完才看懂代码
文档地址:https://www.cnblogs.com/dion-90/articles/8674591.html

lts的工作流程

  • JobClient 提交一个 任务 给 JobTracker, 这里我提供了两种客户端API, 一种是如果JobTracker 不存在或者提交失败,直接返回提交失败。另一种客户端是重试客户端, 如果提交失败,先存储到本地leveldb(可以使用NFS来达到同个节点组共享leveldb文件的目的,多线程访问,做了文件锁处理),返回给客户端提交成功的信息,待JobTracker可用的时候,再将任务提交。
  • JobTracker 收到JobClient提交来的任务,先生成一个唯一的JobID。然后将任务储存在Mongo集群中。JobTracker 发现有(任务执行的)可用的TaskTracker节点(组) 之后,将优先级最大,最先提交的任务分发给TaskTracker。这里JobTracker会优先分配给比较空闲的TaskTracker节点,达到负载均衡。
  • TaskTracker 收到JobTracker分发来的任务之后,执行。执行完毕之后,再反馈任务执行结果给JobTracker(成功or 失败[失败有失败错误信息]),如果发现JobTacker不可用,那么存储本地leveldb,等待TaskTracker可用的时候再反馈。反馈结果的同时,询问JobTacker有没有新的任务要执行。
  • JobTacker收到TaskTracker节点的任务结果信息,生成并插入(mongo)任务执行日志。根据任务信息决定要不要反馈给客户端。不需要反馈的直接删除, 需要反馈的(同样JobClient不可用存储文件,等待可用重发)。
  • JobClient 收到任务执行结果,进行自己想要的逻辑处理。

代码分析

以我公司为例, spring cloud里有两个服务分别是JobClientJobTracker

其中task相当于JobClient, job相当于JobTracker

1.task中的代码, 项目启动运行这个方法, 这相当是定制任务的基本信息:

// task中的代码, 项目启动运行这个方法
/**
 * 定时生成  ...数据
 */
public void jobMethod()
{
    // 定义个bean, 里面可以定义属性
    SynMainTainMsgCommand command = new SynMainTainMsgCommand();

    // 定义任务对象
    Job job = new Job();
    // taskId自定义
    job.setTaskId("doMainTainProdcut");
    // 自定义参数,实际就是HashMap
    job.setParam("description", "定时生成 车辆 保养数据");
    // 注意这里传的commond对象的类全名
    job.setParam("command", command.getClass().getName());
    job.setTaskTrackerNodeGroup("组名");
    job.setNeedFeedback(true);
    job.setReplaceOnExist(true);      // 当任务队列中存在这个任务的时候,是否替换更新
    job.setCronExpression("cron表达式");
    // 提交任务
    Response response = jobClient.submitJob(job);
}

2.先把job任务写了,一会再说怎么调用的
在job服务里实现相应的任务:

@Component
public class SynMainTainMsgHandler extends BaseCommandHandler<SynMainTainMsgCommand, HttpCommandResultWithData> {

    // ...略

    public HttpCommandResultWithData handler(SynMainTainMsgCommand command) {
        // 具体的任务实现...
    }

}

3.关键是下一步,job怎么收到并且执行的


// 1.实现JobRunner的run方法
@JobRunner4TaskTracker
public class JobRunnerImpl implements JobRunner {

    @Override
    public Result run(JobContext jobContext) throws Throwable {
        String successjson;
        try {
        // 接到参数
        String command = jobContext.getJob().getParam("command");
        String commandParam = jobContext.getJob().getParam("commandParam");

        // 反射找到上面定义的bean
        Class clazz = Class.forName(command);

        // ...略部分代码
        Object o = clazz.newInstance();

        // 这里想通过command找handler,并执行
        Command.Result handlerresult = dispatch((AbstractCommand)o);
        // 这里只要找到 BaseCommandHandler的handler方法执行就行了,因为上面的SynMainTainMsgHandler继承了BaseCommandHandler

            successjson = JsonUtil.toJson(handlerresult);


        return new Result(Action.EXECUTE_SUCCESS, successjson);
    }
}
  1. 这里只要找到 BaseCommandHandler的handler方法执行就行了,因为上面的SynMainTainMsgHandler继承了BaseCommandHandler,
    BaseCommandHandler继承CommandHandler。

private <C extends Command<?>, CR extends Command.Result> CR dispatch(C command) {
        CommandHandler<C, CR> commandHandler = (CommandHandler)this.handlerByType.get(command.getClass());
        return commandHandler.handle(command);
    }

省略部分代码,实现思路就是通过传进来的command.className获取到具体的handler。

猜你喜欢

转载自blog.csdn.net/zyjcxc/article/details/82685682