定时任务上线前检查单:从表达式到时区、重试与告警

总结我在多个项目把Cron任务推到线上前的核对清单:表达式可读性、时区一致性、互斥与幂等、失败重试与告警、观测与回溯

优兔GOGO
2025年10月3日
实践手记
运维实践CronQuartz时间戳重试告警

定时任务上线前检查单:从表达式到时区、重试与告警

把定时任务推到生产环境,我现在一定先过一遍“上线前检查单”。这不是形式主义,很多“偶发问题”都能在这张单子上提前暴露。以下条目,基本覆盖我踩过的坑。

1) 表达式与语义:人要能读懂

  • 我会先用可视化工具把表达式“转成中文语义”,确认没人误读。例如每 5 分钟、工作日 9:00、每月最后一天 23:30 等。表达式能写成“看着像对”,但中文描述才是团队对齐的依据。
  • 周一到周五 vs 工作日:很多系统把“工作日”理解成 Mon-Fri,但遇到法定调休就会错位。如果业务有法定节假日要求,表达式本身是不够的,需要结合日历表。

可用工具:

2) 时间与时区:统一口径,避免“跑早/跑晚”

  • 我会把“调度器所在时区”和“业务时间口径”写死在文档(UTC、系统时区、业务所在时区)。跨区部署要特别注意夏令时,避免 2:00 → 3:00 的跳变导致任务跳过或重复。
  • 输入输出时间都统一为 ISO 8601(带时区偏移),日志里附带 Unix 时间戳(秒/毫秒)方便快速换算。

可用工具:

3) 幂等与互斥:允许重放,也防止并发踩踏

  • 幂等:给任务“天然幂等”的能力,例如以业务主键+时间窗口作为幂等键,重复触发也不会二次落账或重复通知。
  • 互斥:对于不能并行的任务,加分布式锁或调度器的“禁止并发”选项,避免上一轮未完成又来一轮。

4) 失败重试与退避:别把系统拖穿

  • 重试次数与间隔写死,避免“无限重试”。遇到外部依赖抖动,用指数退避(如 1s、2s、4s、8s 上限 x 次),并设置总体超时。
  • 将“可重试错误”(网络超时、暂时性 5xx)与“不可重试错误”(参数非法、权限不足)区分开,日志打点不同级别。

5) 观测:日志、指标、追踪三件套

  • 日志:每次触发记录“任务ID、表达式、起止时间、耗时、处理条数、关键入参、关键出参摘要、结果状态、错误码/堆栈定位”。
  • 指标:成功率、平均耗时、P95 耗时、重试次数、错误类型分布。把它们接到可视化告警平台,波动立刻能看见。
  • 追踪:涉及下游服务的,把 traceId 带上,便于跨服务串联排查。

6) 告警:少而准,避免“告警疲劳”

  • 一次性失败不告警(由重试兜底),超过阈值才发。连续失败 N 次、成功率低于阈值、延迟积压超过窗口,各自单独建规则。
  • 告警内容必须包含“复现场景与自愈建议”,别只发一个“失败了”。

7) 回溯与补数:计划之外也能稳住

  • 设计好“补跑”能力:给历史区间重放的入口,能够以“时间窗口+幂等键”的方式补齐数据。
  • 对于消息类任务,加死信队列与人工介入通道,别在故障窗口把数据吞掉。

8) 变更管理:灰度、冻结、回滚

  • 变更窗口:对高风险任务设“变更冻结期”,避免节假日前后推大改。
  • 灰度:先在小分区或影子环境跑一轮,看指标稳定再全量。
  • 回滚:表达式与代码都要能快速回退;文档留有“上一个稳定版本”。

我现在的上线步骤卡片

  1. 在生成器中核对表达式与中文语义一致;
  2. 用时间戳工具对比时区与夏令时表现;
  3. 开启互斥或加分布式锁,落地幂等键;
  4. 配置重试+退避+总体超时;
  5. 打全日志+指标+追踪;
  6. 配准告警阈值与接收人,演练一次;
  7. 准备补跑脚本与回滚方案;
  8. 小流量灰度后再全量发布。

🔗 相关工具