很多初学者一接触线上排障,会自然得出一个结论:既然要查问题,那就把每个请求都记下来,最保险。这个想法不奇怪,甚至在低流量系统里常常可行。
但到了高QPS在线服务,这套思路很容易变成“为了看病,先把病人累趴下”。更常见、更稳的做法是:平时用采样 Trace 看全局路径,低频 Profiling 看资源热点,只有出现异常时才打开按需诊断。你换来的好处是性能更稳、成本更低;你付出的代价是细节变少、偶发问题更难复现。
换句话说,这不是“少监控”,而是“分层监控”。先用轻量手段盯住大盘,真的闻到焦味了,再把放大镜掏出来。
先把几个词翻成人话
高QPS:就是每秒进来的请求非常多。你可以把它想成午高峰的地铁闸机,不是一两个人慢慢过,而是一波一波往里涌。比如一个热门下单接口,平时每秒几百个请求,大促时一下子冲到更多,这就是典型的高QPS场景。
观测性:就是系统出问题时,你能不能从外面看出里面到底发生了什么。它像汽车仪表盘,你不拆发动机,也能先知道是油不够、温度高,还是转速异常。比如订单服务变慢时,团队不需要立刻登录每台机器翻日志,而是先从每秒请求数、错误率、延迟和调用链里判断卡在数据库、缓存还是下游接口。
Trace:就是一次请求在多个服务之间走过的“足迹”。它像快递物流轨迹,包裹经过仓库、分拨站、配送点,都会留下记录。比如用户点一次“提交订单”,请求先过网关,再到订单服务、库存服务、优惠券服务、支付服务,这一路留下的时间和调用关系,就是一条 Trace。
采样:不是把每个请求都记下,而是按规则抽一部分看。它像高峰期餐厅做回访,不会每桌都问一遍,而是先抽一些样本判断整体服务是不是跑偏。比如订单服务平时只保留 1% 的普通请求,但对报错请求和超慢请求尽量全留,这就是很常见的采样思路。
Profiling:就是给程序做“体检”,看 CPU、内存、锁等待这些资源到底花在了哪里。它像运动员带着心率表做阶段性测试,不是 24 小时全程做全套检查。比如服务 CPU 忽然飙高,团队开一个 30 秒的 Profiling,就能看出时间到底耗在数据转换、数据库驱动,还是某段循环里。
按需诊断:就是平时不把重型工具全开,只有发现异常时,才对特定服务、接口、用户、实例或时间段加大观察力度。它像机场安检,平时大家正常过闸,只有出现异常包裹时才开箱细查。比如只有某批用户的请求持续变慢,那么就只对这部分请求临时打开更细的上下文和日志,而不是把全站都切到重诊断模式。
为什么“看得越全”反而可能让系统更慢?
全量 Trace 的直觉很美好:每个请求都留下完整轨迹,问题一来就能回放现场。可在高QPS下,它往往会带来四笔账。
第一笔是计算账。每次请求都要生成链路片段、补充标签、串联上下文、整理后再上报。单次看着不重,乘上每秒成百上千甚至更多请求后,就开始真吃 CPU 了。
第二笔是内存和网络账。数据要先在本地缓冲,再发到观测平台。流量一大,内存顶着,网络也跟着忙,像本来就拥挤的收费站,旁边又加了一条“每辆车都得拍八张照”的流程。
第三笔是存储和检索账。Trace 数据量很大,保存、检索、查询都要钱。你以为只是“多记点信息”,实际上是在给自己养一个同样能吞资源的旁路系统。
第四笔是连锁反应。观测系统本身也可能成为瓶颈。一旦它卡顿,上报线程阻塞、缓冲堆积,主业务链路也可能被拖慢。监控本来是来救火的,别最后自己成了烟雾制造机。
所以,高QPS场景下常见的优化思想不是“关掉观测性”,而是“把常驻观测做轻,把深度观测做准”。不是彻底少看,而是分层看、按证据加码看。
平时怎么看,出事时怎么看?
请求进入
-> 先看基础指标(QPS、错误率、延迟)
-> 正常:保留低比例采样 Trace
-> 出现错误或慢请求:提高关键接口采样,错误请求尽量全留
-> 仍看不清:短时开启低频 Profiling
-> 还不够:对指定接口 / 用户 / 实例开启按需诊断
-> 定位原因后关闭重型诊断,回到轻量常态
这张流程图的意思是:高QPS系统应该先用轻量手段守住全局,再按异常逐级加码;你接下来可以先把团队现有观测手段分成“常驻”和“临时”两类。
三种常见手段,到底各自看什么?
先说结论:采样 Trace 看“路走得对不对”,Profiling 看“力花在哪儿”,按需诊断看“这次到底是谁干的”。它们不是替代关系,更像三把不同尺寸的扳手。
| 手段 | 最适合看什么 | 优点 | 代价 | 适合什么时候先用 |
|---|---|---|---|---|
| 全量 Trace | 每个请求的完整链路 | 细节最全,回放最方便 | 开销最高,最容易拖慢高QPS服务 | 低流量系统、关键少量交易 |
| 采样 Trace | 整体调用路径、慢请求趋势、错误分布 | 开销低很多,能保住全局视角 | 会漏掉未采样到的个别请求 | 高频在线服务的日常观察 |
| 低频 Profiling | CPU、内存、锁、热点函数 | 找资源瓶颈很准 | 持续全开也有成本,不适合长时间重度开启 | 资源异常、性能抖动时 |
| 按需诊断 | 某个接口、用户、实例、时间段的细节 | 聚焦问题,投入最省 | 需要先发现异常线索,平时看不到全部 | 已经怀疑到局部目标时 |
这张表说明:不同工具看的角度不同,别拿锤子当手术刀;你接下来应该先为每种工具定义一个明确的触发条件。
具体到做法,很多团队会这样搭配:
-
日常默认:基础指标全量保留,Trace 只采样一小部分。
-
关键异常兜底:错误请求、超慢请求、关键交易链路尽量提高保留率,甚至局部全量。
-
定时体检:每隔一段时间做一次短时 Profiling,而不是全天候重型体检。
-
出事加码:只有在报警、投诉、抖动出现时,才对目标范围临时开更细的诊断。
这就像医院分诊。平时先量体温、测血压;如果发现异常,再抽血、拍片、做更深检查。没人会让所有人一进门就先做全套核磁,那样医生和病人都会先累坏。
一个初学者也能照着走的排查流程
假设你维护的是一个订单服务。午高峰到了,创建订单 接口里最慢那一小撮请求的耗时,也就是常说的 P99 延迟,从 180ms 涨到 480ms,但错误率没有明显上升。你可以按下面的顺序走。
第 1 步:先看大盘,不要一上来就掀天花板
先看基础指标:QPS 有没有暴涨,CPU 有没有打满,数据库连接数是否逼近上限,只有某一个接口慢,还是整站一起慢。这个阶段你要的是方向感,不是所有细节。
第 2 步:把关键路径的 Trace 采样提上去
平时订单链路可能只保留 1% 的 Trace。现在接口变慢了,就把 创建订单 这条链路短时间提到 10% 或 20%,同时把超过阈值的慢请求尽量都保留下来。这样你就能看到大多数时间是不是耗在库存、优惠券、支付网关,还是某个内部服务调用。
第 3 步:如果怀疑资源问题,再开一小段 Profiling
如果链路上看不出明显外部等待,而机器 CPU 又在上升,就做一小段 Profiling。目的不是长期盯,而是回答一个具体问题:CPU 时间到底烧在谁身上。
第 4 步:如果还是不够,再做按需诊断
假如只有某个客户账号、某一批用户、某几台实例出问题,就对这部分流量临时打开更细的诊断信息,比如更完整的上下文、额外标签,或者只针对目标请求的详细日志。范围越小,成本越可控。
12:00 午高峰开始
12:03 延迟告警触发
12:04 看基础指标,发现只有 创建订单 变慢
12:05 将该接口 Trace 采样从 1% 提到 20%,慢请求尽量全留
12:07 发现时间主要耗在 优惠券服务 调用
12:08 开 30 秒 Profiling,确认 CPU 不是主因
12:09 对异常用户流量开启按需诊断
12:11 发现优惠券服务在特定活动下重试过多
12:15 调整重试策略,延迟回落
这条时间线说明:排障不是一开始就把所有诊断都开满,而是随着证据增多逐步升级;你接下来可以把这个升级顺序写成团队的排障手册。
如果你想把它落成一套“可复制”的默认策略,可以先从这个简化版开始:
-
基础指标全量保留。
-
普通请求只做低比例 Trace 采样。
-
错误请求和超慢请求提高保留率。
-
每隔一段时间做一次短时 Profiling。
-
报警触发后,只对目标接口、实例、用户群临时开启按需诊断。
-
故障结束后,把加码手段及时关回去。
很多初学者容易卡在第 2 步:总觉得“不全量记录就不安心”。其实线上系统最怕的不是“信息不够豪华”,而是“服务先被观测成本压趴”。先活下来,再看清楚,这才是在线服务的思路。
这样做会失去什么?代价必须说清楚
说它是“用可观测性换性能”,就要承认它真的有损失,而且不是小数点后的损失。
第一个代价是诊断粒度下降。不是每个请求都被完整记录,所以某个倒霉请求如果正好没采到,你事后就看不到它的全链路。
第二个代价是复现场景变少。很多偶发问题本来就像捉迷藏:只在特定用户、特定参数、特定时间窗口里出现。全量 Trace 时,你更容易留住现场;改成采样后,它可能刚好从网眼里溜过去。
第三个代价是排查步骤变长。以前可能一条完整 Trace 就能看出问题,现在往往要先看指标,再提采样,再开 Profiling,再做按需诊断。它更像侦探破案,不是一次性翻到底牌。
所以,真正成熟的做法不是“采样了就听天由命”,而是给采样加护栏:
| 场景 | 建议优先策略 | 为什么 |
|---|---|---|
| 日常高QPS稳定运行 | 低比例采样 Trace + 低频 Profiling | 先把常驻开销压住 |
| 错误率上升 | 错误请求尽量全留,关键链路提采样 | 问题样本先别丢 |
| 慢请求增多 | 慢请求提高保留率,必要时开 Profiling | 先分清是等待还是算力问题 |
| 单个用户或某个客户账号投诉 | 按需诊断最优先 | 问题范围小,适合精准打光 |
| 支付、扣款、审计等高价值链路 | 局部更高保留率,必要时局部全量 | 这些地方丢现场的代价更大 |
这张矩阵说明:不是所有流量都该一视同仁;你接下来应该先把“高价值链路”和“普通链路”分开设策略。
再强调一句:全量 Trace 不是原罪,采样也不是银弹。真正要避免的是两个极端。
一个极端是“什么都记”,最后把线上系统和观测系统一起卷进高负载。另一个极端是“什么都省”,结果出了事只剩一句“好像是哪里慢了”。靠谱的做法,是把精力花在最值钱的地方:关键请求尽量多看,普通请求适度抽看,异常时快速放大看。
什么时候别太省观测成本?
如果你维护的是支付扣款、风控判定、审计留痕这类高价值链路,就不能机械地套“全部采样化”。因为这些场景里,丢一条关键现场的代价,可能比多花一些性能更大。
另外,在大版本发布、数据库迁移、流量切换、促销活动开始前后,也常常需要临时提高观测密度。原因很简单:这时候系统最容易冒出新问题,而新问题最怕“刚好没留证据”。
你可以把这条经验记成一句话:稳定期追求轻量,变更期追求证据,关键链路追求确定性。别一套策略打全年。
最后把它记成 5 句能落地的话
-
先
区分常驻观测和临时诊断,别把所有重型工具一直挂在线上。 -
先
选择低比例采样 Trace 守住全局,再用错误请求和慢请求做重点保留。 -
定期
测量观测本身的 CPU、内存、网络、存储开销,别只盯业务指标。 -
遇到异常时按“指标 -> 提采样 -> Profiling -> 按需诊断”的顺序
升级,不要第一步就全开。 -
对支付、审计、关键交易链路单独
验证是否需要更高保留率,别把所有接口都按同一把尺子量。
如果只记一句,那就记这句:高QPS在线服务里,观测性的目标不是“看得最多”,而是“在不压垮系统的前提下,尽快看到最关键的证据”。