颜小二 Logo颜小二内容中心

YanXiaoer Insights

技术与运营洞察

从内容生成到多平台发布,从 AI Agent 调用到账号矩阵运营,颜小二把发布这件事变成可调用、可追踪、可持续维护的执行层。

YanXiaoer Insight · 2026-05-10 · 8 分钟阅读

如何处理发布失败任务的自动重试(进阶版 28)

发布失败的"重试"经常被写得太简单。本文从企业自媒体团队角度出发,把失败分类、退避策略、callback_url 闭环、external_id 幂等讲透,给出 6 步可落地的重试体系与错误码对照表。

如何处理发布失败任务的自动重试(进阶版 28)

企业自媒体团队接入发布 API 之后,最容易被运营追问的不是"发布速度有多快",而是"昨天那批发失败的有没有补上"。

> 重试不是简单的 sleep(30); retry()。失败原因不同,重试策略也完全不同。

如果你做的不是个人号,而是要为公司、为客户、为多个品牌矩阵把内容稳定发出去,这篇文章会教你怎么用 6 步搭建一套可观测、可追溯、不会重复发的失败任务自动重试体系。底层用的是颜小二自媒体发布 API 平台,但思路对自建系统也通用。

发布失败重试链路示意图

这篇适合谁

  • 企业自媒体技术中台:每天 50+ 篇文章,分发到头条号、微信公众号、百家号、知乎,需要补漏机制
  • MCN 矩阵运营技术负责人:账号多、平台多、人工补发太累
  • 内容 SaaS 集成商:把发布做到自家产品里,得给客户一个"能扛"的承诺
  • 有过被运营追问"昨天为什么少发了 12 篇"经历的所有人

前置:先把"失败"分清楚

在写第一行重试代码之前,先把失败拆成 3 类,否则你会越重试越乱:

| 失败类别 | 典型表现 | 是否可重试 | |---|---|---| | 临时性失败 | 网络抖动、平台 5xx、上游限流 | 可,自动 | | 登录态失败 | cookie 过期、滑块、二次验证 | 不可自动,需重登 | | 业务性失败 | 内容违规、标题超长、分类错误 | 不可,需人工 |

任何"一律重试 N 次"的实现都会在第 2 类、第 3 类上踩坑——把审核驳回的稿子重发 5 遍,账号大概率被风控。

6 步搭起重试体系

第 1 步:每篇文章给一个稳定的 external_id

external_id 是颜小二的幂等主键。同一个 external_id + 平台,重发不会发两次。建议命名规则:{业务系统}_{文章 ID}_{版本},例如 cms_98231_v1

如果你的内容来自 CMS,把 CMS 文章 ID 直接拼进去最稳。

第 2 步:在你侧落一张 task 表

每次调发布 API 时同步落库,最少这几列:

  • external_id(业务侧主键)
  • group_code(账号分组路由键)
  • target_platforms(目标平台清单)
  • status(pending / running / success / failed / login_expired)
  • retry_count(已重试次数)
  • last_error_code(上次失败的结构化错误码)
  • next_retry_at(下次可重试时间戳)

第 3 步:固定 callback_url 接收结构化结果

颜小二每次任务终态都会回调你侧的固定 callback_url,结构化字段包含 statusplatform_urlerror_codeerror_msgretryable

你的 callback handler 拿到回调后做三件事:

1. 按 external_id + platform 找到对应任务行 2. 更新 statuslast_error_code 3. 如果 retryable=trueretry_count < 上限,进入重试队列;否则进入人工队列

第 4 步:用指数退避而不是固定间隔

固定间隔(每 60 秒一次)会在平台限流时雪上加霜。用指数退避:

  • 第 1 次:60 秒后
  • 第 2 次:3 分钟后
  • 第 3 次:10 分钟后
  • 第 4 次:30 分钟后
  • 第 5 次:2 小时后

5 次还失败就转人工,不要无限重试。每次重试调发布 API 时保持 external_id 不变,幂等机制会保证不会真的发出去两份。

第 5 步:登录态失败走单独通道

login_expired 不能走普通重试。颜小二会在回调里明确标记 error_code: LOGIN_EXPIRED,你的处理是:

1. 把对应 group_code 下的账号标记为"待重登" 2. 通知本地 Agent 触发该账号的扫码重登流程 3. 重登成功后再把这些 pending 任务批量重投

登录态本地保存(cookie 不上云)是颜小二的安全前提,所以重登必须在客户本地 Agent 完成。

第 6 步:可视化复盘"重试看板"

retry_count > 0 但最终成功的任务、转人工的任务、各平台的失败率单独做一个看板。这个看板能直接告诉你:

  • 哪个平台最近不稳(可能是它前端改版了)
  • 哪个 group_code 下账号最容易掉登录
  • 哪类业务错误最多(标题策略可能要调)

调用代码示例

下面是带重试逻辑的伪代码片段。注意 external_id 在重试时复用:

``json { "external_id": "cms_98231_v1", "group_code": "brand_a_default", "title": "你的文章标题", "content_html": "<p>正文 HTML</p>", "cover_url": "https://yourcdn.com/cover.jpg", "summary": "一句话摘要", "tags": ["AI", "效率"], "category": "科技", "target_platforms": ["toutiao", "wechat_mp", "baijiahao", "zhihu"], "callback_url": "https://your-domain.com/yanxiaoer/callback" } ``

收到 callback 后:

``python def on_callback(payload): task = db.find_by_external_id(payload["external_id"]) task.status = payload["status"] task.last_error_code = payload.get("error_code") if payload["status"] == "failed" and payload.get("retryable"): if task.retry_count < 5: task.next_retry_at = now() + backoff(task.retry_count) task.retry_count += 1 enqueue_retry(task) else: mark_for_human_review(task) elif payload.get("error_code") == "LOGIN_EXPIRED": mark_account_relogin(task.group_code) ``

代码与控制台示意

错误排查清单

| 现象 | 常见原因 | 处理建议 | |---|---|---| | 同一篇被重复发了 2 次 | 重试时换了 external_id | 重试必须复用原 external_id | | 重试 5 次还失败 | 失败属于业务类(违规/格式) | 转人工,不要继续重试 | | 一批账号同时失败 | 某平台风控集中触发 | 暂停该 group_code 24 小时 | | 看不到任何回调 | callback_url 公网不可达 | 检查 HTTPS 证书与防火墙 | | 部分平台成功部分失败 | 各平台审核策略差异 | 看回调 error_msg 针对性调 |

颜小二的多租户内容分发执行中台,把"任务结构化 + callback 闭环 + external_id 幂等"做成默认能力。一个站长 = 一个租户,独立的 API Token、独立的 callback_url、独立的 group_code 路由,重试逻辑跨租户互不干扰。

发布矩阵的可视化重试看板

常见问题(FAQ)

Q:颜小二自己内部会重试吗? 会。临时性失败(网络、5xx、上游短时限流)颜小二底层会重试 N 次后才上报,到你这层一般已经是终态。所以你侧的重试主要处理"颜小二都救不回来"的情况。

Q:重试要不要换 external_id? 绝对不要。同 ID 重发是幂等设计的核心,颜小二会识别为同一任务,不会真的发两次。

Q:可以无限重试吗? 不建议。经验上 5 次封顶比较合理,超过就转人工。无限重试会让"真实失败"被淹没在噪音里。

Q:登录态失败为什么要单独处理? 因为登录态保存在客户本地(cookie 不上云是安全前提),重登必须在本地 Agent 完成。云端无法替代这一步,硬重试只会一直失败。

Q:颜小二的失败回调延迟多久? 平均在任务终态后 1-3 秒内推送。极少数情况下你的 callback_url 不可达时,我们会按指数退避重推,详见 [API 文档](/docs.html)。

下一步

如果你正在被"昨天有 X 篇没发出去"反复打扰,把重试这层独立出来是收益最高的工程改造之一。先用 1 个 group_code 跑通失败-回调-重试-复盘的全链路,再扩到全矩阵。

→ [免费申请接入](/contact.html#form) | [查看 API 文档](/docs.html) | [自媒体发布 API 落地页](/lp/zimedia-publish-api.html)