阿茶在城里开了一家奶茶店「阿茶手作」。每天打烊后,他都会翻一遍小票:从顾客下单到出杯,一共等了多久。第一个月他算了下平均等待时间——4分钟,挺满意。直到有天他撞见一位老顾客足足等了18分钟,而那天恰好有人一口气点了60杯。阿茶这才明白:平均值会骗人。一杯大单把平均数拉高了,可绝大多数人的真实体验其实没那么糟;而少数人糟透了的体验,平均值也救不回来。 这个故事,就是 LLM 应用延迟监控的第一课。ChatGPT 这类服务每秒处理成千上万个请求,每个请求的耗时天差地别:有的 200 毫秒就回了,有的要 8 秒。我们真正关心的不是“平均快不快”,而是“绝大多数人多快”和“最差的那批有多差”——这正是 P50、P95、P99 分位数回答的问题。沿着阿茶的经营之路,我们将依次学会:分位数为什么比均值可靠、延迟数据怎么采集、滑动窗口怎么滚动、SLO 怎么定、告警怎么分级、长尾怎么查、最后怎么把最慢的那杯茶也做快。这是一套从测量到治理的完整闭环。
掌握延迟分位数监控与 SLO 告警实战,是 LLM 应用质量保障的核心技能——它能让你从“系统好像慢了”的模糊感知,进阶到“P99 突破 500ms、燃烧率 2 倍、该扩容了”的精准决策,这正是高级 MLOps 与 SRE 工程师的日常。
可视化演示
展示延迟分布直方图、滑动窗口分位数估计及SLO多级告警策略,P50/P95/P99实时追踪。
本节配有交互动效(进入视口后自动加载,约 3KB)。
延迟分布直方图 P50中位数反映典型延迟水平 P95捕获长尾95%请求延迟 P99极端值暴露尾部异常
分位数基础:均值会骗人
阿茶翻了一个月的小票,算出平均等待时间是 4 分钟,正想奖励自己。但一位熟客的话让他惊醒:“我上周等了 18 分钟。”原来那天有人一下点了 60 杯,整个操作台都堵住了。阿茶重新一算:其实九成的单子都在 3 分钟内出杯了,全是那笔大单把平均数拉上去的。他第一次意识到,平均值是会被少数极端值绑架的。
LLM 服务一模一样。普通问题 300 毫秒就返回,可一个携带 20 万字超长上下文的请求可能要跑 8 秒;偶尔一次上游 API 重试,也能让单个请求慢到 20 秒。这些极端值就像那笔 60 杯的大单,把“平均延迟”拽到完全不可信的位置。何况 LLM 里长尾请求占比并不低:采样、重试、排队、长上下文生成,都会制造“少数慢请求”。所以工程师们改用一种“排队看位置”的指标——分位数。
把 n 个延迟样本从小到大排成一列,第 p 百分位就是“排在 p×n 位置的那个值”。P50 也叫中位数:一半请求比它快,一半比它慢,代表典型体感。P95 表示 95% 的请求都不超过它;P99 则覆盖 99%,几乎是“最差一批”的边界。一条慢到离谱的请求,最多只把 P99 往后挪一点点,却能把平均值拽上天——这就是分位数抗干扰的秘密。
从此阿茶的报表上多了三行:P50、P95、P99。他不再盯着那个“平均 4 分钟”自我安慰,而是看“第 95 杯茶几分钟出的、最慢的 1% 到底有多慢”。这才是顾客真实的体感。
- 排序 sorted把 n 个样本从小到大排成一列,这是分位数的地基,顺序一旦错了全盘皆输。
- 定位 p × n用分位点 p(如 0.99)乘以样本总数 n,算出要盯的队伍位置。
- 上取整 ⌈⌉位置不能是小数,向上取整保证落点合法不越界。
- 减 1 做下标程序里的数组从 0 开始计数,所以第 k 个位置对应下标 k−1。
延迟数据采集
阿茶决定升级小店:每张小票上打印下单时间,出杯时再打一次出杯时间。他特意嘱咐店员,收银机必须联网对时,谁手动记、记晚了,当天报表就是废纸。计量不准,管理就无从谈起——奶茶店如此,LLM 服务更是如此。
在 LLM 应用里,“下单时间”就是请求到达网关的时刻(t_start),“出杯时间”就是完整响应返回的时刻(t_end)。两者相减,得到端到端延迟。对流式输出来说,还要额外记录“首 Token 延迟”(TTFT):用户看到第一个字蹦出来的时刻,决定了他感觉“有没有开始干活”。采集时要注意几件事:埋点要携带上下文(trace_id、用户、模型、prompt 模板版本),方便事后回查;采样策略要倾向尾部——对 P99 监控来说,慢请求恰恰是最珍贵的样本,不能简单“每 10 条抽 1 条”把它漏掉;时间戳要统一规范,服务端用单调时钟避免 NTP 跳变造成负数延迟。整套链路(网关 → 模型服务 → 检索 → 工具调用)用同一个 trace_id 串起来,就像一张小票把收银、制茶、出杯全部打通。
阿茶的小票系统上线后,他第一次能回答“昨天下午茶高峰到底慢在了哪个环节”。有了这只“精准的秒表”,后面所有的统计与告警才算有了地基。
- 起点 t_start用户请求真正到达服务端的那一刻,对应奶茶店的收银机打单时间。
- 终点 t_end响应完整返回(或首个 Token 返回)的那一刻,对应顾客拿到奶茶。
- 作差得总耗时终点减起点,就是这一次请求从头到尾的耗时。
滑动窗口统计
阿茶没有把一万张小票永远压在抽屉里,而是在收银台上放了一块白板,只记录最近一小时的出杯时间。每过一分钟,就擦掉一小时前那批旧记录,补上新数据。白板上的数字永远代表“当下店里的真实状态”——三小时前有多闲,对现在的顾客毫无意义。
这就是滑动窗口的直觉:分位数统计只在最近一段时间窗内进行。窗口用当前时刻 t 和长度 Δ 来定义,凡是时间戳落在 (t−Δ, t] 之间的样本都算数,更早的自动淘汰。窗口每滚动一次,就丢掉最旧的样本、纳入最新的样本。它的好处有二:一是语义正确——只反映近期状态,不会被上周的老数据稀释;二是内存有界——窗口大小固定,不随请求总量无限膨胀。
难点在于“在线求分位数”。朴素做法是把窗口内所有样本全量排序,但窗口里可能躺着几十万条记录,每秒都在重排,谁也扛不住。工程上常用两类近似方案:HDR 直方图把延迟按量级分桶,每个桶只记一个计数,内存恒定;t-digest 用一堆“质心簇”勾勒分布形状,精度高且支持流式合并。它们牺牲微小精度,换来了实时性与可控内存——对告警判断来说完全够用。
阿茶的白板每隔 30 秒就更新一次,永远呈现“最近一小时”的出杯分布。他笑着说:这白板就像店里的脉搏,跳得正常不正常,扫一眼就知道。
- 窗口符号 W(t,Δ)t 是当前时刻,Δ 是窗口长度,这个记号表示“此刻往前数 Δ 的一段时间”。
- 样本与时间戳每个延迟样本 x_i 都带着自己的时间戳 ts_i,相当于每张小票都盖了章。
- 区间过滤只保留满足 t−Δ < ts_i ≤ t 的样本,右侧闭区间保证“当前这一刻”的新数据能进来。
SLO目标设定
阿茶在门口挂了一块招牌:「99% 的奶茶 5 分钟内出杯,超出免单」。这个承诺一挂,他心里开始盘算:按每天 1000 杯算,一个月 3 万杯,最多只能有 300 杯超时。为了守住这个数,他得提前备料、高峰加人。这个招牌,就是奶茶界的 SLO。
SLO(Service Level Objective,服务等级目标)是把“用户体验”翻译成可量化的延迟指标:比如「P99 延迟 ≤ 500ms,且每月满足率达到 99%」。定 SLO 不是拍脑袋:先定义清楚目标(P99 还是 P95?总延迟还是首 Token?),再分配延迟预算——一次请求从网关到模型到检索,各段分到多少毫秒,串起来不能超过总目标。最后还要持续校准:业务要求苛刻(比如支付风控)就收紧,内部闲聊机器人就放宽。SLO 太松,用户骂;太紧,团队天天救火。
有了 SLO,就自然有了“错误预算”:允许不达标的那部分次数。月请求量 N 乘以 (1−SLO),就是本周期最多能容忍的“破功”次数。预算烧完之前可以大胆上线新功能;预算一旦见底,就停掉所有非核心变更、全力保稳定。错误预算把“质量”变成了像奶茶原料一样可量化的库存。
阿茶的“免单预算”一个月就 300 杯。他规定:预算还有富余时,可以试新配方;一旦快用完了,马上停掉所有试验,全员回归标准流程。SLO 让“服务好坏”第一次有了可以精打细算的账本。
- 总请求量 N一个统计周期内的请求总数,比如月请求 1000 万次。
- 容错比例 1 − SLOSLO 承诺 99%,就允许 1% 的不达标。
- 相乘得预算两者相乘,得到本周期最大可容忍的失误次数。
多级告警策略
阿茶明白,不能因为一杯茶慢了就敲锣打鼓——那会让店员彻底麻木。他在操作间装了三盏灯:黄灯代表 P50 连续 5 分钟超过 3 分钟,前台多看两眼;橙灯代表 P95 连续 5 分钟超过 4 分钟,店长去操作台盯着;红灯代表 P99 连续 10 分钟超过 5 分钟,全体停下手里杂活,全力保出杯。灯的颜色和持续时间,比“响铃”本身更重要。
这背后是告警阈值设计的核心原则:阈值必须分级,且必须配合“持续窗口”判定,单次瞬时超标大概率是噪声,连续多个窗口超标才是真故障。工程上常分三级:警告(P50 恶化,公司内部群)、严重(P95 超 SLO,短信 + 值班)、紧急(P99 超 SLO 且持续 10 分钟,电话 + 升级)。同时要做告警抑制:同一故障在冷却期内只报一次,不重复刷屏;维护窗口内静默;故障恢复自动关闭。若红灯持续 15 分钟未恢复,则自动升级到第二梯队甚至值班主管——这就是告警升级。
判断“是否烧得太快”有一个利器——燃烧率(burn rate):当前实际错误率除以允许的错误率。SLO 是 99%,允许错误率 1%;如果某窗口实际错误率是 2%,燃烧率就是 2,说明预算消耗速度是计划的 2 倍。燃烧率连续 1 小时大于 1,就值得立即处理。
阿茶的店从此安静了很多:黄灯亮起时大家心里有数,红灯亮起时全员肃然。没有人再被无关紧要的慢单子消耗注意力——因为灯光的“级别、持续时长、升级路径”,已经替他们把轻重缓急安排得明明白白。
- 实际错误率 error_rate当前窗口内不达标请求的比例,比如 2%。
- 允许错误率分母SLO 允许的失败比例,99% SLO 对应 1%。
- 相除得比值实际错误率是允许值的几倍,就是几倍的燃烧速度。
长尾根因分析
红灯亮了。阿茶没有冲到操作台乱吼,而是翻出最慢那批小票做对比:收银机打单慢了?新来的店员手生?还是珍珠供货商这次送来的珍珠煮不透?他一查发现,九成慢单都有一个共同点:都点了“黑糖珍珠”。别的环节都正常,问题就出在珍珠上。这就是长尾根因分析:把最慢的 1% 拎出来,和普通单子逐段对比,找出差异最大的环节。
LLM 服务同样要拆开看。把一次请求切成网关、模型、检索、上游四段,分别计时,然后做两组对比:一组是 P99 慢样本的分段均值,一组是 P50 正常样本的分段均值。哪个段的差值最大,嫌疑人就是谁。比完数值再上火焰图:把慢请求的调用栈按时间堆叠,一眼就能看到时间堆在哪一层——是模型推理占了大头,还是向量检索在反复重试。最后配一条 Trace 样本:抽几条最慢的链路和最快的链路逐行对比,查排队、重试、上下文长度这些“隐藏变量”。排查顺序也有讲究:先外后内、先网络后计算——客户端超时、网关排队、GC 停顿、上游限流,逐层排除,不要一上来就怀疑模型本身。
阿茶找到了:问题就在“珍珠”这道工序上——对应到 LLM 里,就是向量检索环节。他换了更快的原料商,并给这道工序单独加了监控。长尾的根因,就这样被“分段对比”这盏探照灯照了出来。
- 拆分四段一次请求被拆成网关、模型、检索、上游四个可计时的台阶。
- 求和得总量各段耗时加起来就是端到端总延迟。
- 对比得出差异分别取 P99 样本与 P50 样本的分段均值,差值最大的段即最大嫌疑。
长尾延迟优化
根因找到了,接下来是动手治。阿茶一口气做了四件事:热门款提前备好(黑糖珍珠早上就煮两锅放着,来了直接舀)——对应 LLM 里的语义缓存,重复的 prompt 直接命中缓存,省掉一次完整生成;大单排队不挡小单(60 杯的团购单独排一条队,不占用普通顾客的出杯通道)——对应并发与排队控制,限制单请求最大排队时间,避免队头阻塞;换了一口更快的高压锅——对应模型量化,INT8 推理比 FP16 快一截,精度损失可控;先上第一口(奶茶做好前先让顾客喝一口试饮,感觉“已经开始了”)——对应流式输出,首 Token 快速返回,用户体感大幅改善,虽然总耗时的 P99 还是照实统计。
优化的靶心要清楚:平均延迟降低很容易,难的是把 P99 甚至 P99.9 压下来。缓存是对付长尾的利器——命中缓存的请求可能只要几十毫秒,未命中则要几百毫秒,命中率越高,整体分布越往左移。评估缓存收益有一个简单的加权公式:平均延迟 = 命中率 × 命中延迟 + 未命中率 × 未命中延迟。把这个公式拆开看,就能算出“把命中率从 60% 提到 80%”到底能省多少毫秒,值不值得投入。
三个月后,阿茶的招牌依然挂着,但红灯几乎没再亮过。他用一句话总结了这整套打法:先测准(分位数),再承诺(SLO),盯警报(多级告警),查到底(根因分析),治根子(优化)——然后回到第一步,继续测。监控不是一次性工程,而是一个不断转动的飞轮。
- 命中率 h缓存命中比例,取值 0 到 1 之间,是优化杠杆的核心旋钮。
- 两条路径延迟L_cache 是命中缓存的快路径,L_miss 是回源计算的慢路径。
- 加权平均两条路径按命中率加权求和,得到整体平均延迟。
AI 应用场景
ChatBot 首 Token 延迟实时监控与告警
阶段:监控与告警
解决的问题:传统方式只能靠用户投诉“机器人回得慢”来事后感知,无法主动发现体验劣化。AI 方式在 Langfuse/Phoenix 等平台埋点,实时统计首 Token 延迟的 P50/P95/P99,当 P99 连续 5 个窗口超过 SLO 阈值(如 500ms)时自动告警,并在燃烧率超 1 时触发扩容流程。
具体案例:某客服 ChatBot 上线后,监控面板显示 P50 稳定在 200ms,但 P99 从 600ms 爬升到 1.2s。告警触发后,SRE 通过 Trace 定位到是某次模型版本升级导致长上下文首 Token 变慢,立即回滚版本,P99 恢复。
RAG 系统分阶段 P99 定位长尾
阶段:根因分析
解决的问题:RAG 链路包含检索与生成两大阶段,延迟问题容易被“总延迟”掩盖。AI 方式按“网关→向量检索→重排→LLM 生成”分段埋点,对比 P99 慢样本与 P50 正常样本的分段耗时差异,快速定位长尾出在检索还是生成。
具体案例:某知识库问答系统 P99 突然恶化,分段对比发现检索阶段均值从 80ms 涨到 900ms,进一步火焰图显示是 Embedding 模型在大量并发下排队。通过给检索服务增加副本并开启结果缓存,P99 回落到 180ms。
大模型网关多租户 SLO 治理
阶段:SLO 治理
解决的问题:不同业务线共用一个大模型网关,需求差异巨大:搜索场景要求 P99 < 300ms,闲聊机器人可以接受 2s。统一一个阈值必然顾此失彼。AI 方式按租户分别设定 SLO 与错误预算,预算消耗快的租户自动限流降级,预算充足的租户可享更高优先级。
具体案例:某公司网关为 12 个业务线配置了独立 SLO。一次大促中,营销活动的 P99 燃烧率飙到 4,系统自动限制其并发额度,保住搜索和支付等高优链路,整体可用性未受影响。
Python 演示
import randomfrom collections import deque def gen_latency_batch(n, base=120, tail_rate=0.04, tail_extra=400): """生成一批 LLM 推理延迟样本,base 是常规延迟,tail 是长尾异常。""" samples = [] for _ in range(n): v = base + random.expovariate(1 / 45) if random.random() < tail_rate: v += tail_extra * (1 + random.random()) samples.append(v) return samples def percentile(sorted_samples, p): """在已排序样本上取 p 分位数。""" idx = int(p * len(sorted_samples)) return sorted_samples[min(idx, len(sorted_samples) - 1)] def sliding_pctl(frames, window=30): """对连续帧做滑动窗口分位数统计,返回每帧的 P50/P95/P99。""" window_buf = deque() rows = [] for frame in frames: window_buf.append(sorted(frame)) if len(window_buf) > window: window_buf.popleft() merged = sorted(x for buf in window_buf for x in buf) rows.append(( percentile(merged, 0.50), percentile(merged, 0.95), percentile(merged, 0.99), )) return rows def evaluate_slo(rows, p99_limit=600, min_over=3): """P99 连续超过阈值 min_over 个窗口才告警,避免单次抖动误报。""" over_count = 0 for i, (_, _, p99) in enumerate(rows): if p99 > p99_limit: over_count += 1 if over_count >= min_over: print(f"[告警] 第{i}个窗口 P99={p99:.0f}ms 连续超标") else: over_count = 0 if __name__ == "__main__": random.seed(2024) frames = [gen_latency_batch(400) for _ in range(90)] rows = sliding_pctl(frames, window=30) evaluate_slo(rows) p50, p95, p99 = rows[-1] print(f"最终窗口 P50={p50:.0f}ms P95={p95:.0f}ms P99={p99:.0f}ms")
v = base + random.expovariate(1 / 45)用指数分布模拟大多数请求的常规延迟,符合“短延迟居多”的真实形态。if random.random() < tail_rate: v += tail_extra * (1 + random.random())小概率叠加长尾增量,制造出“少数慢请求”。idx = int(p * len(sorted_samples))计算分位数对应的数组下标,是公式⌈p×n⌉−1的代码实现。window_buf.append(sorted(frame))每帧样本排序后推入窗口缓冲区。if len(window_buf) > window: window_buf.popleft()窗口满了就丢弃最旧一帧,完成滚动更新。merged = sorted(x for buf in window_buf for x in buf)合并窗口内所有帧的样本,作为当前窗口的统计基础。if over_count >= min_over:连续多个窗口超标才触发告警,过滤单窗口抖动的噪声。
常见误区
误区我看到监控面板上写着 P99=500ms,心想“天哪,99% 的请求都要等 500ms?那用户体验也太差了。”于是拿着这个结论去找开发吵架。
正解P99 是一个边界值:99% 的请求耗时都 ≤ 500ms,剩下 1% 比 500ms 更慢。绝大多数请求其实远快于 500ms,就像奶茶店说“99% 的茶 5 分钟内出杯”,不代表大家都正好等了 5 分钟,而是绝大多数 3 分钟就拿到了。P99 描述的是“最差那批人的门槛”,不是“所有人的常态”。
为何常见:分位数名字里带个“99“,直觉上容易把它理解成”99 个样本都等于这个值“,忽略了它只是”排队位置”上的单点取值。
误区我把 P99 告警阈值设成 200ms,心想“宁可错杀一千,不可放过一个”,结果一天收到 200 条告警,群里的告警机器人成了最吵的成员,到第三天没人看了。
正解告警噪声本身就是事故。阈值应该分层:P50 黄灯观察、P95 橙灯注意、P99 红灯必处理,而且每条告警都要加“连续 N 个窗口超标”的判定条件。阈值低 + 无持续条件 = 告警风暴 = 值班疲劳 = 真故障被淹没。
为何常见:出于“小心驶得万年船”的心态,只看到了“发现得快”,没算“误报的代价”。告警系统的目标不是多报警,而是每次报警都有价值。
误区我觉得滑动窗口把从上线到现在的所有延迟样本都存下来,每次统计全量排序,这样 P99 最精确,为什么还要搞什么 HDR 直方图和 t-digest?
正解全量保留意味着内存随请求量无限增长,排序耗时越来越长,最终监控系统比业务系统还吃资源。滑动窗口的哲学恰恰是“旧数据不值钱”——上周的延迟对判断当下的服务状态毫无意义。HDR 直方图和 t-digest 用固定内存换微小精度损失,实时性和准确性都够用。
为何常见:把“监控统计”误当成“离线数据分析”,追求理论上的精确,忽略了在线场景对时效和资源的要求。
误区我看到 P99=450ms,低于 500ms 的 SLO,长舒一口气:“用户体感肯定没问题,可以回家睡觉了。”
正解P99 只覆盖 99% 的请求,剩下 1% 可能是 5 秒、10 秒甚至超时——而这 1% 往往是高价值大客户或超长上下文的复杂请求。另外 P50 决定多数人的体感,P99.9 兜底极端场景。正确姿势是组合看:P50 看典型、P95/P99 看长尾、错误预看守不守得住,再配合趋势变化判断是否恶化。
为何常见:单一指标思维,以为一个数字就能代表全部质量。监控系统的成熟度,恰恰体现在“用多个维度互相对照”。
面试题
Q1. 某 LLM 接口 P99=800ms,最准确的理解是?
- A.所有请求平均耗时 800 毫秒
- B.99% 请求不高于 800 毫秒← 正确答案
- C.1% 请求耗时恰为 800 毫秒
- D.峰值延迟等于 800 毫秒
答案:B。P99 是排序后第 99% 位置的边界值,表示“99% 的请求耗时不超过 800ms”,剩下 1% 比 800ms 更慢,而不是所有请求都正好 800ms。就像奶茶店说“99% 的茶 5 分钟内出杯”,绝大多数其实更快。
Q2. 为什么要用分位数而不用平均值监控延迟?
- A.平均值计算过程耗时太长
- B.平均值会被长尾请求拉偏← 正确答案
- C.平均值无法存储到数据库
- D.平均值没有统一时间单位
答案:B。平均值是“总时间 ÷ 总请求数”,一笔超大请求就能把均值拽高,掩盖大多数用户的良好体验。分位数按队伍位置取值,天然抗干扰:P50 反映典型体感,P99 反映长尾风险。
Q3. LLM 流式会话的端到端延迟应如何定义?
- A.从请求发起到首 Token 返回← 正确答案
- B.从代码编译到部署完成
- C.从模型加载到模型退出
- D.从日志打印到存储落盘
答案:A。LLM 流式场景的关键体验是“多久开始说话”,因此端到端延迟通常定义为从请求发出到首个 Token 返回(TTFT),总耗时则到完整响应结束。B/C/D 都在请求生命周期之外,不构成用户可感知的延迟。
Q4. 样本数 n=1000,求 P95 应取排序后第几个?
- A.第 95 个样本的数值
- B.第 950 个样本的数值← 正确答案
- C.第 990 个样本的数值
- D.第 500 个样本的数值
答案:B。P95 的位置是 ⌈0.95×1000⌉=950,即排序后第 950 个样本的值。第 95 个接近 P10,第 990 个接近 P99,第 500 个就是 P50。做题要先算位置再取值。
Q5. 滑动窗口统计相比全量累计统计的优势是?
- A.保证历史数据永不丢失
- B.关注最近数据且内存有界← 正确答案
- C.无需记录任何请求时间
- D.可以精确统计所有异常
答案:B。滑动窗口只保留最近 Δ 时间内的样本,窗口大小固定、内存有界,且天然聚焦“当前状态”。A 恰恰相反——旧数据会被丢弃;C 违背了统计前提;D 说“精确统计所有异常”不现实,滑动窗口通常搭配近似分位数。
Q6. 告警抑制(dedupe)解决的主要问题是?
- A.同一故障反复刷屏扰人← 正确答案
- B.告警阈值设置太高了
- C.监控数据采集不过来
- D.日志文件写入太频繁
答案:A。告警抑制解决“同一故障反复刷屏”:一条 P99 超限告警发出后,在冷却期内相同条件不再重复发,只更新状态。B/C/D 分别是阈值、采集、日志问题,与去重无关。
Q7. 哪些因素会让 P99 明显恶化而 P50 变化不大?
- A.偶发的 GC 停顿和重试← 正确答案
- B.个别节点网络重传← 正确答案
- C.全量请求平均提速 20%
- D.少量超大上下文请求← 正确答案
答案:ABD。P99 只看最慢的 1%,偶发 GC 停顿、网络重传、超大上下文这类“少数派”很容易把 P99 打高,却完全不影响 P50。C 让所有请求都快 20%,P50 和 P99 都会下降,不符合“P99 恶化 P50 不变”的条件。
Q8. SLO=99.9%,某 5 分钟窗口内错误率=0.6%,燃烧率为?
- A.0.6 倍——消耗速度很慢
- B.6 倍——预算消耗过快← 正确答案
- C.1.02 倍——速度基本正常
- D.0.066 倍——无需处理
答案:B。燃烧率 = 实际错误率 ÷ 允许错误率 = 0.6% ÷ (1−99.9%) = 0.6% ÷ 0.1% = 6 倍。燃烧率 6 意味着错误预算消耗速度是计划的 6 倍,必须立即介入。A/C/D 都没有正确理解燃烧率的除法关系。
Q9. 适合流式滑动窗口近似分位数的方案有?
- A.t-digest 分布估计← 正确答案
- B.HDR 直方图分桶← 正确答案
- C.全量排序后取下标
- D.用平均值代替 P99
答案:AB。t-digest 用质心簇近似分布,HDR 直方图按桶累积计数,两者都只需固定内存、支持流式更新。C 全量排序在滑动窗口场景下内存和时间都扛不住;D 用均值代替 P99 恰恰丢掉了长尾信息。
Q10. 错误预算已消耗过半,合理的应对措施有?
- A.暂停非核心功能的发布← 正确答案
- B.主动扩容提升冗余容量← 正确答案
- C.把 SLO 改为更宽松的值
- D.关闭全部监控与告警
答案:AB。错误预算过半说明“本月允许的失误”快花完了,此时应暂停非核心发布、扩容保冗余,把预算省给核心流量。C 临时放宽 SLO 等于自欺欺人,掩盖了真实质量;D 关闭监控会让问题的雪球越滚越大。