问题与范围
讨论单请求延迟分布、并发请求的组合效应和服务级目标。默认 API 每分钟处理 10 万次请求,平均 80 毫秒,p95 为 180 毫秒,p99 为 2 秒。数字是面试假设,不是行业基准。重点是推理和验证,不要求提出具体厂商工具。
面试官在考察什么
面试官想看你是否理解平均值只描述总量,不描述分布形状。尾部请求可能集中在某个租户、路由、依赖、区域、请求大小或重试路径。好的回答会区分测量窗口、聚合维度、客户端体验和服务端原因,并把指标连接到可执行的 SLO。
回答前要澄清的问题
- 延迟是从客户端发出到收到首字节,还是到完整响应?
- p99 是按单个实例、路由、区域还是全服务计算?窗口多长?
- 是否包含超时、取消、重试和缓存命中?
- 请求大小、租户、依赖调用和错误率是否随尾部变化?
- 目标是降低所有请求,还是保证关键路径的尾部预算?
30 秒回答框架
“平均 80 毫秒并不表示所有请求都接近 80 毫秒;p99 为 2 秒说明最慢 1% 仍会显著影响用户和上游超时。先固定测量定义和窗口,按路由、区域、实例、租户、请求大小和依赖分解分布。再查看队列、连接池、GC、磁盘、锁、下游和重试。改进应针对瓶颈:有界队列、合理超时、批量或缓存、减少串行依赖、隔离噪声租户,并以 p95/p99 SLO 和错误预算验证回归。”
分步深入设计
先定义观测点:客户端总耗时、边缘到服务、服务处理时间、下游等待和响应传输。明确是否使用首字节或完整响应,统一单调时钟和采样规则。把超时与取消单独计数;把重试请求与原始请求关联,避免一次用户操作被算成多个独立成功。
百分位必须基于请求样本分布,不能先对实例 p99 求平均。按路由、状态码、区域、实例、租户、请求大小和依赖绘制分位数与样本量。窗口太小会抖动,窗口太大又会掩盖发布后的回归;同时展示短窗口告警和长窗口 SLO。
组合请求会放大尾部。若一个页面串行调用多个服务,总延迟接近各阶段之和;并行调用时,只要一个子请求慢,整体延迟就接近最大值。为每个阶段分配预算,记录 trace span,并识别扇出数量。不能用单服务平均值推断端到端体验。
定位时先看相关性而非猜测:队列年龄上升表示排队或容量问题;连接池等待表示并发边界;GC、磁盘和 CPU 抖动可能形成长尾;单个下游 p99 变差会传导到上游。比较成功与超时样本的请求属性,并用受控采样保留慢请求上下文。
改进措施应匹配原因。减少串行依赖、使用缓存或批量可降低固定开销;有界并发、背压和租户隔离可阻止拥塞扩散;合理的超时和有限重试避免重试风暴;请求拆分或异步化可把不可控工作移出同步路径。尾延迟改善不能靠无限增加线程或盲目加副本。
SLO 用“合格请求占比”表达用户体验,例如 99.9% 的有效请求在 300 毫秒内完成。错误预算把延迟违约与错误放在同一决策框架。SLO 必须标明入口、状态码、缓存语义和时间窗口;若只对平均值设目标,系统可能在平均值稳定时持续伤害最慢用户。
发布和故障演练要验证分布变化。比较版本前后的 p50、p95、p99、最大值、超时率和样本量;向特定依赖注入延迟,观察尾部是否按预期扩大;制造单租户大请求和连接池耗尽,确认隔离与降级生效。恢复后检查队列排空速度和重试放大,而不是只看平均值恢复。
高质量示范回答
“80 毫秒平均值与 2 秒 p99 同时成立,说明分布有明显长尾,最慢 1% 的请求可能触发用户超时或上游级联。我要先统一计时边界,区分首字节、完整响应、取消和重试,再按路由、区域、实例、租户、请求大小和依赖分解。端到端页面还要考虑串行求和和并行取最大值,因此会用 trace span 给每段分配预算。
定位到队列、连接池、GC、磁盘或下游后,分别采用有界并发、缓存/批量、减少串行依赖、租户隔离和有限重试。最终用 99.9% 请求在 300 毫秒内完成的 SLO、错误预算和发布前后分位数比较验证,确保尾部改善没有牺牲关键错误或数据正确性。”
常见错误
- 只报告平均值 → 长尾用户被隐藏 → 同时报告分位数、样本量和超时率。
- 平均各实例 p99 → 百分位不可线性平均 → 合并原始样本或使用正确的直方图聚合。
- 把重试当新用户请求 → 体验与负载被误计 → 关联原始请求和尝试。
- 只看服务端时间 → 网络、排队和客户端传输被遗漏 → 定义完整端到端边界。
- 无限增加线程 → 竞争和排队让尾部更长 → 设置有界并发和背压。
- 盲目重试超时 → 重试风暴压垮依赖 → 预算、抖动和明确截止时间。
- 只对整体设 SLO → 某个租户或区域长期退化 → 按关键维度切分并保护公平性。
- 发布后只看平均值 → 回归被掩盖 → 比较多档百分位和窗口。
追问与回答
追问一:为什么 p99 不是“最慢请求”?
p99 表示约 99% 样本不超过该值,剩余约 1% 更慢;最大值对单个异常和样本量极其敏感。两者都可看,但用途不同。
追问二:页面有五个并行请求,如何估算体验?
并行阶段的完成时间接近五个请求中的最大值,还要加客户端调度和传输开销。应测量页面总耗时,并用 trace 识别最常成为最大值的请求。
追问三:什么时候应该接受更高尾延迟?
离线导出或低频后台任务可能用吞吐换延迟;交互式关键路径通常不能。应在不同服务或请求类上分别定义 SLO,而不是用一个平均目标覆盖全部场景。
追问四:直方图为什么比平均值有用?
直方图保留延迟分桶和分布形状,可估计多个百分位并观察长尾。聚合时仍要注意分桶边界、采样误差和窗口样本量。
追问五:如何区分排队长尾和下游长尾?
把等待、处理和下游 span 分开记录。若队列年龄与服务时间一起上升,偏向容量或并发问题;若仅下游 span 变慢,则应检查依赖、连接和重试。
追问六:错误预算如何帮助延迟治理?
把超过延迟阈值的请求计入预算消耗。预算快速耗尽时暂停高风险发布、优先修复尾部;预算充足时可进行受控性能实验。这样延迟目标能影响工程决策。