SH

Soloharness

架构专题

返回 Blog

架构专题

82个定时任务怎么不出错?销售Agent的Cron调度与容错实践

Soloharness 团队 · 2026 年 5 月 28 日

一个10人销售团队的AI Agent系统,背后跑着82个定时任务。

不是因为设计过度——而是当你给每个销售配一个独立bot、每个bot需要晨间推送、gate-check、CRM审计、看板刷新,再加上管理者报告和运维监控时,任务数量自然就到了这个量级。问题是:82个任务怎么保证不出错、不冲突、不把系统搞崩?

82个任务都是什么

按功能分五类:

  • 个人推送 50 个:10个销售bot × 5个时段(07:40晨间待办、09:00首访提醒、12:00午间汇总、16:00下午跟进、20:00晚间复盘)。每个时段的推送内容不同——晨间是待办排序,午间是上午拜访结果汇总,晚间是当日完成情况和明日预排。
  • Gate-check 10 个:每bot一个,夜间02:30-02:57错峰执行。用LLM对照六步法21道通关凭证,判断每个客户当前Gate和缺失项。
  • 明道云审计 10 个:每bot一个,凌晨00:40-01:10错峰执行。检查当天的CRM写入是否完整、是否有遗漏的拜访记录需要补录。
  • 管理者报告 8 个:日报(每日07:00)、周报(周一07:10)、Pipeline健康度(周三/周五07:00)、丢单预警(每日06:30)、Top10机会跟踪(每日07:20)、新人进度(每日07:30)、团队MEDDIC评分汇总(每日07:15)、扩展机会扫描(周一07:05)。
  • 运维监控 4 个:日志轮转(每日03:00)、健康检查(每小时整点)、归档审计(每日02:00)、异常告警(每30分钟)。

时间错峰:避免把自己打崩

82个任务不能同时跑。最直接的原因是LLM API限流——gate-check每个任务需要调用一次LLM(读取客户MD、对照通关凭证、生成评分),10个bot同时调用很容易触发429。

解决方案是三级错峰

同组内错峰:10个gate-check任务间隔3分钟(02:30, 02:33, 02:36...),保证同一时刻只有一个LLM调用在进行。

不同类型任务错峰:gate-check在02:30-02:57,明道云审计在00:40-01:10,个人推送在07:40/09:00/12:00/16:00/20:00。时间窗口不重叠。

高低优先级错峰:管理者报告(需要读全量数据)安排在07:00-07:30,个人推送(只读单人数据)在07:40。管理者报告先跑完,个人推送再跑——避免争夺tasks.db的读写锁。

文件锁:防止重复执行

Linux的cron是时间驱动的——如果上一轮任务还没跑完,下一轮又会触发。这在任务执行时间不稳定时会导致同一个任务同时跑两份。

解法是文件锁:每个任务执行前检查对应的.lock文件是否存在。如果存在,说明上一轮还在跑,跳过这一轮。如果不存在,创建.lock文件,执行任务,执行完删除。

文件锁比进程锁更简单可靠——不需要管理PID文件、不需要处理僵尸进程。在一台单机部署的系统上,文件锁足够用了。

状态文件:知道发生了什么

每个任务执行完都会写入一个状态文件,记录三样东西:执行时间、结果(成功/失败/部分完成)、关键指标(如"推送了3条待办""gate-check了5个客户")。

状态文件的价值在于可追溯。当销售说"我今天没收到推送"时,运维可以查看该bot的推送任务状态文件——是没跑(cron没触发)、跑了但失败了(LLM返回错误)、还是成功了但企微消息没送达。三种情况的处理方式完全不同。

状态文件还驱动运维监控:每天06:00的健康检查任务会读取所有82个任务的状态文件,汇总失败清单,推送给运维bot。运维bot再决定哪些需要人工介入、哪些可以自动重试。

幂等设计:重跑不会出事

容错的最后一环是幂等性——同一个任务跑两次,结果和跑一次一样。

这对gate-check特别重要。如果02:30的gate-check跑到一半挂了(比如LLM超时),06:00发现后补跑——补跑时不能重复写入tasks.db的待办(否则销售会收到两条一样的待办)。

实现方式:gate-check每次写入前先查——如果同一天、同一个客户、同一个Gate的待办已经存在,跳过写入。这个"先查后写"逻辑保证了补跑的安全性。

个人推送的幂等更简单——推送内容是当天快照,推两次销售会收到两条一样的消息。这不会导致数据错误,但会打扰销售。所以推送任务额外检查.pushed标记——如果今天已经推过,跳过。

从82个任务看系统设计原则

82个任务听起来很多,但每个任务的设计都遵循同一个原则:单一职责、可独立失败、可独立重跑。

单一职责意味着每个任务只做一件事——gate-check只做Gate判断,不做推送;推送只做消息发送,不做数据分析。这让每个任务的代码都很短(通常50-100行),出问题时容易定位。

可独立失败意味着一个任务挂了不影响其他任务。gate-check的LLM调用超时不会导致晨间推送失败——因为它们读的是不同的数据源、走的是不同的API。

可独立重跑意味着运维可以在不重启整个系统的情况下补跑单个任务。这在生产环境中极其重要——你不会为了修一个推送任务而重启整个系统。

在一个实际部署中,82个任务的平均每日成功率是99.2%(约0.6个任务/天需要人工关注),最常见的失败原因是LLM API超时(占失败任务的70%),其次是企微消息接口限流(占20%)。这些失败通过06:00的健康检查汇总后,运维bot会在06:30推送修复建议——通常是"重跑这个任务"或"等10分钟再试"。

如果你也在搭建销售 AI 系统,soloharness.com 可能值得看看。