任务调度中心构建

  • 任务调度中心构建

    • 系统架构
    • 搞起来
      • 一、创建数据库表
      • 二、执行器实现
      • 三、效果
      • 设计原理参见下篇文章

因工作需要,需要构建独立于业务系统之外的任务调度中心,解决当前业务系统的痛点,将调度任务做成可配置化、动态化、方便监控管理的调度中心。
      原本打算自己基于quartz+rest的方式自己造轮子的,方案也想好了,准备排期搞起来。后来调研了下,发现已经有前辈开源了非常好用的调度中心系统,经过对比选择了xxl-job进行了二次开发。记录下配置过程以及调用原理,方便后来的同学快速切入。

系统架构


xxl-job 1.9版本系统架构图如下,主要分为两大模块:
一、调度中心
调度中心即为我们需要部署的任务调度中心系统,它独立于业务系统。分为任务管理、执行器管理、日志管理、以及其他报表和任务依赖处理等。核心能力主要体现在:
1.任务调度,底层基于quartz实现分布式调度能力,通过rest rpc的方式调用业务系统内置的jetty通讯信道,调起业务系统的调度任务。
2.日志收集,实时收集任务执行过程的日志。
3.回调服务,业务系统异步回调到调度中心
4.注册服务,支持业务系统心跳注册到调度中心
二、任务执行器
任务执行器内置在业务系统中,业务系统依赖了调度中心的jar后,通过内置的jetty服务进行通讯,具体实现在下文中介绍。

搞起来

一、创建数据库表

从入门到原理,先让调度中心跑起来,首先创建数据库表,主要是quartz集群用到的表【11张,具体参考quartz开发说明】和xxl-job扩展的表【5张】。

CREATE TABLE XXL_JOB_QRTZ_JOB_DETAILS(SCHED_NAME VARCHAR(120) NOT NULL,JOB_NAME  VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,JOB_CLASS_NAME   VARCHAR(250) NOT NULL,IS_DURABLE VARCHAR(1) NOT NULL,IS_NONCONCURRENT VARCHAR(1) NOT NULL,IS_UPDATE_DATA VARCHAR(1) NOT NULL,REQUESTS_RECOVERY VARCHAR(1) NOT NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,JOB_NAME  VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,NEXT_FIRE_TIME BIGINT(13) NULL,PREV_FIRE_TIME BIGINT(13) NULL,PRIORITY INTEGER NULL,TRIGGER_STATE VARCHAR(16) NOT NULL,TRIGGER_TYPE VARCHAR(8) NOT NULL,START_TIME BIGINT(13) NOT NULL,END_TIME BIGINT(13) NULL,CALENDAR_NAME VARCHAR(200) NULL,MISFIRE_INSTR SMALLINT(2) NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)REFERENCES XXL_JOB_QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_SIMPLE_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,REPEAT_COUNT BIGINT(7) NOT NULL,REPEAT_INTERVAL BIGINT(12) NOT NULL,TIMES_TRIGGERED BIGINT(10) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES XXL_JOB_QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_CRON_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,CRON_EXPRESSION VARCHAR(200) NOT NULL,TIME_ZONE_ID VARCHAR(80),PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES XXL_JOB_QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_SIMPROP_TRIGGERS(          SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,STR_PROP_1 VARCHAR(512) NULL,STR_PROP_2 VARCHAR(512) NULL,STR_PROP_3 VARCHAR(512) NULL,INT_PROP_1 INT NULL,INT_PROP_2 INT NULL,LONG_PROP_1 BIGINT NULL,LONG_PROP_2 BIGINT NULL,DEC_PROP_1 NUMERIC(13,4) NULL,DEC_PROP_2 NUMERIC(13,4) NULL,BOOL_PROP_1 VARCHAR(1) NULL,BOOL_PROP_2 VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES XXL_JOB_QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
)  ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_BLOB_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,BLOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES XXL_JOB_QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
)  ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_CALENDARS(SCHED_NAME VARCHAR(120) NOT NULL,CALENDAR_NAME  VARCHAR(200) NOT NULL,CALENDAR BLOB NOT NULL,PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_PAUSED_TRIGGER_GRPS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_GROUP  VARCHAR(200) NOT NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_FIRED_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,ENTRY_ID VARCHAR(95) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,FIRED_TIME BIGINT(13) NOT NULL,SCHED_TIME BIGINT(13) NOT NULL,PRIORITY INTEGER NOT NULL,STATE VARCHAR(16) NOT NULL,JOB_NAME VARCHAR(200) NULL,JOB_GROUP VARCHAR(200) NULL,IS_NONCONCURRENT VARCHAR(1) NULL,REQUESTS_RECOVERY VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,ENTRY_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_SCHEDULER_STATE(SCHED_NAME VARCHAR(120) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,LAST_CHECKIN_TIME BIGINT(13) NOT NULL,CHECKIN_INTERVAL BIGINT(13) NOT NULL,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_LOCKS(SCHED_NAME VARCHAR(120) NOT NULL,LOCK_NAME  VARCHAR(40) NOT NULL, PRIMARY KEY (SCHED_NAME,LOCK_NAME)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_group` int(11) NOT NULL COMMENT '执行器主键ID',`job_cron` varchar(128) NOT NULL COMMENT '任务执行CRON',`job_desc` varchar(255) NOT NULL,`add_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,`author` varchar(64) DEFAULT NULL COMMENT '作者',`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',`executor_fail_strategy` varchar(50) DEFAULT NULL COMMENT '失败处理策略',`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',`glue_source` text COMMENT 'GLUE源代码',`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_group` int(11) NOT NULL COMMENT '执行器主键ID',`job_id` int(11) NOT NULL COMMENT '任务,主键ID',`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',`trigger_code` varchar(255) NOT NULL DEFAULT '0' COMMENT '调度-结果',`trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志',`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',`handle_code` varchar(255) NOT NULL DEFAULT '0' COMMENT '执行-状态',`handle_msg` varchar(2048) DEFAULT NULL COMMENT '执行-日志',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOGGLUE` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_id` int(11) NOT NULL COMMENT '任务,主键ID',`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',`glue_source` text COMMENT 'GLUE源代码',`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',`add_time` timestamp NULL DEFAULT NULL,`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE XXL_JOB_QRTZ_TRIGGER_REGISTRY (`id` int(11) NOT NULL AUTO_INCREMENT,`registry_group` varchar(255) NOT NULL,`registry_key` varchar(255) NOT NULL,`registry_value` varchar(255) NOT NULL,`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` (`id` int(11) NOT NULL AUTO_INCREMENT,`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',`title` varchar(12) NOT NULL COMMENT '执行器名称',`order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序',`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',`address_list` varchar(512) DEFAULT NULL COMMENT '执行器地址列表,多地址逗号分隔',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、修改配置
任务调度中心系统主要设计两个配置文件的修改:
job-admin.properties【系统配置】

### xxl-job email 预警发消息用的邮箱
xxl.job.mail.host=smtp.163.com
xxl.job.mail.port=25
xxl.job.mail.ssl=false
xxl.job.mail.username=xxx
xxl.job.mail.password=xxx
xxl.job.mail.sendFrom=xxx@163.com
xxl.job.mail.sendNick=《xxxx任务调度平台预警》### xxl-job login 管理员账号
xxl.job.login.username=xxx
xxl.job.login.password=xxx### 国际化处理,默认中文, i18n (default empty as chinese, "en" as english)
xxl.job.i18n=
# 鉴权访问token,用于业务系统和调度中心
xxl.job.accessToken=xxxx
# mysqldb数据库配置
xxl.job.db.driverClass=com.mysql.jdbc.Driver
xxl.job.db.url=xxxx
xxl.job.db.user=xxxx
xxl.job.db.password=xxxx

quartz.properties【quartz配置】

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.instanceId: AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: falseorg.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 15
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: trueorg.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.maxMisfiresToHandleAtATime: 1#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore# for cluster
org.quartz.jobStore.tablePrefix: XXL_JOB_QRTZ_
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 5000

二、执行器实现

封装成依赖包
执行器需要依赖下面的这个包,为了方便业务系统依赖,建议抽出来deploy到maven仓库。

        <!-- job-core --><dependency><groupId>xxx.xxx.common</groupId><artifactId>job-core</artifactId><version>${job-core.version}</version></dependency>

代码实现
业务系统实现IJobHandler, 下面代码是java系统最常用的Bean模式,还支持其他多种模式

/*** 任务Handler示例(Bean模式)* * 开发步骤:* 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”;* 2、注册到Spring容器:添加“@Component”注解,被Spring容器扫描为Bean实例;* 3、注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值对应的是调度中心新建任务的JobHandler属性的值。* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;* * @author xuxueli 2015-12-19 19:43:36*/
@JobHandler(value="demoJobHandler")
@Component
public class DemoJobHandler extends IJobHandler {@Overridepublic ReturnT<String> execute(String param) throws Exception {XxlJobLogger.log("XXL-JOB, Hello World.");for (int i = 0; i < 5; i++) {XxlJobLogger.log("beat at:" + i);TimeUnit.SECONDS.sleep(2);}return SUCCESS;}}

配置文件

### 调度中心地址,多个地址以逗号隔开
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin### 执行器名称和端口号,ip不配置默认取当前机器ip
xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.ip=
xxl.job.executor.port=9999### 鉴权token,和调度中心保持一致
xxl.job.accessToken=### 日志路径
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 日志存放天数
xxl.job.executor.logretentiondays=-1

三、效果

调度中心有完整的日志监控:

业务系统的执行器可以以心跳注册的形式注册到调度中心,保持了自动发现的能力,也可以支持手动注册

任务调度支持多种模式,配置完在相应的调度时间时,就会触发业务系统的任务调度,也可以手动执行、终止、查看日志。但是小编发现它不支持REST调用,很不方便,于是二次开发了支持REST接口的调用方式,业务系统不需要依赖jar包了,不过REST调用业务系统最好做成异步调用,不然离线任务时间太长可能会挂起。

设计原理参见下篇文章

xxl-job的设计原理主要涉及到quarz、jetty hession序列化通信、任务守护线程、队列消耗线程、rest代理模式,比较隐晦的就是rest代理模式,这一块也是xxl-job独创之处,涉及到了java反射、代理对应、寻址等。
小编梳理下思路,小章分享

参考文献:xxl-job官网

一、任务调度中心构建示例相关推荐

  1. XXL-JOB 任务调度中心 后台任意命令执行漏洞

    XXL-JOB 任务调度中心 0x01 漏洞描述 0x02 漏洞指纹 0x03 漏洞复现 0x04 漏洞示例 0x01 漏洞描述 在日常开发中,经常会用定时任务执行某些不紧急又非常重要的事情,例如批量 ...

  2. SparCC的微生物网络构建示例

    SparCC的微生物网络构建示例 续前文"微生物共发生网络",本篇继续简介SparCC的网络构建方法. 基于高通量测序的技术,例如16S rRNA分析,为阐明天然微生物群落的复杂结 ...

  3. SPIEC-EASI的微生物网络构建示例

    SPIEC-EASI的微生物网络构建示例 续前文"微生物网络",本篇继续简介SPIEC-EASI的网络构建方法. 16S rRNA测序技术为揭示了微生态系统中的系统发育和微生物种群 ...

  4. R线性回归模型构建示例

    R线性回归模型构建示例 简单线性回归(simple linear-regression)是预测连续变量的最简单,最流行的技术.它的前提假设是:结果与预测变量之间存在线性关系. 线性回归的数学公式可以写 ...

  5. springcloud(七):配置中心svn示例和refresh

    上一篇springcloud(六):配置中心git示例留了一个小问题,当重新修改配置文件提交后,客户端获取的仍然是修改前的信息,这个问题我们先放下,待会再讲.国内很多公司都使用的svn来做代码的版本控 ...

  6. SpringBoot2 集成 xxl-job任务调度中心_参数传递

    文章目录 一.xxl-job任务调度中心 1. 调度中心创建任务 2. 调度中心创建执行器 二.执行器任务编码 2.1. 单参数 2.2. 多参数 三.调度中心参数传递测试 3.1. 单个参数传递 3 ...

  7. SpringBoot2 集成 xxl-job任务调度中心

    接上一篇: 搭建xxl-job任务调度中心 https://gblfy.blog.csdn.net/article/details/113809843 文章目录 一.SpringBoot 配置 1. ...

  8. java 中心度_任务调度中心 (优化版)【原】

    任务调度中心 主要依赖quartz.jar相关类 判断cron表达式 , 在下次即将执行的时间在指定时间内时, 从线程池中取线程进行调度 (优化版) 为什么要有调度中心 因为在集群环境,多server ...

  9. XXL-JOB原理--任务调度中心执行器注册(三)

    在上一篇博客XXL-JOB学习--执行器注册(一)中我们介绍了xxl-job执行器注册到任务调度中心的流程及相关注册信息,接下来我们看看任务调度中心接受任务注册后做了哪些事情. 一.注册地址 地址:h ...

最新文章

  1. LeetCode刷题记录10——434. Number of Segments in a String(easy)
  2. 整理对应_JSP第二版课后习题答案【侵权联系我删除】
  3. 哈希表(HashMap)分析及实现(JAVA)
  4. sqlite的控制台中文显示问题
  5. Deepfacelab的填坑之旅
  6. 公共无线网络多陷阱 ***称15分钟盗银行账号密码
  7. opencv+python 霍夫圆检测原理
  8. s3c2440 IIC AT24C08
  9. Avalondock 第四步 边缘停靠
  10. 2021牛客暑期多校训练营#10:F-Train Wreck
  11. 工作日志Android,android Locat工作日志的使用
  12. python进程已结束,退出代码 -1073740791 (0xC0000409)解决办法
  13. Adb连不上夜神模拟器的原因adb devices显示设备信息为空
  14. php国际象棋棋盘,php趣味编程 - php输出国际象棋棋盘 - 小徐
  15. 系统架构中常见问题及解决方案
  16. 专家解读:顺丰和菜鸟开战核心是大数据
  17. 2021 回头看看这一年
  18. 音乐相册源码php,基于PHP的DIY音乐相册网站的设计与实现(MySQL)(含录像)
  19. 怎样建设一个公司网站的教程
  20. 前58同城高级副总裁宋波及总监郭冬涉嫌受贿被警方刑拘

热门文章

  1. Java 2实用教程(第五版)第一课
  2. 佰马加入智慧灯杆产业联盟
  3. 一个11层的CNN(基于无人售货机的货物识别
  4. Windows Server 2003上搭建FTP服务器(IIS同理)
  5. 2023年PMP考试---备考教材清单!
  6. 关于百度快照问题的若干说明
  7. python贪心算法几个经典例子_关于贪心算法的一些探讨、经典问题的解决和三种典型的贪心算法算法(哈弗曼,Kruskal,Prim)的Python实现。...
  8. 开源夏令营《基于HackRF开发GPS信号仿真模拟器》开题报告
  9. sql中时间的比较方法
  10. 硬盘分区出错提示磁盘结构损坏且无法读取怎么修复??