状态页搭建指南:给 AI 服务拆组件、定等级、写事故更新

博客 / 开发工具

状态页搭建指南:给 AI 服务拆组件、定等级、写事故更新

状态页搭建的难点不在选哪个工具,而在先想清楚四件事:页面上列哪些组件,每个组件的状态由谁判定,几个等级各自代表什么,出了事故每次更新写什么。对 AI API 服务来说,组件最好按“接入网关 + 各模型组 + 控制台”来拆,状态由自动探测和真实请求统计共同给出,人工只负责确认和写说明。下面按这个顺序讲,文末附上线前检查表。

文中拿 cdnping 自己的 API 状态页 和 AGI Plan 状态页 做参照。AGI Plan 是 cdnping 的商业合作方,这两个页面的做法和缺点我们都比较清楚。

状态页到底要回答用户什么问题?

用户打开状态页,通常只想知道三件事:

  1. 我现在遇到的问题,是不是你们那边的?
  2. 如果是,影响哪部分,你们知道了没有,大概什么时候好?
  3. 过去一段时间你们稳不稳?

所以状态页不是监控大盘,不需要把 CPU、队列长度这类内部指标搬上去,只需要给出用户能对照自己情况的结论。用户一般怎么读状态页,可以先看怎么看 OpenAI 状态页和 Claude 状态页。

组件怎么拆才对 AI 服务有用?

拆组件的原则是:用户能分辨出的故障边界,就是组件边界。用户分不出“鉴权服务”和“计费服务”的区别,但分得出“控制台登不上”和“接口报 5xx”。

一个典型的 AI API 服务可以这样拆:

组件用户看到的现象主要数据来源
API 接入网关连不上、TLS 失败、所有请求都报错外部探测
各模型组(例如推理组、通用组、轻量组)某一类模型报错多、变慢,其他正常真实请求成功率
控制台与登录网页打不开、登不上、建不了密钥外部探测 + 人工
计费与额度扣费异常、额度显示不对人工发布
文档与官网页面打不开外部探测
上游依赖(只展示,不计入自家可用率)上游厂商有事故同步上游官方状态页

模型组为什么要单独拆,数据能说明。以 AGI Plan 为例,cdnping 在 2026 年 10 月 17 日的快照里,从 Cloudflare 边缘(丹佛节点)探测 agiplan.dev 入口,可用率字段为 100%(采集当天才开始,实际只覆盖约一个半小时);同一份快照里,AGI Plan 公开的按真实请求计算的可用率,最近 1 天“快速组”约为 77.3%,“均衡组”为 100%,“前沿模型组”约为 99.8%。入口能通,不代表每一组模型都能用。如果状态页只放一个“API”组件,这种情况下它会一直是绿色。

上游依赖建议单独成区,标明“第三方”,不计入自己的可用率。

状态数据从哪来:自动探测、真实请求还是人工发布?

三种来源各有盲区,单用哪一种都不够。

来源能发现什么发现不了什么适合驱动
外部定时探测入口不可达、DNS/TLS 问题、整体变慢只有部分模型或部分请求失败网关、控制台、文档
真实请求统计按组的成功率、错误码分布没有流量的时段(夜里请求很少,比例不可靠)各模型组
人工发布计费错误、数据问题、计划维护反应慢,依赖值班人员事故说明、维护公告

探测和真实请求统计的区别,可以参考合成监控和真实用户监控有什么区别。

cdnping 的 /status 用的是前两种加上游同步:从 Cloudflare 边缘每 5 分钟探测各家官方 API 入口,每 15 分钟同步 OpenAI、Anthropic、Moonshot、Groq、Cloudflare、GitHub、Cursor 的官方状态页,保留 30 天历史。具体口径写在数据方法里。

探测数据会把真实情况放大或缩小,口径要写清楚。举一个例子:cdnping 在 2026-10-17 北京时间 16:40 到 18:05 之间,从丹佛(DEN)节点共做了 242 次探测,这一窗口里 Kimi 开放平台的可用率字段是 94.4%,p95 延迟 1125 ms,其余入口都是 100%。窗口只有一个半小时、只有一个节点,这个数字说明“这段时间从这个位置探测到过失败”,不能拿来评价长期稳定性。状态页上展示自己的数字时,同样要标明窗口和探测位置。

真实请求统计要注意分母。AGI Plan 的公开口径是“成功 /(成功 + 因平台自身原因失败)”,只有 5xx 算平台失败,用户的 401、429 不算。这个口径你可以不同意,但一定要写出来。夜里每小时只有几个请求时,一次失败就能让比例掉一大截,可以设一个最低请求数,低于它就显示“数据不足”而不是红色。怎么自己测、怎么定口径,可以看自己测 AI API 的可用率。

一个最小探测怎么写?

假设你的接口是 https://api.example.com,下面这条命令可以放进任意定时任务,每次输出状态码、连接耗时和总耗时:

curl -s -o /dev/null --max-time 10 \
  -w '%{http_code} %{time_connect} %{time_appconnect} %{time_total}\n' \
  https://api.example.com/v1/models

判断规则可以先这样定:拿不到状态码(超时、DNS 失败、TLS 失败)记为失败;5xx 记为失败;不带密钥返回 401 说明网关在正常工作,记为成功。探测点至少放两个不同地区,只有两个点同时失败才判定为“入口故障”,避免把单个探测点的网络问题算到自己头上。更完整的探测和告警清单见AI 应用可用性监控怎么做。

状态等级怎么定义?

等级越少越好用。建议四级加一个维护状态,并且把阈值写在页面上:

等级页面文案示例阈值(按 5 分钟窗口,需按自己的情况调整)
正常运行正常成功率 ≥ 99%,p95 延迟在基线 2 倍以内
性能下降部分请求变慢成功率 ≥ 99%,但 p95 延迟超过基线 2 倍
部分中断部分请求失败成功率在 90% 到 99% 之间,或某个模型组不可用
严重中断大部分请求失败成功率低于 90%,或入口不可达
维护中计划维护提前公告的维护窗口

几点经验:

  • 自动判定只负责调高等级;降回正常要人工确认或连续几个窗口恢复,避免页面黄绿来回跳。
  • 各家给事故定的级别差异很大,不要拿别人的分布当标准。cdnping 同步的官方状态页里,2026-09-17 到 2026-10-17 这一个月,OpenAI 登记了 major 4 次、minor 19 次,Cloudflare 登记了 major 3 次、minor 19 次。大部分事故都标为 minor,标准由各家自己定。
  • 可用率目标和等级阈值要对得上。目标和错误预算的算法见SLI、SLO、SLA 到底差在哪。

事故更新每一段该写什么?

事故公告常见四个阶段:调查中、已定位、观察中、已恢复。每一段都要回答固定的问题:

阶段必须写不要写
调查中现象、受影响组件、开始时间、下次更新时间未经确认的原因
已定位原因的大类(上游、配置变更、容量)、正在做什么甩锅给某个具体厂商的措辞
观察中已采取的措施、指标是否恢复、用户需不需要操作“已完全修复”这类还没验证的结论
已恢复影响时段(起止时间带时区)、影响范围、后续改进空泛的致歉段落

标题写“现象 + 范围”。官方状态页里的标题大多是这个结构,例如 cdnping 同步到的几条:

  • Increased HTTP 502 Errors(Cloudflare,minor,持续 591 分钟)
  • Network Performance Issues in London(Cloudflare,major,持续 13 分钟)
  • Elevated Errors in China Network Colos(Cloudflare,minor)
  • Widespread feature degradation(OpenAI,major,持续 146 分钟)

前三条一眼能看出影响和位置,最后一条范围较宽,需要点进去看组件。中文模板如下:

【部分中断】轻量模型组请求失败率升高
开始时间:2026-10-16 14:05(北京时间)
影响:轻量模型组约一半请求返回 5xx,其他模型组和控制台正常。
当前进展:已定位为上游供应商错误率升高,正在将流量切换到备用供应商。
用户需要做什么:无需修改配置;如有重试逻辑,建议使用指数退避。
下次更新:30 分钟内。

模板里的时间和比例是示例。AGI Plan 的公开数据里确实能看到类似的小时:cdnping 镜像的快照中,10 月 16 日北京时间 14 时起连续两个小时桶,失败请求分别是 722 和 877 次,多于同一小时的成功数(664 和 455)。像这样的小时,状态页上应该有对应的事故记录,否则用户会觉得页面没有反映实际情况。

另外两条规则:每次更新都写“下次更新时间”,到点没进展也要发一条“仍在处理”;已恢复的事故不要改写前面的更新,保留原文,补充说明即可。

历史保留多久?要不要提供 RSS 和 JSON?

历史建议至少保留 30 天,足够覆盖“最近一个月稳不稳”这个最常见的问题;条件允许可以更长。cdnping 的 /status 目前保留 30 天,而且采集从 2026-10-17 才开始,历史还很短,页面上会如实标出。

机器可读的出口建议都给:

  • JSON:给用户的监控系统和机器人用。cdnping 的开放数据接口 /api/status 以 CC BY 4.0 发布;AGI Plan 在 https://agiplan.dev/api/status/requests?month=YYYY-MM 提供逐小时、逐能力组的成功和失败计数,不需要登录。
  • RSS / Atom:给只想订阅事故公告的人用,每次事故更新生成一条。
  • Webhook 或邮件订阅:用户量大以后再加。

JSON 的字段可以参考下面这个结构(示例,不是某个现有接口的定义):

{
  "updated": "2026-10-23T12:00:00Z",
  "components": [
    {"id": "gateway", "status": "operational", "uptime_30d": 0.999},
    {"id": "group-fast", "status": "partial_outage", "uptime_30d": 0.98}
  ],
  "incidents": [
    {"id": "inc-001", "title": "轻量模型组请求失败率升高",
     "impact": "minor", "started": "2026-10-16T06:05:00Z", "resolved": null}
  ]
}

字段一旦公开就尽量别改名,下游会有人写死解析。

用什么搭:需不需要服务器?

开源和托管方案很多,这里不排名,只按部署方式分三类,选哪类取决于你愿意维护什么:

类型做法适合要注意
无服务器用 CI 定时任务或边缘定时任务做探测,结果写进仓库或对象存储,生成静态页小团队、组件少探测频率受定时任务限制,探测位置单一
自托管程序常驻服务 + 数据库,自带后台和事故编辑需要人工发布、订阅通知状态页要和主服务分开部署,否则主服务挂了它也一起挂
托管服务第三方托管页面和订阅不想维护数据口径受平台限制,接入自家请求统计要自己推送

不管哪一类,有一条要坚持:状态页和被监控的服务不要共用同一套基础设施,包括域名解析、CDN 和数据库。如果你的主站在 Cloudflare 上,状态页可以放在另一家托管,反过来也一样。2026 年 10 月中旬 Cloudflare 自己的状态页就登记过 Workers 定时触发器(Cron Triggers)和 Durable Objects 的故障,探测程序如果跑在这些组件上,那几天就可能缺数据。

上线前检查表

  • 组件按用户能分辨的故障边界拆分,模型组单独列出
  • 每个组件写明数据来源:探测、请求统计还是人工
  • 探测点至少两个地区,单点失败不直接判红
  • 请求统计设了最低请求数,样本不足时显示“数据不足”
  • 等级阈值和可用率口径写在页面或方法说明里
  • 事故模板包含现象、范围、开始时间(带时区)、用户需要做什么、下次更新时间
  • 上游依赖单独成区,不计入自家可用率
  • 历史至少 30 天,并标明采集起始日期
  • 提供 JSON 和 RSS,字段名写进文档
  • 状态页与主服务的 DNS、CDN、数据库分开
  • 演练一次:手动制造一个组件故障,看页面多久变色、公告多久发出

最后一项最容易跳过,也最能暴露问题。上线后可以用 /down 这类综合官方状态、API 探测和用户报告的页面对照自己的状态页,看两边的判断是否一致;想了解过去一段时间各家官方状态页实际登记了什么,可以看 2026 年 9–10 月 AI 服务故障盘点。

相关文章

继续阅读