真正健壮的系统靠分层捕获+有策略重试应对异常:网络/io层捕获瞬时故障并立即重试,执行引擎层用钩子捕获隐式异常,ui层区分可重试与不可重试错误,线程级设异常处理器;重试须白名单限定错误类型、指数退避延时、最多3次;任务状态需数据库持久化以支持原子续跑;重试失败后应智能降级或fallback。

自动化调度任务一旦进入生产环境,异常不是“会不会发生”,而是“何时发生”。真正健壮的系统不靠运气避开错误,而靠分层捕获 + 有策略重试来消化它。关键不在多试几次,而在试得对、等得巧、停得准。
分层捕获:从底层到业务,逐级兜底
异常若只靠顶层 try-catch,90% 会漏掉——尤其是线程池任务、异步调用或 UI 自动化中静默失败的情况。
- 网络/IO 层:拦截超时(ETIMEDOUT)、连接重置(ECONNRESET)、5xx 响应码,这些属于瞬时故障,适合立即响应式重试;
-
执行引擎层:如 Celery Worker、OpenClaw 或影刀 RPA 的任务执行器,需启用
afterExecute或等效钩子,捕获未显式抛出的异常; - UI 自动化层:DrissionPage 或 Selenium 应分离“元素未加载”(可重试)和“业务校验失败”(不可重试),前者用显式等待+重试,后者应标记失败并跳过;
-
线程/进程级:为每个工作线程设置
UncaughtExceptionHandler,确保崩溃时不丢堆栈,还能触发告警或日志归档。
重试策略配置:不是设个次数就完事
盲目重试等于放大问题。有效配置必须绑定三要素:什么错才重试、重几次、每次隔多久。
- 可重试错误需白名单管理:仅对网络超时、服务暂时不可用(502/503/504)、CUDA OOM 等临时性错误开启重试;401(认证失效)、400(参数错误)、空指针等永久性错误应直接失败并记录;
- 间隔必须指数退避:第 1 次等 1s,第 2 次等 2s,第 3 次等 4s……避免并发重试压垮下游;部分场景(如 GPU 显存回收)还需叠加固定冷却期(如 5s 冷却后再重试);
- 最大次数建议设为 3:实测表明,超过 3 次仍失败的任务,大概率存在配置、依赖或数据问题,继续重试无意义,应转入人工核查队列。
状态驱动的任务调度:让重试可追溯、可干预
在多实例并发场景(如 10 浏览器同步上货),不能靠“重跑整个脚本”来恢复,而要基于数据库状态做原子化任务续跑。
- 用 SQLite 或轻量数据库建任务表,字段含
id、status(0=待执行,1=运行中,2=成功,3=失败)、retry_count、last_error; - 每个浏览器实例通过
UPDATE ... WHERE status = 0 LIMIT 1 RETURNING *安全“抢单”,失败后仅更新该条记录的status=3和retry_count+1; - 定时扫描
status=3 AND retry_count 的任务,自动触发重试,并写入新日志行,全程留痕。
智能降级与 fallback:重试失败后的合理出口
重试不是万能解药。当达到上限后,系统要有预案,避免雪崩或阻塞。
- 对模型调用类任务,配置
fallbackResponse,如超时返回“暂无法生成,请稍后重试”,防止空响应导致下游解析崩溃; - 对电商上架类任务,失败后可自动转入“人工复核队列”,附带截图、请求参数、错误日志,供运营快速判断是页面改版还是库存不足;
- Dify 或 AutoGPT 类工作流中,可在节点配置
"strategy": "fallback",指定跳转备用节点(如调用本地缓存、切换小模型、返回模板话术)。











