⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 君哥聊技术 「君哥聊技术」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

在工作中,批量任务调度的需求经常会遇到,比如下面的几个场景:

  1. 数据迁移:从数据库 A 批量读取数据,加工后把数据写入数据库 B;
  2. 消息通知:运营商批量给客户发送短信;
  3. 批量扣款:在还款日,银行批量扣除贷款客户的当期还款金额;
  4. 账务加工:系统通过日终跑批的方式加工当天的账务数据。

从开源框架来看,优秀的分布式任务调度框架并不少,比如 Quartz、Spring Batch、xxl-job、PowerJob 等。如果公司不使用开源框架,要自研一套,该如何设计呢?

今天就来聊一聊怎样设计一套分布式任务调度平台。

1.触发器

既然是任务调度,那触发器肯定是必不可少的。触发器就是控制任务什么时间开始执行,使用者可以定义好 Cron 表达式,到时间保证任务被触发。

除了定时触发外,也要设计通用的触发接口,方便地给外部系统提供触发入口。

在一些对账类的场景,可能多个系统联合对账,上游系统加工好后把账务文件送过来,触发本系统的批量任务进行对账。本系统对账完成后,要把对账结果异步通知给调用方。

2.调度器

调度器的主要作用是给待执行任务找到一台合适的机器,然后把它调度到这台集群上的待执行队列。

2.1 调度策略

调度器的调度策略可以有几种:

  • 调度到固定一台机器;
  • 以轮询方式调度到下一台机器;
  • 根据集群中各机器的资源状况调度到一台空闲的机器,这个比较难一些;
  • 随机选择一台机器;
  • 所有机器都执行。

在集群环境下,调度器对定时任务的作用是非常重要的,调度不好,很容易导致任务在不同机器上重复执行。

同时,调度器可以根据机器的资源情况进行任务调度,提高任务执行效率。

当然,也可能会有广播的场景,这时调度器需要把任务调度到所有的机器上执行。

还需要考虑的一个点就是任务优先级,优先级高的任务需要优先调度。

3 执行器

调度器把任务调度到某一个机器上后,就把任务交给了执行器。执行器可以定义一个线程池,接到任务后把任务丢到线程池中,等待被线程池调度。

执行器可以提供一个基类,任务类通过继承这个基类被调度平台识别。

4.任务链

任务链也是非常重要的概念,在任务调度平台上要支持任务链的定义,比如 task1->task2->task3 这样一条任务链,task1 执行完成后触发 task2,task2 执行完成后触发 task3。

任务链使用的业务场景很多。比如一个复杂度高、耗时很长的任务,可以拆分成多个子任务,这样如果有一个任务失败了,把异常问题解决后,从失败任务节点重新调起就可以。

实现任务链的方法有多种,这里提供两个思路供参考,一个是不定义任务链,给每个任务定义一个子任务,触发时只触发第一个任务,任务执行完成后执行子任务;第二个方法是定义一个任务链,任务链明确任务依赖关系。

5.熔断

批量任务一般用于处理数据量大的任务,比如给 10 万个客户发送短信通知。这会对本系统资源消耗较大,也可能会对下游系统造成压力。

如果没有任何防控手段,很可能会因为下游系统接口响应慢造成系统连锁反应。有了熔断能力,系统就可以及时发现问题并做出反应,对本系统和下游系统进行保护。

6.异常处理

异常处理的手段也是必要的。异常处理可以包含下面功能:

  • 用户可以方便地查看异常;
  • 解决异常后,可以方便地重新发起任务;
  • 遇到一些任务因为异常原因耗时太长,可以中断任务;
  • 遇到任务执行时间长,长时间占用系统资源,可以把任务挂起,给其他任务执行时间,其他任务执行完后可以再恢复这个任务。

7.阻塞控制

对于单机执行的任务,遇到任务排队的情况很正常。可以设置阻塞策略,比如按照 FIFO 方式进行排队执行,或者不做排队,有正在执行的任务时直接丢弃。

8.服务注册/发现

前面说到调度器会把任务调度到其中一台机器执行,那为了方便地管理集群中的机器,服务注册和发现功能也是很必要的。

9.任务监控

好多跑批任务是在日终执行,比如凌晨。把任务加入公司的监控体系,如果任务失败,触发监控告警,可以让运维人员和研发人员第一时间感知到。

10.控制台

有了上面的讨论,控制台的作用就很重要的。可以包括:

  • 触发器配置;
  • 触发类型配置;
  • 调度器配置;
  • 执行器配置;
  • 任务和子任务配置;
  • 异常处理;
  • 阻塞控制策略配置;
  • 任务执行状态查询;
  • 集群管理。

11.总结

通过本文的讨论,我们设计一个任务调度平台,需要下面的功能,希望对你设计和理解任务调度平台有所帮助。

文章目录
  1. 1. 1.触发器
  2. 2. 2.调度器
    1. 2.0.1. 2.1 调度策略
  • 3. 3 执行器
  • 4. 4.任务链
  • 5. 5.熔断
  • 6. 6.异常处理
  • 7. 7.阻塞控制
  • 8. 8.服务注册/发现
  • 9. 9.任务监控
  • 10. 10.控制台
  • 11. 11.总结