【背景】
我做了 8 年前端,最近半年主抓的是核心链路的稳定性与可观测性。一个让我反复纠结的场景:
我们的下单页走的是「页面渲染 → 表单校验 → 调 3 个接口(库存 / 价格 / 优惠券)→ 提交订单」这条链路。上个月一次灰度,前端做了组件重构 + 接口并发策略调整:
- 后端接口 5xx 率:灰度组 0.04%,对照组 0.05%(基本持平,甚至略好)
- 但前端会话成功率(定义:进入下单页 → 成功提交订单,期间无未捕获异常 / 无核心接口超时):灰度组 92.1%,对照组 95.8%
接口侧看不出问题,但用户侧多了 3.7pp 的失败。复盘才发现:重构后接口并发从「串行」改成了「Promise.all 并行」,某个慢响应(P99 800ms)会让 Promise.all 整体等待时间被拉长,前端在 3s 的 setTimeout 兜底里抛超时,但后端其实 3.2s 返回了 200 —— 接口侧记的是"成功",用户侧记的是"失败"。
这件事让我开始认真想一个更基础的问题:前端 SLO 的"北极星"指标到底该锚定在哪?
【常见分歧 / 几种做法】
我观察到的至少有三种口径:
派别 A:接口 5xx 率 + 4xx 率
- 优点:简单、后端天然就有、Prometheus 一行 PromQL 搞定、跨团队对齐成本低
- 缺点:抓不到"接口都 200 但用户没走完"的场景(比如上面那个 Promise.all 超时、前端 JS 异常、白屏、首屏卡死)
- 典型用法:灰度判定的"硬门槛",5xx 率劣化 10% 就回滚
派别 B:Web Vitals(LCP / INP / CLS)
- 优点:Google 推荐、有通用阈值(LCP < 2.5s / INP < 200ms / CLS < 0.1)、
web-vitalsSDK 一行接入 - 缺点:不区分业务路径,首页 LCP 2.3s 和下单页 LCP 2.3s 的业务含义完全不同;INP 是交互感知,对"提交订单"这种单次操作覆盖很弱
- 典型用法:体验大盘的"长期趋势",不做灰度硬门槛
派别 C:用户会话成功率 / 任务完成率
- 优点:最贴近用户真实感知,能抓住"接口 200 但用户没走完"的隐性失败
- 缺点:口径难定(什么算"一次会话"?什么算"核心路径"?)、采样成本高、需要前端埋点体系支撑、跨端(H5 / App / 小程序)对齐困难
- 典型用法:核心业务路径(下单 / 支付 / 登录)的 SLO,一般要求 ≥ 99%
【我的倾向与理由】
我目前的实践是「分层 + 分路径」:
-
核心业务路径(下单 / 支付 / 登录)用"会话成功率"做灰度硬门槛
- 口径:进入核心页面 → 成功完成目标动作,期间无未捕获 JS 异常 / 无核心接口超时 / 无白屏(用
PerformanceObserver+error事件 + 自定义mark埋点) - 阈值:灰度组 vs 对照组劣化 ≥ 0.5pp 触发告警,≥ 1pp 自动暂停灰度
- 数据源:自研前端可观测 SDK,采样率 100%(核心路径 QPS 不高,全量扛得住),数据落到 ClickHouse,5min 聚合
- 口径:进入核心页面 → 成功完成目标动作,期间无未捕获 JS 异常 / 无核心接口超时 / 无白屏(用
-
非核心路径(列表页 / 详情页 / 营销页)用 Web Vitals + 接口 5xx 率组合
- LCP P75 劣化 ≥ 100ms 触发告警
- 接口 5xx 率劣化 ≥ 10% 触发告警
- 这两个指标用 RUM 平台(我们用的某云 RUM)+ 后端 Prometheus 双源
-
JS 异常率作为"兜底"指标
- 口径:
window.onerror+unhandledrejection+ 框架 errorBoundary,按page + component维度聚合 - 阈值:灰度组 vs 对照组劣化 ≥ 50% 触发告警
- 这个指标的好处是"什么 bug 都能兜住",缺点是噪声大(用户网络抖动、第三方 SDK 异常都会进来),需要白名单过滤
- 口径:
【想听大家在什么场景下怎么选】
几个具体问题,想听听不同规模 / 不同业务形态的同学怎么定:
- 你们的前端 SLO 北极星指标是什么? 是接口 5xx、Web Vitals、会话成功率,还是别的?
- "会话成功率"的口径你们怎么定? 什么算"一次会话"?什么算"核心路径"?是产品定的还是 SRE 定的?
- 灰度判定的"硬门槛"和"软观察"你们怎么分? 哪些指标劣化直接回滚,哪些只告警不回滚?
- 前端可观测 SDK 的采样率怎么定? 核心路径 100% 全量你们扛得住吗?非核心路径降到 10% 会不会漏掉长尾?
- 跨端(H5 / App / 小程序)的 SLO 怎么对齐? 是统一口径还是各端各定?
- 有没有遇到过"接口 200 但用户没走完"的隐性失败? 你们的排查路径是什么?
我抛砖引玉,期待拍砖。
0赞
0收藏
0楼层