XXL-JOB、PowerJob 与平台边界:什么时候该把任务交给调度中心
团队把单机定时器迁到调度平台后,最常见的误判是“中心集群已经高可用,所以任务不会丢也不会重”。实际上中心可能成功下发、执行器已经提交、回调却丢失;也可能执行器刚注册就被摘除、路由缓存尚未收敛;分片广播还会主动把一次 fire 扩成多个 attempt。平台提高的是控制面可见性和重新派发能力,不会自动合并业务副作用。
XXL-JOB 官方文档把调度中心、执行器注册、路由策略、阻塞策略、失败重试和分片广播拆开;PowerJob 则以 Server、Worker、Processor 和分布式计算能力组织任务。产品功能不同,但共同边界是中心决定把哪次尝试发给谁,业务正确性仍由处理器与数据系统证明。
从现场还原真正的运行链
控制面维护任务定义、触发时刻、执行器地址、路由策略和运行记录;数据面在 Worker 中加载 Processor,使用本地线程、连接和凭证操作业务资源。一次下发至少带 jobId、fireId、attemptId、shardIndex、shardTotal、deadline 与配置版本。执行器先做 admission,再写 RUNNING 见证,业务完成后回传终态。回调超时只能说明中心不知道结果,不能证明处理器失败。
最危险的提交与恢复窗口
FAILOVER 路由通常在下发前探测可用节点,不能处理节点接收后、提交前后的全部故障;BUSYOVER 依据执行器报告判断忙碌,报告存在采样与传播延迟;SHARDING_BROADCAST 把每个节点视为一个动态分片,扩缩容会改变 shardTotal,若游标只保存 shardIndex 就会漏扫或重扫。平台选择必须落到状态表:谁创建 fire、谁持有 attempt 租约、谁判定超时、谁能终止、谁保存业务结果。
沿六个状态节点逐段验证
登记任务版本
来到“登记任务版本”时,先记录输入标识、状态版本、owner、剩余 deadline 和允许的下一迁移,再执行外部动作。正向实验断言计划、attempt 与领域结果守恒;反向实验在状态写入前后分别制造崩溃、超时或租约切换,确认迟到写被拒绝,UNKNOWN 能通过 operationId 对账,而不是被无条件重跑掩盖。
注册执行器
来到“注册执行器”时,先记录输入标识、状态版本、owner、剩余 deadline 和允许的下一迁移,再执行外部动作。正向实验断言计划、attempt 与领域结果守恒;反向实验在状态写入前后分别制造崩溃、超时或租约切换,确认迟到写被拒绝,UNKNOWN 能通过 operationId 对账,而不是被无条件重跑掩盖。
选择路由
来到“选择路由”时,先记录输入标识、状态版本、owner、剩余 deadline 和允许的下一迁移,再执行外部动作。正向实验断言计划、attempt 与领域结果守恒;反向实验在状态写入前后分别制造崩溃、超时或租约切换,确认迟到写被拒绝,UNKNOWN 能通过 operationId 对账,而不是被无条件重跑掩盖。
下发 Attempt
来到“下发 Attempt”时,先记录输入标识、状态版本、owner、剩余 deadline 和允许的下一迁移,再执行外部动作。正向实验断言计划、attempt 与领域结果守恒;反向实验在状态写入前后分别制造崩溃、超时或租约切换,确认迟到写被拒绝,UNKNOWN 能通过 operationId 对账,而不是被无条件重跑掩盖。
处理器提交
来到“处理器提交”时,先记录输入标识、状态版本、owner、剩余 deadline 和允许的下一迁移,再执行外部动作。正向实验断言计划、attempt 与领域结果守恒;反向实验在状态写入前后分别制造崩溃、超时或租约切换,确认迟到写被拒绝,UNKNOWN 能通过 operationId 对账,而不是被无条件重跑掩盖。
回调与重调度
来到“回调与重调度”时,先记录输入标识、状态版本、owner、剩余 deadline 和允许的下一迁移,再执行外部动作。正向实验断言计划、attempt 与领域结果守恒;反向实验在状态写入前后分别制造崩溃、超时或租约切换,确认迟到写被拒绝,UNKNOWN 能通过 operationId 对账,而不是被无条件重跑掩盖。
先把四个标识拆开,故障才有名字
到点、开始、提交和确认是四个不同时间
状态迁移要能拒绝迟到写
可观测性必须能重建一次执行
停机和发布要先处理调度所有权
实例进入拒绝流量时先暂停领取新 fire,再等待已领取 attempt 到达安全边界;短任务可排空,长任务保存检查点并释放租约。强杀预算必须覆盖路由摘除、调度扫描周期、当前原子批次和资源关闭。发布期间新旧版本若同时识别同一任务,配置版本、处理器兼容和 operationId 算法必须保持一致,否则滚动升级会制造双计划。
一个会稳定暴露问题的反向实验
中心显示 SUCCESS 可能只代表回调码成功,处理器内部异步提交的子任务仍在失败;中心显示 FAIL 也可能发生在业务提交之后。把脚本和凭证直接放在控制面,会把调度管理员权限扩张成生产数据权限;把所有日志上传中心,又会在大结果和异常风暴时反向压垮调度数据库。可靠设计让中心保存索引与摘要,详细业务证据进入受控日志和领域账本。 复现时固定任务定义、输入快照、时钟源和线程池容量,保存首次失败的控制记录与领域账本;修复后用同一故障点重放,并同时证明正常路径没有新增重复、等待和资源泄漏。
两个 Java 17 模型把不变量钉在输出上
下面的模型不模拟完整框架,而是把最容易被产品日志掩盖的状态转折压缩成确定性见证。它们执行真实计算和断言,输出发生变化就说明执行语义被改写。
javac --release 17 -Xlint:all -Werror examples/backend-development/scheduling-async/xxljob-powerjob/PlatformBoundaryDemo.java examples/backend-development/scheduling-async/xxljob-powerjob/RoutingOwnershipDemo.java
java -cp examples/backend-development/scheduling-async/xxljob-powerjob PlatformBoundaryDemo
java -cp examples/backend-development/scheduling-async/xxljob-powerjob RoutingOwnershipDemojobs=120 workers=8 controlWrites=240 businessWrites=120 resultOwner=DOMAIN_LEDGER separated=true
fireId=report@T2 dispatches=2 accepted=1 staleRejected=1 routing=FAILOVER duplicateControlled=true第一行验证正常时间或覆盖模型,第二行专门验证恢复、重派、租约或取消窗口。工程接入后,用真实数据库唯一约束、执行器故障和平台回调替换内存状态,但保留相同 operationId、状态迁移和输出不变量。
架构取舍不是功能数量比赛
少量应用内任务不需要为统一大屏支付中心、数据库、网络和权限成本。出现跨应用统一停启、动态路由、分片运营、执行历史检索、细粒度权限与大量执行器时,平台才带来净收益。XXL-JOB 更偏轻量中心与执行器模型,PowerJob 提供更强的分布式计算和工作流表达;选择时用任务规模、执行模型、恢复语义、扩展成本和团队运维能力验证,不用功能数量投票。
发布门禁:证明执行收敛,而不是证明按钮可用
发布时必须守住“控制面可以重派 attempt,但不能越权替代领域账本判定业务终态”。验收证据至少包含一轮正常 fire、一轮执行中强杀、一轮回调丢失或租约过期、一轮停机恢复;核对 planned、started、terminal、businessWrites、unknown 与 retry 的守恒关系。配置例外必须有 owner、影响窗口、补偿控制和到期条件,过期自动阻断。
