---
title: "合成监控和真实用户监控的区别：AI 应用怎么组合拨测与 RUM"
description: "讲清合成监控（拨测）与真实用户监控（RUM）的区别，结合 LLM 接口、流式响应和“变笨了”这类 AI 特有信号，给出按场景选型的对照表、curl 拨测命令和前端埋点代码，以及一个最小实施方案。"
url: https://cdnping.org/blog/synthetic-monitoring-vs-real-user-monitoring-ai
language: zh-CN
published: 2026-10-25
category: "性能"
tags: ["监控","合成监控","RUM","可用性","AI API"]
source: cdnping.org
license: Free to quote and summarize with a link to the url above.
---
# 合成监控和真实用户监控的区别：AI 应用怎么组合拨测与 RUM

合成监控和真实用户监控的区别可以这样概括：合成监控是你自己按固定频率、从固定位置发请求去“试一下”，回答的是“服务现在通不通”；真实用户监控（RUM）是从真实用户的请求里收集数据，回答的是“用户实际用起来怎么样”。前者没有用户也能工作，但只代表探测点所在的网络；后者最贴近体验，但没有流量的时候就是一片空白。

做 AI 应用时，两者之间的空档更明显。上游模型 API 网络是通的，返回的结果却可能变差；流式响应的首个 token 迟迟不来，HTTP 状态码却是 200。下面把两种方式落到 LLM 接口上，再用 cdnping 自己的做法说明怎么组合。

## 合成监控和真实用户监控分别是什么？

**合成监控（Synthetic Monitoring）**，国内常叫“拨测”或“主动监控”。你写好一个脚本，例如每 5 分钟请求一次某个 API 入口，记录是否成功、耗时多少。请求是“合成”出来的，不是任何用户发起的。

**真实用户监控（Real User Monitoring，RUM）**，也叫“被动监控”。在前端或服务端埋点，把每个真实请求的状态码、耗时、首字节时间等上报。数据量随流量变化，有多少用户就有多少样本。

| 维度 | 合成监控（拨测） | 真实用户监控（RUM） |
|---|---|---|
| 数据来源 | 自己发的探测请求 | 用户真实请求 |
| 什么时候有数据 | 7×24，按固定频率 | 只在有流量时 |
| 代表谁的网络 | 探测节点所在的机房和线路 | 用户自己的网络、设备、地区 |
| 擅长发现 | 上游完全不通、证书过期、DNS 解析失败 | 某地区变慢、某类请求失败、长尾延迟 |
| 盲区 | 测不到用户侧网络；只测固定请求，测不到“答得差” | 低峰期样本少；上线前没有数据 |
| 能否做基线对比 | 能，条件固定，前后可比 | 难，用户构成一直在变 |
| 成本 | 探测频率 × 节点数，可控 | 和流量成正比，要考虑采样 |

## 放到 AI 应用里，两者各自漏掉什么？

普通网页的监控文章大多讨论首屏时间、LCP 这类指标。AI 应用多了三类信号，正好分别落在两种方式的盲区里。

### 1. 探测点的网络不等于用户的网络

合成探测只能说明“从探测点出发是通的”。以 cdnping 的 [API 状态页](/status) 为例：它从 Cloudflare 边缘节点每 5 分钟探测一次各家官方 API 入口。2026-10-17 生成的数据快照里，探测来自 DEN 节点（丹佛），窗口是当天 UTC 08:40 到 10:05，共 242 次探测。在这个窗口里：

- Claude API 的中位耗时为 73 ms，xAI API 为 42 ms；
- DeepSeek API 为 353 ms，阿里云百炼为 615 ms，硅基流动为 631 ms。

这组数字只说明“从丹佛的边缘节点看过去”是这样，不能理解为国内服务比海外服务慢。从国内网络发起探测，结果通常会反过来。这正是合成监控的局限：数据准确，但代表性取决于探测点放在哪里。要知道用户那一侧的情况，需要在用户的网络里测，例如 cdnping [首页的在线测速](/)，它在浏览器里测“首次连接”（含 DNS 与 TLS 握手）和“往返”（连接复用后 3 次请求的中位数）。两段耗时怎么拆分，可以参考 [AI API 延迟拆解：连接建立、网关往返与首 token 时间](/blog/api-latency-connect-rtt-ttft)。

### 2. 流式响应：200 不代表体验好

LLM 接口大多用 SSE 流式返回。一个常见情况是：响应头很快回来，状态码 200，但第一个 token 过了很久才到。只检查状态码的拨测会判定“正常”，用户看到的却是界面卡住不动。

所以 AI 应用的监控至少要分开记录：连接建立耗时、首 token 时间（TTFT）、完整响应耗时。合成探测可以用一个固定的小请求测 TTFT，得到可比的基线；RUM 则能告诉你真实的长提示词、长输出下 TTFT 分布是什么样。

### 3. “变笨了”：两种方式都很难直接测出来

模型输出质量下降，网络层面完全看不出来。可能的原因包括推理供应商换了、量化精度变了（例如 fp8、fp4），相关背景见 [模型变笨还是换了供应商](/blog/llm-quantization-fp8-fp4-providers)。cdnping 的 [模型监测页](/models) 会记录 OpenRouter 上各供应商的量化精度变化，可以作为一条旁证。

在监控体系里，这类问题通常靠两种手段：

- 合成侧：准备几条答案确定的固定提示词（例如让模型按固定格式输出一段 JSON），定时调用并校验结构是否合法、关键字段是否正确。这比只看状态码多走了一步，但也只能覆盖你预设的题目。
- 用户侧：在界面上放一个“答得不好”的反馈入口，统计反馈比例的变化。

cdnping 的 [挂了吗](/down) 页面就是这个思路：除了官方状态页和每 5 分钟的 API 探测，还收集用户一键报告，报告类型分为打不开、很慢、变笨了、限流、额度被重置、被登出。“打不开”“很慢”网络探测能部分发现；“变笨了”“额度被重置”“被登出”这类问题，探测基本测不到，只能靠用户告诉你。

## 没有流量时，真实用户数据会是什么样？

RUM 的盲区可以用一份公开数据直接看到。AGI Plan 公开了按真实请求计算的可用率数据（AGI Plan 是 cdnping 的商业合作方），接口是 `https://agiplan.dev/api/status/requests?month=YYYY-MM`，按小时给出成功和失败计数，只有 5xx 算平台失败。

快照中 2026-10-15 到 10-17 的 48 个小时桶里，能看到两种情况：

- 故障时信号很清楚：10 月 16 日 UTC 早上连续两个小时桶，分别是 664 成功 / 722 失败、455 成功 / 877 失败。真实请求失败率在这样的时段非常醒目，不需要额外探测就能发现。
- 低峰期几乎没有样本：10 月 16 日 UTC 20 点到 22 点的三个小时桶，每个只有 2 个请求。这时候即使服务完全不可用，RUM 也很难给出可信的结论，2 个请求失败 1 个就是 50%。

这就是需要合成探测补位的原因：固定频率的探测在低峰期依然有稳定样本。反过来，探测只覆盖固定请求，不能代替真实请求的失败率。可用率的口径和错误预算怎么算，可以看 [SLI、SLO、SLA 到底差在哪](/blog/sli-slo-sla-error-budget-explained)。

## 按场景怎么选？一张判断表

| 你想回答的问题 | 首选 | 补充 |
|---|---|---|
| 上游模型 API 现在通不通 | 合成探测（多节点） | 官方状态页 |
| 半夜没人用时服务是否正常 | 合成探测 | — |
| 某个地区或运营商的用户是否变慢 | RUM（按地区分组） | 在该地区补一个探测点 |
| 流式响应首 token 是否变慢 | 两者都要：探测看基线，RUM 看分布 | — |
| 升级 SDK 或换网关后是否变差 | 合成探测做前后对比 | 灰度期间看 RUM |
| 模型输出质量是否下降 | 固定提示词的结构校验 | 用户反馈比例 |
| 是否触发了限流（429） | RUM（真实并发才会触发） | — |
| 判断是服务故障还是用户自己的网络 | 合成探测 + 用户侧测速对照 | 见 [三步判断是服务故障还是网络问题](/blog/is-chatgpt-down-or-my-network) |

## 最小实施方案

下面是一个小团队可以照着做的组合，按顺序推进。

### 第一步：给每个上游入口加一个合成探测

最简单的版本用 curl，每 5 分钟跑一次，把各阶段耗时记下来：

```bash
curl -o /dev/null -s --max-time 10 \
  -w 'code=%{http_code} dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
  https://api.anthropic.com/v1/models
```

不带密钥请求时返回 401 是正常的，说明 DNS、TCP、TLS 和对方网关都工作了；超时、000 或 5xx 才说明有问题。判断规则建议写成“连续 2 次失败才告警”，避免单次网络抖动造成误报。

如果要测 TTFT，再加一个带密钥的固定小请求，开启流式，记录收到第一个数据事件的时间。注意 curl 的 `time_starttransfer` 记录的是第一个响应字节，可能只是响应头，不一定是第一个 token，严格测 TTFT 需要在脚本里解析 SSE 事件。

探测节点至少放两个：一个靠近你的服务器，一个靠近主要用户。更完整的告警配置可以参考 [AI 应用可用性监控怎么做](/blog/ai-app-availability-monitoring-guide)，脚本和口径参考 [自己测 AI API 的可用率](/blog/measure-ai-api-uptime-yourself)。

### 第二步：在前端给流式请求加 RUM 埋点

在发起对话的地方包一层计时，把结果用 `sendBeacon` 上报：

```js
async function chatWithTiming(url, body, onChunk) {
  const t0 = performance.now();
  let ttft = null, status = 0, error = null;
  try {
    const res = await fetch(url, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(body),
    });
    status = res.status;
    const reader = res.body.getReader();
    for (;;) {
      const { done, value } = await reader.read();
      if (done) break;
      if (ttft === null) ttft = performance.now() - t0;
      onChunk(value);
    }
  } catch (e) {
    error = e.name;
  } finally {
    navigator.sendBeacon('/rum', JSON.stringify({
      status,
      error,
      ttft_ms: ttft === null ? null : Math.round(ttft),
      total_ms: Math.round(performance.now() - t0),
      net: navigator.connection ? navigator.connection.effectiveType : null,
    }));
  }
}
```

服务端只需要把这些字段存下来，按小时汇总成功数、失败数和 TTFT 分位数。不要上报提示词和回答内容；如果需要地区维度，在服务端按 IP 粗粒度解析出地区后丢弃原始 IP。

### 第三步：放一个用户反馈入口

在每条回答旁边放“答得不好”和“很慢”两个按钮，记录时间和所用模型组。它的样本量远小于 RUM，但能覆盖前两步都测不到的质量问题。

### 第四步：把三路信号放在同一张图上

告警时按下面的顺序看：

1. 合成探测失败、RUM 失败率也升高：上游或你自己的服务出了问题，查官方状态页，阅读方法见 [怎么看 OpenAI 状态页和 Claude 状态页](/blog/how-to-read-ai-status-pages)。
2. 合成探测正常、RUM 失败率升高：多半是用户侧网络、某个地区线路，或者真实并发触发了限流，按错误码和地区分组看。
3. 两者都正常、用户反馈增多：考虑质量问题，跑一遍固定提示词校验，看看模型或供应商是否有变化。
4. 合成探测失败、RUM 正常：先怀疑探测节点自身的网络，或者探测的入口和用户实际用的入口不一样。

## cdnping 自己是怎么组合的？

cdnping 本身就是三种信号的组合，可以当作一个参考样例：

- 边缘合成探测：[/status](/status) 从 Cloudflare 边缘每 5 分钟探测各官方 API 入口，每 15 分钟同步部分官方状态页，保留 30 天历史；
- 用户侧主动测量：[首页测速](/) 在用户浏览器里测连接和往返耗时，结果可以匿名计入统计，不记录 IP。它介于合成和 RUM 之间：请求是合成的，但发生在用户真实的网络里；
- 用户信号：[/down](/down) 的一键报告，补上“变笨了”“额度被重置”这类探测测不到的问题。

各项数据的采集方式和口径写在 [数据方法](/methodology) 页。需要说明的是，cdnping 从 2026-10-17 开始采集，本文引用的探测和请求数据都只覆盖很短的窗口，用来说明方法，不代表任何服务的长期表现。

## 常见误区

- 只做拨测，就认为用户体验没问题。拨测只证明探测点能连上，用户在哪个网络、用什么设备，它不知道。
- 只看 RUM 的平均值。AI 请求的耗时和输出长度强相关，平均值会被长回答拉高。按 TTFT 和总耗时分开统计，并看 p95。
- 把 401、429 都当成故障。401 往往是密钥或配置问题，429 是限流，处理方式不同，不要和 5xx 合并成一个失败率。429 的处理见 [API 返回 429 Too Many Requests 怎么办](/blog/llm-api-429-too-many-requests-fix)。
- 低峰期用 RUM 判断可用率。几个请求的样本算出来的百分比波动很大，这个时段应以合成探测为准。

小团队不需要一次全做。先按上面的第一、二步加上合成探测和流式请求埋点，网络不通、上游 5xx 和首 token 变慢这几类问题就能看到；质量问题再靠第三步的反馈入口补。
