elastic-job源码分析(二)任务调度

前一节分析了一下elastic的启动过程,接下来看一下它的调度过程。elastic-job的调度引擎是基于quartz,也就是说调度这一块都是quartz来负责,elastic-job则在上层逻辑进行处理。
那么从作业开始调度开始看起

public void init() {
        // 1.将配置更新到注册中心
        LiteJobConfiguration liteJobConfigFromRegCenter = schedulerFacade.updateJobConfiguration(liteJobConfig);
        // 2.缓存当前作业分片数到本地
        JobRegistry.getInstance().setCurrentShardingTotalCount(liteJobConfigFromRegCenter.getJobName(), liteJobConfigFromRegCenter.getTypeConfig().getCoreConfig().getShardingTotalCount());
        // 3.JobScheduleController 实例,controller类负责控制quartz调度引擎
        JobScheduleController jobScheduleController = new JobScheduleController(
                createScheduler(), createJobDetail(liteJobConfigFromRegCenter.getTypeConfig().getJobClass()), liteJobConfigFromRegCenter.getJobName());
        // 4.缓存作业对应的controller对应的
        JobRegistry.getInstance().registerJob(liteJobConfigFromRegCenter.getJobName(), jobScheduleController, regCenter);
        // 5.作业开始调度前,更改一些配置()
        schedulerFacade.registerStartUpInfo(!liteJobConfigFromRegCenter.isDisabled());
        // 6.根据cron表达式开始调度作业
        jobScheduleController.scheduleJob(liteJobConfigFromRegCenter.getTypeConfig().getCoreConfig().getCron());
    }

前几个步前面都说过,主要看第六步,第六步是调用JobSchedulerController控制器来根据cron表达式来使用quartz来开启调度。

public void scheduleJob(final String cron) {
        try {
            if (!scheduler.checkExists(jobDetail.getKey())) {
                scheduler.scheduleJob(jobDetail, createTrigger(cron));
            }
            scheduler.start();
        } catch (final SchedulerException ex) {
            throw new JobSystemException(ex);
        }
    }

先检查了schdeduler是否设置了jobDetail,如果没有则设置jobDetail,最后调用start开启任务调度。
在实例化JobSchedulerController时,创建JobDetail,使用的jobClass是LiteJob

private JobDetail createJobDetail(final String jobClass) {
		// 使用LiteJob类作为中间类,协调elastic和quartz
        JobDetail result = JobBuilder.newJob(LiteJob.class).withIdentity(liteJobConfig.getJobName()).build();
        // 作业门面设置到jobDataMap最终设置到LiteJob中
        result.getJobDataMap().put(JOB_FACADE_DATA_MAP_KEY, jobFacade);
        Optional<ElasticJob> elasticJobInstance = createElasticJobInstance();
        if (elasticJobInstance.isPresent()) {
        	// 设置真实的作业执行类到LiteJob
            result.getJobDataMap().put(ELASTIC_JOB_DATA_MAP_KEY, elasticJobInstance.get());
        } else if (!jobClass.equals(ScriptJob.class.getCanonicalName())) {
            try {
                result.getJobDataMap().put(ELASTIC_JOB_DATA_MAP_KEY, Class.forName(jobClass).newInstance());
            } catch (final ReflectiveOperationException ex) {
                throw new JobConfigurationException("Elastic-Job: Job class '%s' can not initialize.", jobClass);
            }
        }
        return result;
    }

LiteJob是一个中间类,用于衔接quartz和elastic-job,具体如何操作的看下LiteJob

public final class LiteJob implements Job {

    // 提供set方法,可以从JobDataMap取相同key的value自动设置到属性上
    @Setter
    private ElasticJob elasticJob;
    @Setter
    private JobFacade jobFacade;

    @Override
    public void execute(final JobExecutionContext context) throws JobExecutionException {
        // 根据job类型获取具体的job执行器
        JobExecutorFactory.getJobExecutor(elasticJob, jobFacade).execute();
    }
}

这个类有两个属性,一个是elastic-job的作业接口,后面所有类型的作业都是实现了这个接口,第二个是作业的门面接口,包括了一些作业执行状态更改配置加载的一些用途。这里有个小技巧,对相应的属性提供set方法,然后就可以将创建jobDetail时设置到JobDataMap里面的数据自动注入了,但是key的名字一定要和属性名一致。当作业触发执行时,根据job类型获取Executor进行执行,最终调用真实作业的execute方法。

public static AbstractElasticJobExecutor getJobExecutor(final ElasticJob elasticJob, final JobFacade jobFacade) {
        if (null == elasticJob) {
            return new ScriptJobExecutor(jobFacade);
        }
        if (elasticJob instanceof SimpleJob) {
            return new SimpleJobExecutor((SimpleJob) elasticJob, jobFacade);
        }
        if (elasticJob instanceof DataflowJob) {
            return new DataflowJobExecutor((DataflowJob) elasticJob, jobFacade);
        }
        throw new JobConfigurationException("Cannot support job type '%s'", elasticJob.getClass().getCanonicalName());
    }

本文主讲SimpleJob类型作业,其他自行探讨。我们再进入SimpleJobExecutor查看

public final class SimpleJobExecutor extends AbstractElasticJobExecutor {
    private final SimpleJob simpleJob;
    public SimpleJobExecutor(final SimpleJob simpleJob, final JobFacade jobFacade) {
        super(jobFacade);
        this.simpleJob = simpleJob;
    }
    // 调用真实的作业执行
    @Override
    protected void process(final ShardingContext shardingContext) {
        simpleJob.execute(shardingContext);
    }
}

好像发现并没有execute方法哎,别急,先看下process方法,该方法直接调用了真实的作业类型。而对于execute则是由其父类抽象实现具体如下图
任务调度时序图
最终还是调用了Executor,而在executor中调用了真实作业的execute方法,并将分片参数传入。至于分片相关后面章节会提到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三寸花笺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值