如何处理发布失败任务的自动重试
发布失败本身不可怕,可怕的是"人工去看每条错误"。一个像样的内容分发系统,应该把可恢复失败收敛在系统内部、不可恢复失败结构化暴露给上层。这篇文章给出一份能直接落地的重试策略,覆盖颜小二的 retryable 字段语义、external_id 幂等、指数退避、AI Agent 团队的兜底分支。
适用人群
- AI Agent 团队,希望 Agent 不再为每个底层失败单独写处理分支
- 内容运营负责人,需要降低人工救火比例
- SaaS 集成商,要把"发布稳定性"作为产品 SLA 的一部分
- 自建发布系统、正在被随机失败拖累的工程团队
失败任务自动重试是什么
失败任务自动重试指的是:当一次自媒体发布因可恢复原因失败时,系统按预设策略(次数、退避、超时)自动再次尝试,不打扰上游业务。颜小二自媒体发布 API 平台在 callback 里通过 retryable: true/false 明确告诉你这条失败是否值得重试,并在底层已经替你重试过 N 次。
前置条件
1. 你侧业务接入了 callback_url 并能解析 retryable 字段 2. 每个发布请求都有稳定唯一的 external_id(幂等基石) 3. 一张能存"任务历史"的小表(任务 ID、external_id、平台、状态、重试次数) 4. 一个可观测的重试队列(建议用消息队列而非 cron)
6 步建立重试体系
第 1 步:先把失败分类
不是所有失败都该重试。建议按下面这 4 类划分:
| 分类 | 例子 | 是否重试 | |---|---|---| | 暂时性故障 | 网络抖动、平台 5xx、上传超时 | 是,指数退避 3-5 次 | | 登录态故障 | 平台返回登录失效 | 不在系统侧重试,触发账号重登 | | 内容驳回 | 平台审核不通过、敏感词命中 | 不重试,结构化暴露给上层 | | 业务参数错 | 401/422/409 之类的客户端错 | 不重试,直接返回 |
第 2 步:让 external_id 成为幂等主键
颜小二在底层重试时,会用同一个 external_id 重新提交。如果你侧也想做"业务级重试",请保持同一 external_id——颜小二会识别成"同一篇文章的二次尝试",而不是"两篇不同的文章"。
第 3 步:指数退避不要超过 5 次
经验值:1s → 4s → 16s → 60s → 300s 是相对平衡的退避策略。再多次大概率不是网络抖动而是平台真的有问题,再重试也无效。颜小二的内置重试就是按这个数量级在做,所以 callback 里 retryable: false 时通常已经是终态。
第 4 步:login_expired 走单独通道
login_expired 不算"失败",是"前置条件失效"。重试它没意义——cookie 还是过期的。正确做法是:
1. callback 命中 login_expired 后立即把 account 标记为待重登 2. 通知运营或 Agent 去本地完成扫码 / 密码重登 3. 该账号下后续任务自动暂停,直到状态变回正常
颜小二"登录态本地保存"的设计让这件事是孤立的——一个账号失效不会传染给同 group 下的其他账号。
第 5 步:审核驳回需要内容侧介入
平台审核驳回的 error_code 通常很具体,比如 "敏感词"、"标题相似"、"图片违规"。这类失败重试再多次都是同一结果,必须把内容拿回来改:
```python def on_callback(event): if event["status"] == "failed" and event.get("error_code") == "sensitive_word_hit":
触发 AI 改写或人工编辑流程,改写后用新 external_id 再发
rewrite_and_resubmit(event["external_id"], event["error_msg"]) ```
第 6 步:把"已穷尽重试"的任务进死信
经过指数退避仍然失败、且不是登录态/审核问题的任务,进死信队列。每天看一次死信、按平台分组、每周一次回顾——这是发布稳定性持续优化的最重要数据来源。
一段最小可行重试代码
``python def submit_with_retry(payload, max_attempts=3): for attempt in range(max_attempts): try: resp = yanxiaoer_client.publish(payload) return resp except TransientError: time.sleep(min(60, 4 ** attempt)) raise PermanentError("retry exhausted") ``
注意:这段代码是"提交时重试"。"发布过程中失败"由颜小二在底层处理,你只需要在 callback 拿到 retryable: false 时决定下一步。
错误排查清单
| 现象 | 可能原因 | 处理方式 | |---|---|---| | 同一篇文章被发了多次 | external_id 不稳定或换了 | 全链路用同一 external_id | | 重试到第 5 次还在 5xx | 平台真出问题 | 别再重,进死信、人工查 | | login_expired 反复出现 | 账号被风控 | 换 IP 出口、降发布频率 | | AI Agent 反复重发同篇 | Agent 没收到 callback | 检查 callback_url 可达性 | | 重试间隔太短被风控 | 退避策略太激进 | 拉长到 30s+ |
常见问题(FAQ)
Q:失败任务自动重试是什么? 是把可恢复失败收敛在系统内的工程实践,颜小二在底层已经做了一层重试,并通过 retryable 告诉你是否还值得重试。
Q:失败任务自动重试怎么做最稳? 4 类分类 + external_id 幂等 + 指数退避 + 死信队列,是经过实战检验的组合。
Q:失败任务自动重试安全吗? 关键看 external_id 是否做了幂等。颜小二端用"租户 + external_id"做主键,不会因为重试发出多条。
Q:失败任务自动重试有哪些案例? AI Agent 团队最典型——Agent 调用一次,剩下的重试、登录失效检测全部由颜小二吞掉。具体见 [Agent 稳定执行层落地页](/lp/agent-stable-execution.html)。
Q:失败任务自动重试的对比方案是什么? 不重试或人工重试。前者发布稳定性靠运气,后者人力成本随账号数线性增长。两条路都没有"系统侧自动 + 业务侧只看结构化结果"划算。
下一步
- 字段定义:[API 文档](/docs.html)
- Agent 执行层方案:[Agent 稳定执行层](/lp/agent-stable-execution.html)
- 申请接入:[免费申请接入](/contact.html#form)