调度任务组件
调度任务模块waf-job,是用于定义系统中的分布式任务接口,提供任务管理服务的模块,调度任务支持自定义扩展,该模块为独立的springboot应用,扩展时也需要新启一个应用来实现。
1、调度任务扩展依赖
<!-- 指定waf-parent为parent,版本号为实际发布的版本-->
<parent>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- 扩展调度任务依赖,版本号不需要指定,继承parent中的版本-->
<dependency>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-job</artifactId>
</dependency>
2、application yml配置
yml文件的配置参照waf-job中的配置进行调整,这里不再进行详细说明,主要是对数据源,redis的配置。
# 调用模块配置(如waf-framwork---> waf-job,则在waf-framwork的yml文件需要配置waf-job的restful地址)
waf:
api:
# 调度任务rest服务地址(本地如不需要发送可将值设置为空)
message-rest-url: http://localhost:8011/waf-job
#执行器ID(根据xxx-job-admin中的配置生成的ID修改)
jobGroupId: 2
3、调度任务服务列表
waf-job提供的任务调度API是基于xxx-job-admin的JobInfoController进行的二次封装,封装的接口为是简化调度任务的使用方式。
xxl-job 架构图

分布式调度任务流程图

3.1、基于waf-proxy调用
waf-proxy对waf-job提供的服务进行的再次封装,只需要配置API服务的地址就能进行直接调用,再次做了简化
<!-- 指定waf-parent为parent,版本号为实际发布的版本-->
<parent>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-parent</artifactId>
<version>1.0.1.RELEASE</version>
</parent>
<!-- 调度任务依赖,版本号不需要指定,继承parent中的版本-->
<dependency>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-job</artifactId>
</dependency>
# 调用模块配置(如waf-framwork---> waf-proxy,则在waf-framwork的yml文件需要配置waf-job的restful地址)
waf:
api:
#任务调度API服务
job-rest-url: http://localhost:8011/waf-job
#执行器ID(根据xxx-job-admin中的配置生成的ID修改)
jobGroupId: 2
通过JobInfoClientService实例来调用提供的服务(代码片断如下:)
@Autowired
private JobInfoProxyService jobInfoProxyService;
@Test
public void saveJobInfo() throws Exception {
JobInfo jobInfo = new JobInfo();
jobInfo.setJobGroup(Integer.parseInt(SpringContextUtils.getPropertis("waf.server.jobGroupId")));
jobInfo.setJobDesc("测试调度任务-新增");
jobInfo.setJobCron("0 0/2 * * * ?");
jobInfo.setExecutorRouteStrategy("FIRST");
// @XxlJob("metwafHandler") 执行的bean名称
jobInfo.setExecutorHandler("wafJobHandler");
jobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
jobInfo.setGlueType("BEAN");
jobInfo.setAuthor("admin");
jobInfo.setExecutorParam("{\"userId\":\"test\"}");
// 调度状态:0-停止,1-运行
jobInfo.setTriggerStatus(1);
// 任务超时时间 (秒)
jobInfo.setExecutorTimeout(100);
jobInfo.setAlarmEmail("lawmancs@qq.com");
// 子任务(没有可不设置)
jobInfo.setChildJobId("6");
// 失败重试次数
jobInfo.setExecutorFailRetryCount(2);
Map retMap = jobInfoProxyService.saveJobInfo(jobInfo);
LOGGER.info("retMap:{}",retMap);
}
注意
在waf-parent:2.0之后版本已经移除了waf-proxy,相关的功能整合到waf-common模块中
3.2、基于Restful服务调用
3.2.1、获取调度任务列表
- 请求方式:GET
- 接口地址:/v1/jobInfo/pageList
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| start | 开始页 | Integer | 是 | 第一页从0开始 |
| length | 每页记录数 | Integer | 是 | |
| jobGroup | 执行器ID | Integer | 是 | 创建时获取 |
| triggerStatus | 状态 | Integer | 是 | -1所有;0停止;1启动 |
| jobDesc | 任务名称 | String | ||
| executorHandler | 执行bean名称 | String | 执行业务逻辑的bean | |
| author | 负责人 | String |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data":{
"recordsFiltered": 8,
"data":[
{
"id": 11,
"jobGroup": 2,
"jobCron": "0 0/2 * * * ?",
"jobDesc": "测试调度任务-新增",
"addTime": 1580697139000,
"updateTime": 1580699478000,
"author": "admin",
"alarmEmail": "lawmancs@qq.com",
"executorRouteStrategy": "FIRST",
"executorHandler": "wafJobHandler",
"executorParam": "{\"userId\":\"test\"}",
"executorBlockStrategy": "SERIAL_EXECUTION",
"executorTimeout": 100,
"executorFailRetryCount": 2,
"glueType": "BEAN",
"glueSource": null,
"glueRemark": null,
"glueUpdatetime": 1580697139000,
"childJobId": "6",
"triggerStatus": 0,
"triggerLastTime": 0,
"triggerNextTime": 0
},
{"id": 10, "jobGroup": 2, "jobCron": "0 0/2 * * * ?", "jobDesc": "测试调度任务-新增"},
{"id": 9, "jobGroup": 2, "jobCron": "0 0/2 * * * ?", "jobDesc": "测试任务新增ccc"}
],
"recordsTotal": 8
}
}
data中的主要属性说明
| 参数 | 参数名称 | 数据类型 | 描述 |
|---|---|---|---|
| id | 任务ID | Integer | |
| jobGroup | 执行器ID | Integer | 执行器配置的ID |
| jobCron | cron表达式 | String | |
| jobDesc | 任务标题 | String | |
| author | 责任人 | String | |
| alarmEmail | 报警邮件 | String | |
| executorRouteStrategy | 路由策略 | String | 包括:第一个、最后一个、轮询等 |
| executorHandler | JobHandler | String | |
| executorParam | 任务参数 | String | |
| executorBlockStrategy | 阻塞处理策略 | String | 单机串行(默认)、丢弃后续调度等 |
| executorFailRetryCount | 失败重试次数 | String | |
| glueType | 运行模式 | String | |
| childJobId | 子任务ID | Integer | |
| triggerStatus | 任务状态 | Integer | 0-停止;1-启动 |
| recordsTotal | 总记录数 | Integer | 查询总记录数 |
3.2.2、获取任务详情
- 请求方式:GET
- 接口地址:/v1/jobInfo/{jobId}
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobId | 任务ID | String | 是 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data":{
"id": 4,
"jobGroup": 2,
"jobCron": "0 0/2 * * * ?",
"jobDesc": "测试任务新增2",
"addTime": "2020-02-01 10:38:02",
"updateTime": "2020-02-01 17:32:02",
"author": "admin",
"alarmEmail": null,
"executorRouteStrategy": "FIRST",
"executorHandler": "wafJobHandler",
"executorParam": null,
"executorBlockStrategy": "SERIAL_EXECUTION",
"executorTimeout": 0,
"executorFailRetryCount": 0,
"glueType": "BEAN",
"glueSource": null,
"glueRemark": null,
"glueUpdatetime": "2020-02-01 10:38:02",
"childJobId": null,
"triggerStatus": 0,
"triggerLastTime": 0,
"triggerNextTime": 0
}
}
data中的主要属性说明
| 参数 | 参数名称 | 数据类型 | 描述 |
|---|---|---|---|
| id | 任务ID | Integer | |
| jobGroup | 执行器ID | Integer | 执行器配置的ID |
| jobCron | cron表达式 | String | |
| jobDesc | 任务标题 | String | |
| author | 责任人 | String | |
| alarmEmail | 报警邮件 | String | |
| executorRouteStrategy | 路由策略 | String | 包括:第一个、最后一个、轮询等 |
| executorHandler | JobHandler | String | |
| executorParam | 任务参数 | String | |
| executorBlockStrategy | 阻塞处理策略 | String | 单机串行(默认)、丢弃后续调度等 |
| executorFailRetryCount | 失败重试次数 | ||
| glueType | 运行模式 | String | |
| childJobId | 子任务ID | Integer | |
| triggerStatus | 任务状态 | Integer | 0-停止;1-启动 |
| recordsTotal | 总记录数 | Integer | 查询总记录数 |
3.2.3、调度任务-新增
- 请求方式:POST
- 接口地址:/v1/jobInfo
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| com.wiseda.waf.common.model.job.JobInfo | 任务对象 | String | 是 | 对象属性与2.2中一致 |
- 请求格式:JSON
{
"jobGroup": 2,
"jobCron": "0 0/2 * * * ?",
"jobDesc": "测试任务新增",
"author": "admin",
"executorRouteStrategy": "FIRST",
"executorHandler": "wafJobHandler",
"executorBlockStrategy": "SERIAL_EXECUTION",
"glueType": "BEAN"
}
请求参数说明
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobGroup | 执行器ID | Integer | 是 | 执行器配置的ID |
| jobCron | cron表达式 | String | 是 | |
| jobDesc | 任务标题 | String | 是 | |
| author | 责任人 | String | 是 | |
| alarmEmail | 报警邮件 | String | 否 | |
| executorRouteStrategy | 路由策略 | String | 是 | 包括:第一个、最后一个、轮询等 |
| executorHandler | JobHandler | String | 是 | |
| executorParam | 任务参数 | String | 否 | |
| executorBlockStrategy | 阻塞处理策略 | String | 是 | 单机串行(默认)、丢弃后续调度等 |
| executorFailRetryCount | 失败重试次数 | 否 | ||
| glueType | 运行模式 | String | 是 | |
| childJobId | 子任务ID | Integer | 否 | |
| triggerStatus | 任务状态 | Integer | 否 | 0-停止;1-启动 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data":{
"jobId": "15"
}
}
data参数说明
| 参数 | 参数名称 | 数据类型 | 描述 |
|---|---|---|---|
| jobId | 任务ID | Integer | 新增返回的任务ID,如需后续修改,启停需保存该ID |
3.2.4、调度任务-修改
- 请求方式:PUT
- 接口地址:/v1/jobInfo
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| com.wiseda.waf.common.model.job.JobInfo | 任务对象 | String | 是 | 对象属性与2.2中一致 |
- 请求格式:JSON
{
"id": 15,
"jobGroup": 2,
"jobCron": "0 0/2 * * * ?",
"jobDesc": "测试任务新增-修改",
"author": "admin",
"executorRouteStrategy": "FIRST",
"executorHandler": "wafJobHandler",
"executorBlockStrategy": "SERIAL_EXECUTION",
"glueType": "BEAN"
}
请求参数说明
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| id | 任务ID | Integer | 是 | 任务ID |
| jobGroup | 执行器ID | Integer | 是 | 执行器配置的ID |
| jobCron | cron表达式 | String | 是 | |
| jobDesc | 任务标题 | String | 是 | |
| author | 责任人 | String | 是 | |
| alarmEmail | 报警邮件 | String | 否 | |
| executorRouteStrategy | 路由策略 | String | 是 | 包括:第一个、最后一个、轮询等 |
| executorHandler | JobHandler | String | 是 | |
| executorParam | 任务参数 | String | 否 | |
| executorBlockStrategy | 阻塞处理策略 | String | 是 | 单机串行(默认)、丢弃后续调度等 |
| executorFailRetryCount | 失败重试次数 | 否 | ||
| glueType | 运行模式 | String | 是 | |
| childJobId | 子任务ID | Integer | 否 | |
| triggerStatus | 任务状态 | Integer | 否 | 0-停止;1-启动 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data": null
}
3.2.5、调度任务-启动
- 请求方式:PATCH
- 接口地址:/v1/jobInfo/{jobId}/start
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobId | 任务ID | String | 是 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data": null
}
3.2.6、调度任务-暂停
- 请求方式:PATCH
- 接口地址:/v1/jobInfo/{jobId}/pause
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobId | 任务ID | String | 是 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data": null
}
3.2.7、调度任务-删除
- 请求方式:DELETE
- 接口地址:/v1/jobInfo/{jobId}
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobId | 任务ID | String | 是 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data": null
}
3.2.8、调度任务-触发一次调度任务
- 请求方式:PATCH
- 接口地址:/v1/jobInfo/{jobId}/trigger
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobId | 任务ID | String | 是 | |
| executorParam | 执行参数 | String | 否 | 自定义格式,一般采用JSON |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data": null
}
3.2.9、调度任务-下次执行时间
- 请求方式:GET
- 接口地址:/v1/jobInfo/{jobId}/nextTriggerTime
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 |
|---|---|---|---|---|
| jobId | 任务ID | String | 是 |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data":[
"2020-02-03 18:10:00",
"2020-02-03 18:12:00",
"2020-02-03 18:14:00",
"2020-02-03 18:16:00",
"2020-02-03 18:18:00"
]
}
data中为一组5条后续的任务执行时间
参考资料
https://www.xuxueli.com/xxl-job/
4、项目实际应用
在基础框架中提供了waf-job模块,在waf-porxy中定义的job的restful 接口地址,对于项目中的实际需求场景,建议将waf-job fork到自己的项目中,自行完善实际的业务需求,保持着controll中提供出去的api地址一致,就可以让直接使用waf-proxy定义的job服务,也可以自定去定义。
5、xxl-job 安装应用
xxl-job部署可参照上面链接选择一种来部署。
