xxLjob两个任务 pullGuanjiaSalesJob,不同的执行参数,配置了同一个 @XxlJob("pullGuanjiaSalesJob")两个任务同一个调用时间 CRON:0 0 3 * * ?,具体如何调度的,及任务如何执行的
在 XXL-JOB 中,当两个任务配置了相同的 @XxlJob("pullGuanjiaSalesJob")
方法且 CRON 表达式相同(如 0 0 3 * * ?
,即每天凌晨3点触发),其调度和执行流程如下:
1. 调度中心的触发机制
(1) 任务存储与触发检查
XXL-JOB Admin(调度中心) 会定期扫描任务表(默认每秒一次),检查到达触发时间的任务。
如果两个任务的 CRON 表达式均为
0 0 3 * * ?
,调度中心会在 同一时间点(3:00:00) 生成两条任务触发记录。
(2) 任务触发顺序
默认并发触发:
调度中心会 同时 向执行器发送两个任务的触发请求(即使jobHandler
相同),但会携带不同的jobId
和参数(如param=type=daily
和param=type=monthly
)。阻塞策略影响:
如果任务配置了SERIAL_EXECUTION
(串行执行),调度中心会按任务ID顺序依次触发(前一个任务执行完成后,再触发下一个)。
2. 执行器的任务执行
(1) 任务分发到执行器
调度中心通过 RPC 调用执行器(Executor),传递以下信息:
jobHandler
:pullGuanjiaSalesJob
(两个任务相同)。jobParam
:任务参数(如type=daily
和type=monthly
)。jobId
:任务唯一ID(区分不同任务实例)。
执行器会根据
jobId
和jobParam
区分任务,即使jobHandler
相同。
(2) 执行器线程池处理
执行器接收到任务后,会提交到内置的线程池(默认核心线程数为
8
)。默认并发执行:两个任务会由不同线程同时执行。
串行执行:如果配置了
SERIAL_EXECUTION
,则任务会排队依次执行。
(3) 任务方法执行
java
@XxlJob("pullGuanjiaSalesJob") public ReturnT<String> pullGuanjiaSalesJob(String param) {if ("type=daily".equals(param)) {// 执行每日统计逻辑} else if ("type=monthly".equals(param)) {// 执行月度统计逻辑}return ReturnT.SUCCESS; }
通过
param
区分不同任务的业务逻辑。
3. 关键影响因素
(1) 阻塞策略(Block Strategy)
策略 | 对相同 jobHandler 任务的影响 |
---|---|
SERIAL_EXECUTION | 串行执行(按任务ID顺序,前一个完成后再触发下一个)。 |
DISCARD_LATER | 丢弃后续触发,只执行第一个到达的任务。 |
COVER_EARLY | 覆盖早期触发,只执行最新的一个任务。 |
(2) 执行器线程池配置
线程池大小通过
xxl.job.executor.corePoolSize
配置(默认8)。若线程池已满,新任务会等待或丢弃(取决于配置)。
4. 执行流程示例
场景描述
任务1:
jobId=1
,param=type=daily
,阻塞策略为SERIAL_EXECUTION
。任务2:
jobId=2
,param=type=monthly
,阻塞策略为SERIAL_EXECUTION
。
执行步骤
调度中心 在 3:00:00 同时检测到两个任务需触发。
由于
jobHandler
相同且阻塞策略为SERIAL_EXECUTION
,调度中心按jobId
顺序触发:先触发
jobId=1
(type=daily
),等待其执行完成。完成后触发
jobId=2
(type=monthly
)。
执行器依次运行两个任务,通过
param
区分逻辑。
5. 如何避免问题?
(1) 确保参数可区分逻辑
在
@XxlJob
方法内明确解析param
,避免逻辑冲突。示例:
java
@XxlJob("pullGuanjiaSalesJob") public ReturnT<String> execute(String param) {if (param == null) {return ReturnT.FAIL;}switch (param) {case "type=daily":// 每日逻辑break;case "type=monthly":// 月度逻辑break;}return ReturnT.SUCCESS; }
(2) 调整阻塞策略
若任务需严格串行,配置
SERIAL_EXECUTION
。若允许并发,但需避免资源竞争,可在代码中加锁:
java
private final Object lock = new Object();@XxlJob("pullGuanjiaSalesJob") public ReturnT<String> execute(String param) {synchronized (lock) {// 业务逻辑}return ReturnT.SUCCESS; }
(3) 监控与日志
在任务日志中记录
jobId
和param
,便于排查问题:java
@XxlJob("pullGuanjiaSalesJob") public ReturnT<String> execute(String param) {log.info("Job started: jobId={}, param={}", XxlJobHelper.getJobId(), param);// 业务逻辑return ReturnT.SUCCESS; }
6. 总结
调度机制:相同 CRON 的任务会同时触发,但执行顺序受阻塞策略控制。
执行逻辑:通过
jobParam
区分任务,由执行器线程池并发或串行执行。最佳实践:
使用参数明确区分任务逻辑。
关键任务配置
SERIAL_EXECUTION
避免并发问题。监控日志确保任务按预期执行。