概念与功能
分布式定时任务调度框架是一种专门用于在分布式系统中管理和调度定时任务的工具。这类框架能够在多个节点上协调执行任务,确保任务按照预定的时间和频率执行。从系统分析角度来讲,所有的分布式定时任务调度器都包含四个核心概念。
- Job: 作业,代表需要被调度和执行的任务
- Trigger: 触发器,定义Job的触发时机
- Executor: 执行器,执行任务的工作节点
- Scheduler: 调度器,根据Trigger信息,对Job进行调度分配
一个完善的分布式定时任务调度器应该具有如下的功能:
- 任务管理功能:
- 按照设置好的任务调度策略触发任务的分配与执行
- 允许用户添加新任务、编辑已有任务的配置信息,以及删除不再需要的任务
- 支持设置任务之间的依赖关系,确保任务按照指定的顺序执行
- 有且只有一个服务节点执行某个触发器上的作业
- 任务监控功能:
- 提供实时的任务执行状态监控
- 记录任务执行的开始时间,结束时间,执行结果和具体的执行器地址等
- 具有良好的可扩展性和可用性
- 每天可以调度数千、数万甚至上百万个任务的执行
- 不会因为系统中部分机器的故障导致任务调度失败
目前,在Java生态中,有很多成熟的分布式任务调度框架可供选择。接下来,我们来列举几个常用的分布式定时任务调度框架。
Quartz Scheduler
Quartz Scheduler是一款开源的分布式任务调度框架,其全称是Quartz Enterprise Job Scheduler。Quartz Scheduler依赖数据库存储来记录任务状态,进行任务的调度。
Quartz Scheduler框架具有如下几个核心概念:
- Job: Job代表一个需要被调度的具体任务。
- JobDetail: JobDetail是用来描述Job详细信息的类。每个JobDetail对象包含了Job的关键信息,包括Job的名称、Job组名、Job类、Job数据等。
- Trigger: Trigger是用于定义任务执行时间和执行规则的组件。每个Job都需要关联一个或多个Trigger,以指定任务何时执行。常用的Trigger类型有SimpleTrigger和CronTrigger等。
- JobStore: JobStore负责Job和Trigger的持久化存储。
- Scheduler: Scheduler是Quartz Scheduler的核心组件,负责管理和协调所有的任务调度工作。
- Listener: Quartz Scheduler提供了丰富的监听器接口,开发人员可以实现自定义的监听器来监控任务的执行状态、处理任务执行事件等。
Quartz Scheduler的主要工作流程如下图所示:
当使用Quartz Scheduler框架时,我们通常需要编写一些代码来配置调度器(scheduler)、定义任务逻辑(Job)和触发器(Trigger)以及启动调度器。相关代码示例如下所示。
// 创建调度器 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 创建Job实例 JobDetail job = JobBuilder.newJob(SimpleJob.class) .withIdentity("simpleJob", "group1") .build(); // 创建Trigger,20秒后执行 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("simpleTrigger", "group1") .startAt(DateBuilder.futureDate(20, DateBuilder.IntervalUnit.SECOND)) .build(); // 启动调度器 scheduler.start(); // 将Job和Trigger关联到调度器,完成任务调度设置 scheduler.scheduleJob( jobDetail, trigger );
Quartz Scheduler是比较古老的一款分布式任务调度框架,它简单易用,上手方便,适用于小型分布式系统。该框架也存在着一些缺点,例如:水平扩展性差(Quartz依赖数据库锁来保证有且只有一个执行器运行某项具体Job),缺少可视化管理等。
ElasticJob
ElasticJob最初是由当当网开源的分布式调度框架,该框架目前已经是Apache ShardingSphere开源项目下的子项目。ElasticJob底层处理逻辑依赖于Quartz,但是相对于Quartz,ElasticJob的核心竞争力主要包括:良好的可扩展性,任务分片和可视化管理。ElasticJob在发布之初只有一个elastic-job-core项目。从2.x版本开始,该项目被拆分成elastic-job-lite和elastic-job-cloud两个子项目。elastic-job-lite 为轻量级无中心化解决方案,使用 jar 包提供分布式任务的调度和治理。 elastic-job-cloud 采用中心化架构设计,通过Mesos对资源进行控制,并且通过部署在Mesos Master上面的调度器进行任务和资源的分配。
接下来,我们主要介绍一下elatic-job-lite框架的工作原理。本章节中的工作原理介绍基于elastic-job-lite 2.1.5版本进行。
在ElasticJob框架中,任务调度执行处理流程如下所示:
虽然ElasticJob在底层依然依赖Quartz Scheduler框架针对单个job做任务调度工作,但是在确保任务执行节点唯一性方面却有显著的优势。因为ElasticJob不再依赖分布式锁抢占来保证任务执行节点的唯一性,而是通过向zookeepr的job节点添加相关配置信息而提前为任务调度工作分配好执行器节点,同时利用了zookeeper的服务注册与发现功能实现了任务调度故障迁移功能。ElasticJob中的任务分片功能也极大地提高了任务执行的速度和效率。
XXL-JOB
XXL-JOB也是一款目前使用比较多的开源分布式任务调度系统,该系统的早期版本在任务调度方面也是依赖Quartz框架进行的。但是,从v2.1.0版本开始,该系统使用了自研调度组件替代了底层对Quartz框架的依赖(注意:这次的版本升级并不是向前兼容的。所以如果想要将生产环境正在使用的v1.x版本XXL-JOB系统升级到v2.1.x版本,那么在已有任务的无缝迁移上面可能面临一些比较头疼的问题,具体升级方案可以参考我之前发表的一篇文章:XXL-JOB最佳实践与升级指南)。与ElasticJob不同的是,XXL-JOB具有明确的任务调度服务器集群来进行任务调度。目前官方网站给出的v2.4.0版本架构图如下所示:
有关该系统的具体使用方法,本文内容不做过多的介绍。感兴趣的读者可以自行前往相关官方网站进行查看。这里我们只是介绍一下XXL-JOB自研任务调度组件的工作原理。
如上面的架构图所示,XXL-JOB主要由两个子系统组成,分别是调度中心侧子系统和执行器侧子系统。自研任务调度组件功能工作在调度中心侧子系统中。下载相关源代码之后,我们可以直接对相关功能进行静态分析和动态分析。分析之后,我们会发现任务调度的主要处理逻辑是在JobScheduleHelper类中完成的。主要处理流程如下所示:
总结
本文介绍了三种常用的轻量级分布式定时任务调度器以及它们的底层工作原理,更多相关知识请阅读书籍《Java网络爬虫精解与实践》。本文由原创作者首发在阿里云技术社区,未经许可,请勿转载。