RUM 真实用户监控方案设计
如果说 Lighthouse/Performance 面板告诉你“理论上能跑多快”,那么 RUM(Real User Monitoring) 才能回答:
- 真实用户到底慢在哪?
- 慢是“某地区/某机型/某版本/某网络”的问题还是全局问题?
- 优化上线后是否真的变好?有无回归?
这篇文章不讲“把 SDK 丢进去就完事”,而是站在体系设计角度,从 0 到 1 设计一套能长期演进的 RUM:
- 指标体系(Core Web Vitals + 业务指标)
- 采样与成本控制
- 上报协议与可靠性
- 事件模型与数据仓库建模
- 分析维度(分桶)与聚合
- 告警与 SLO
- 隐私与合规
1. 先定目标:RUM 的“产品定义”
在做任何技术实现前,你必须把目标写成一句可验证的话:
我们要用 RUM 在 7 天内发现性能回归,并能定位到“哪类用户/哪条链路/哪个版本”导致 INP 恶化。
RUM 的价值通常分三层:
- 可见性:上线后真实体验有数据
- 可定位:能切片(地区/设备/页面/版本)
- 可闭环:告警 → 归因 → 修复 → 复盘
如果你只做第 1 层,它会退化成“报表”。
2. 指标体系:不要只盯 Core Web Vitals
2.1 必选:Core Web Vitals + 补充指标
建议最小集合:
- LCP(最大内容绘制)
- INP(交互到下一次绘制)
- CLS(布局偏移)
- TTFB(服务端首字节)
- FCP(首屏内容绘制,辅助解释 LCP)
但这还不够,你还需要“解释型指标”:
- Long Task(长任务)统计(数量/总时长/Top 贡献)
- Resource timing(关键资源耗时)
- JS 错误/资源错误(与性能回归强相关)
2.2 业务指标:把性能与转化绑定
纯性能指标很容易变成“工程师自嗨”。
建议定义 1~3 个业务级指标:
- 首次有效交互时间(例如搜索可用、下单可点)
- 首次关键接口完成(例如
/api/me完成) - 转化漏斗关键点耗时(例如“加入购物车”到“支付成功”)
这些指标让你能回答:
- “慢 200ms 对业务有没有影响?”
3. 采样策略:RUM 成败的 50%
RUM 的难点不是“能不能采”,而是“采多少、怎么采、怎么省钱”。
3.1 两种采样:会话采样 vs 事件采样
- 会话采样:进入站点就决定该会话是否采集全部指标
- 优点:链路完整、便于归因
- 缺点:成本高
- 事件采样:每种事件独立采样(例如性能 10%、错误 100%)
- 优点:更灵活
- 缺点:同一会话数据不完整
生产建议:两者结合。
3.2 分层采样建议
一个可用的默认配置:
- 性能指标:10%(按会话)
- 错误指标:100%(或至少 50%)
- 关键交易链路:100%(只对“完成交易”的会话上报完整链路)
3.3 动态采样:用“预算”来管理
你可以给 RUM 设预算:
- 每日上报不超过 N 条
- 每秒不超过 M 条
当超预算时:
- 降低非关键事件采样率
- 只保留异常事件(例如 LCP > 4s)
4. 客户端采集:指标怎么拿?
4.1 Web Vitals 指标
现代浏览器提供了可观测入口:
PerformanceObserverperformance.getEntriesByType()
你可以使用社区实现(例如 web-vitals 思路),但要明确:
- 指标口径要固定(同一页面、同一版本)
- 不同浏览器差异要做兼容
4.2 上下文(Context)是 RUM 的灵魂
只上报 LCP=2500ms 没意义。
你至少需要这些维度:
- 页面:
path,routeName,referrer - 用户:匿名
userIdHash(可选) - 设备:
deviceMemory,hardwareConcurrency,viewport - 网络:
effectiveType,rtt,downlink - 版本:
appVersion,buildId,commitSha - 环境:
prod/staging,region,cdnPop
这些字段必须:
- 控制体积(短字段名/枚举)
- 可被服务器校验(防伪造污染)
5. 上报链路:可靠性与性能不能两头都丢
5.1 传输:优先 sendBeacon,降级到 fetch(keepalive)
- 页面卸载时
sendBeacon更可靠 - 非卸载场景可用批量
fetch
5.2 批量与压缩
建议:
- 以 5~20 条为一个 batch
- gzip/br 压缩(服务器支持)
- 限制 payload 大小(例如 < 64KB)
5.3 去重与重试
- 给每条事件生成
eventId - 服务端按
eventId去重 - 客户端失败重试次数有限(例如 2 次)
5.4 采集对页面的影响
RUM 本身不能成为性能负担。
实践建议:
- 采集计算尽量放在 idle(
requestIdleCallback) - 上报放在后台、批量
- SDK 初始化延后(首屏后)
6. 事件模型与数据建模:决定你能不能分析
6.1 事件类型(Event Types)
建议至少定义:
page_viewweb_vitalsresource_timinglong_taskjs_errorapi_timing(业务关键接口)
每种事件都有“必填字段”和“可选字段”。
6.2 存储建模:宽表 + 明细表
常见两种设计:
- 宽表(便于查询):把常用字段打平
- 明细表(便于追踪):存完整 payload(可选)
一个可落地的折中:
- 以
web_vitals为核心宽表(用于大盘/SLO) - 以
session_trace为明细表(只对采样会话存)
6.3 聚合口径:p75/p90/p95/p99
RUM 的统计不要只用平均值。
推荐:
- p75:更贴近“多数用户体验”
- p95/p99:定位极端慢问题
对于 Web Vitals,Google 口径常用 p75。
7. 分析维度:怎么做到“可定位”?
可定位的关键在于“维度设计”。
建议固定一套常用切片:
- 页面(路由)
- 地区/运营商
- 设备档位(内存/CPU 核数分桶)
- 网络(4g/3g/slow-4g)
- 版本(最近 10 个 buildId)
- 入口来源(referrer/channel)
注意:维度越多,成本越高。
实践做法:
- 维度字段做枚举/分桶
- 对长尾维度做 Top N
8. 告警与 SLO:让 RUM 成为“系统”
8.1 SLO 的定义
示例:
- 过去 1 天内,p75 LCP < 2500ms
- 过去 1 天内,p75 INP < 200ms
- 过去 1 天内,CLS p75 < 0.1
8.2 告警规则
建议用“双阈值”防抖:
- 5 分钟窗口连续超阈值
- 且样本量 > 最小值(例如 300)
8.3 回归检测
把版本作为维度:
- 新版本的 p75 INP 相比上版本恶化 > 15%
- 触发告警并附带“top 页面 / top 设备 / top 地区”
9. 隐私与合规:你必须提前做的约束
- 禁止上报 PII(手机号、邮箱、身份证等)
- URL 中 query/fragment 需要脱敏
- 事件 payload 做字段白名单
- 允许用户 opt-out(尤其是欧盟地区)
如果产品面向多地区,建议把合规当成“需求”,不是“上线前检查”。
10. 最小可用方案(MVP)建议
如果你要在 1~2 周内把 RUM 跑起来:
- 先采:page_view + web_vitals + js_error
- 先做:按路由维度的大盘(p75)
- 再做:版本对比(回归检测)
- 最后做:会话 trace(定位长尾)
总结
RUM 的关键不是 SDK,而是:
- 指标体系与业务目标绑定
- 采样与预算控制成本
- 上报可靠且不影响性能
- 数据建模支持切片与聚合
- 告警/SLO 能闭环


