关于定时任务,想必大家都不会陌生,简单的定时任务有jdk提供的定时任务、spring提供的定时任务,稍微复杂一些有quartz定时任务,分布式任务有xxl-job
、elastic-job
。由于项目中使用的定时任务是xxl-job
,因此本系列将从源码的角度来分析xxl-job
定时任务的设计与实现。
关于xxl-job
的操作,xxl-job
社区贴心地提供了操作文档:https://www.xuxueli.com/xxl-job/,文档不长,一遍看下来xxl-job
的操作基本就会了,这块就不过多叙述了。
1. 获取xxl-job
源码
既然是源码分析,当然要先获取源码了,xxl-job
的github地址为https://github.com/xuxueli/xxl-job
。一般来说,直接frok
这个仓库就可以了,不过由于国内网络的原因,github 的访问并不稳定,比如checkout
到一半网络断开、push
超时等。为了规避这些问题,建议使用国内的git仓库——gitee,操作方式如下:
1.1 创建新的gitee仓库
登录个人的gitee
,点击“+”号,选择“从github/gitlab导入仓库”:
1.2 导入xxl-job
仓库
复制xxl-job
的github
地址,点击导入:
等待一会,就得到了自己的xxl-job
的gitee
地址了,本人得到的地址为https://gitee.com/funcy/xxl-job
,并且gitee上也提供一个按钮,可以很方便地同步github上的代码:
如果有一天,你发现作者在github
提交了大把代码,想及时同步到自己的gitee
仓库,只要点击这个按钮就可以了,不过这样可能会覆盖自己的代码,可以通过新建分支来规避。
1.3 创建新分支
接下来,就可以基于该仓库自由操作了,继续,选择一个自己准备放项目的目录,然后clone
:
git clone https://gitee.com/funcy/xxl-job
接下来,需要基于 tag 创建分支(新分支命为2.3.0.LEARN
)
git tag
git checkout 2.3.0
git checkout -b 2.3.0.LEARN 2.3.0
git push -u origin 2.3.0.LEARN
后续我们所有的分析操作就都在2.3.0.LEARN
上进行了。
关于创建分支一些小疑问:
为什么要创建新分支?
主要是防止点击同步时,代码被覆盖。如果直接在
master
分支,或其他在github
中已有的分支上进行修改,点击同步后,所作的修改都会被github
上的分支覆盖,而在gitee
上新建的分支则不会被覆盖为什么要基于
tag
创建新分支而不是master
?一般来说,
master
上的代码是最新稳定版本的代码,因此会不断变化,而tag
上的代码,表示打tag那一刻的代码,之后不再变化,这样就保证了同一个tag上的代码,无论什么时候都是一样的。事实上,了解了git的
tag
概念后,会发现tag
上的代码checkout
下来后,无法再怎么修改都不能提交,即不会被修改;相反地,master
或其他分支,修改后可以再提交。由于tag
上的代码是不变的,为了能提交代码,必须要基于tag
上的代码创建新分支
- 为什么选择的tag版本是
2.3.0
而不是其他?因为当前最新版的
xxl-job
是2.3.0
,当然要分析最新版的代码了。
2. xxl-job
项目结构
拿到代码后,我们来看下xxl-job
的项目结构:
xxl-job-admin
:管理后台,提供任务管理界面,同时也是任务的调度器、触发器,本系列文章中简称为admin
。xxl-job-core
:xxl-job
的核心组件,同时也是xxl-job
对外提供的jar
包,提供了任务执行相关逻辑。xxl-job-executor-samples
:执行器示例,在本系列文章中,执行器是指集成了xxl-job
任务执行功能的项目,也称为executor
xxl-job-executor-sample-frameless
:不集成任何框架的示例xxl-job-executor-sample-springboot
:集成了 springboot 框架的示例
关于该项目的更多细节,可以参考官方文档https://www.xuxueli.com/xxl-job/,这里截取官方的架构图:
建议先了解上图中xxl-job
的组件,后面的源码分析会一步步揭开这些组件工作的原理。
3. 启动xxl-job
大致了解xxl-job
的结构后,接下来我们在idea
中启动xxl-job
,这样也是方便我们后面调试。
3.1 执行sql脚本
xxl-job
的sql脚本位于xxl-job/doc/db
目录下,文件名为tables_xxl_job.sql
准备一个mysql
数据库,直接执行该脚本即可。需要注意的是,如果数据库中已存在名为xxl_job
数据库,执行该脚本会覆盖原来的库,需要注意下。
执行成功后,数据库中会出现如下表:
各表的功能如下:
xxl_job_user
: 用户信息,用来验证登录到管理后台的用户是否合法xxl_job_info
: 任务信息表,用来配置需要执行的任务xxl_job_log
: 日志表,用来记录任务的执行日志xxl_job_log_report
: 任务执行报表,用来汇总、统计任务的执行情况xxl_job_logglue
: gule模式任务表,主要记录glue模式任务的执行代码xxl_job_registry
: 执行器的注册记录表,每一个执行器都保存一条注册记录xxl_job_group
: 执行器的注册汇总表,多个执行器汇总成一条记录xxl_job_lock
: 锁表,xxl-job
用来实现分布式锁的表
3.2 启动admin
admin
的启动类为com.xxl.job.admin.XxlJobAdminApplication
:
不过在启动前,需要调整数据库的连接配置,配置文件为application.properties
:
将数据库的连接信息调整正确后,运行XxlJobAdminApplication
就可以启动了,控制台日志如下:
在浏览中访问http://localhost:8080/xxl-job-admin/
,界面如下:
管理后台的菜单不多,操作比较简单,大家可根据官方文档可行摸索。
3.3 启动executor
xxl-job
提供了两个执行器示例,考虑到当前开发基本上基于springboot
,本系列将重点分析集成了springboot
的执行器示例,即xxl-job-executor-sample-springboot
。
在启动xxl-job-executor-sample-springboot
前,要先配置xxl-job-admin
项目的地址,配置文件为application.properties
:
配置key为xxl.job.admin.addresses
,如果有多个xxl-job-admin
地址,可以使用,
分开。
配置好admin
地址后,启动即可,启动类为com.xxl.job.executor.XxlJobExecutorApplication
,控制台日志如下:
注意到这里有两个端口:
- 8081:这个是 项目的web 服务提供的对外访问端口,用来访问 springmvc 接口的
- 9999:这个是
xxl-job
用来与admin
通讯的接口,用来处理xxl-job-admin
发送过来的请求,这个后面我们再分析
3.4 第一个定时任务
xxl-job
本身也提供了示例任务:
任务在任务管理
菜单下,后续我们配置自己的任务时,也是在这里配置。
从界面上可以看到,目前已经有了一个测试任务,不过状态为stop
,我们可以在“操作”栏启动该任务,也可以使用“执行一次”功能来手动执行该任务,这里我们使用“执行一次”来运行该任务:
直接点击“保存”即可,之后可以在“调度日志”菜单查看任务执行情况:
可以看到任务执行成功了。
该任务的代码位于xxl-job-executor-sample-springboot
模块的com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler
方法,代码如下:
关于其中的调度原理,我们将在后面的文章中再分析。
4. 总结
本文是xxl-job
源码分析的开篇,介绍了源码分析前的准备工作,主要包含了三个方面:
- 源码的获取,介绍了如何从github上获取
xxl-job
源码,以及分支的创建流程 - 项目的启动,介绍了sql脚本的处理、
admin
注册地址的配置,以及项目的启动(admin
与executor
) - 执行定时任务,介绍了如何执行
xxl-job
提供的任务示例,由于本系列文章以源码分析为主,因此任务的配置、cron表达式的意义等均无叙述,若要了解这些操作可以参考官方文档(https://www.xuxueli.com/xxl-job/)或者自行搜索资源。
作为源码分析的准备工作就到这里了,下-篇我们将正式进入xxl-job
项目的源码分析中。
限于作者个人水平,文中难免有错误之处,欢迎指正!原创不易,商业转载请联系作者获得授权,非商业转载请注明出处。