news 2026/10/11 3:21:10

推理服务的可观测性:从用户体验、流式交付到 GPU 证据的完整排障闭环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
推理服务的可观测性:从用户体验、流式交付到 GPU 证据的完整排障闭环

推理服务的可观测性:从用户体验、流式交付到 GPU 证据的完整排障闭环

用户说“回答很慢”,工程师需要回答四个问题:慢在哪里,影响谁,有什么证据,怎么验证修复。

本文以 Kubernetes 上的流式 LLM 推理服务为主线,结合框架指标、OpenTelemetry、自定义阶段埋点、DCGM 和 eBPF,建立从用户体验到 GPU 执行的关联分析方法。适用于 vLLM 等推理框架;具体指标与参数必须以部署版本为准。文中的阈值、案例数字和容量配置均为教学示例,不代表实测结果或通用性能承诺。

这张图只展示在线请求的主路径;实际关联必须同时维护两条辅助路径:

请求路径:客户端 → Ingress/网关 → 业务/RAG → 推理引擎 → GPU/rank Metrics: 各层低基数指标 ─────────────────────────→ Prometheus/Grafana/SLO Trace: trace_id/request_id ─────────────────────→ OTel Collector/Trace Store 映射: model → Pod UID → node/worker → GPU UUID/rank → batch_id(采样追踪) 下钻: 体验告警 → model/pod 看板 → 慢请求 Trace → 短窗口 eBPF/Nsight

Prometheus 只保存有限枚举标签;request_id、trace_id、batch_id只放日志/追踪。图或映射中任何一环不存在时,禁止把节点全部 GPU 活动强行归属给单个请求。

术语与数据契约(先读本节)

术语严格含义不应写成
引擎 ITL引擎实际导出相邻 token/调度事件的间隔客户端 SSE 间隔
chunk gap本层收到相邻有效 SSE 内容事件的间隔;一个事件可含多个 token每 token 生成时间
用户可见 TTFT客户端实际展示首个有效内容减去用户发起时间首字节、role、心跳时间
请求级平均 TPOT用首/末有效输出和可信N推导,且仅N>1逐 token 精确时钟

若只有代理/客户端视角,面板必须叫chunk_gap,而不是 ITL。输入 token 吞吐是输入工作负载代理,前缀缓存、KV 重用和分块 Prefill 存在时不等于实际 Prefill 计算量。

一、用户的一句“慢”,可能是四类不同的问题

上线了流式推理接口,GPU 利用率在 90% 左右,输出吞吐也很高,但用户仍在投诉。原因可能完全不同:

  • 请求发出后几秒没有内容:首个有效输出晚,优先检查网关、业务前置处理、排队和 Prefill。
  • 很快开始回答,但持续生成很慢:检查 Decode 调度、活跃序列、KV Cache、计算、访存和通信。
  • 回答一阵后突然停顿,再一次性出现大量文字:检查流式缓冲、客户端读取、批量输出、调度中断和抢占。
  • 每个 token 都正常,但整段回答耗时很长:可能只是输出长度变大,不能直接认定模型变慢。

因此,第一步不是加卡,而是把“慢”转化为明确的测量口径。可观测性建设的顺序也应如此:先量化体验,再拆解阶段,最后用硬件证据解释原因。

二、先统一指标口径:TTFT、TPOT、ITL 不是同一件事

2.1 为每个测量位置定义时间点

在客户端或网关的一次请求观测中,定义:

时间点含义
t0本层开始发送请求或接收请求
t1本层收到第一个有效输出 token/内容事件
tN本层收到最后一个有效输出
tend本层收到流完成标记或请求结束
N本次请求的输出 token 数,由服务端 tokenizer/usage 等可信来源统计

“有效输出”要写入接口契约:角色信息、SSE 心跳、空 delta 不计入;如果产品隐藏思考内容,需要同时记录“首个模型输出”和“首个用户可见内容”。只有后者直接解释用户为什么迟迟看不到回答。

同一个指标必须带测量位置:客户端 TTFT、网关 TTFT、引擎 TTFT 的起止点不同,数值不能直接比较。非流式接口收到完整响应前通常看不到首个 token,不能拿首字节时间冒充流式 TTFT。

2.2 指标定义与使用场景

指标推荐口径用来回答什么
TTFTt1 − t0用户等多久才看到首个有效输出
单请求平均 TPOT(tN − t1) / (N − 1),仅 N > 1首个 token 之后,平均每 token 需要多久
ITL相邻输出 token 的到达间隔;若只观测到 chunk,则记录 chunk gap生成过程中是否存在长停顿
生成跨度tN − t0从请求开始到最后有效输出的时间
E2Etend − t0整个请求何时结束,包括尾部收尾
单请求生成速度(N − 1) / (tN − t1)一条请求的平均生成速度,token/s
聚合输出吞吐窗口内实际生成的输出 token / 窗口秒数整个服务的输出能力
输入吞吐窗口内处理的输入 token / 窗口秒数Prefill 侧工作量
队列长度/排队时间等待请求数/请求等待调度的实际时长首字慢是否来自排队

对同一测量位置、同一输出 token 口径:

tN − t0 = TTFT + TPOT × (N − 1)

若 E2E 定义到完成标记,还应加上tend − tN。N 为 0 或 1 时,TPOT 不定义,不能填 0 混入延迟直方图。失败、取消和没有输出的请求单独统计结果与耗时,避免只看成功样本。

例如:首个输出等待 0.8 秒,200 个输出 token 的平均 TPOT 为 0.04 秒,则生成跨度为0.8 + 199 × 0.04 = 8.76 秒。其中约 25 token/s 是这条请求的速度,不能用集群的 5,000 token/s 来替代。

2.3 chunk 不是 token,TPOT 分位数也不是 ITL 分位数

SSE 的一个内容事件可以包含多个 token。一次网络读取还可能包含多个 SSE 事件;token 的文本片段也不能通过“字符数”准确反推 token 数。推测解码、输出合并与代理缓冲都可能进一步改变到达形态。

因此建议保留两套统计:

  1. 请求级平均 TPOT:每个完成请求产生一个样本,适合比较请求体验。
  2. 输出事件间隔:每个间隔产生一个样本,适合发现停顿;面板必须标清 token gap 还是 chunk gap。

长请求贡献更多间隔样本。ITL P99 与请求 TPOT P99 权重不同,不能互换。vLLM 当前文档也区分了输出事件间隔与请求级 TPOT,旧版指标名和语义可能不同。[1][2]

2.4 分位数之前,先控制工作负载差异

至少按模型版本、输入长度档、输出长度档、业务优先级和副本查看分布。常见误判是:模型没有退化,只是输入从短问答变成了长上下文 RAG。

长度档使用有限枚举,例如0–1k / 1k–4k / 4k–16k / >16k;档位应与业务匹配。不要把精确 token 长度、用户 ID 或 request_id 放到 Prometheus 标签中。

还要记住三条统计边界:

  • 不能平均多个副本的 P99;应合并相同桶边界的 Histogram,再计算分位数。
  • P99(TTFT) − P99(queue)不是 Prefill P99。
  • P99(TTFT) + P99(decode)不是 E2E P99。分位数对应的可能是不同请求。

三、把请求拆开:找到首字之前和生成之中的等待

3.1 建立阶段契约,而不是画一张含糊的耗时图

对单个请求,建议记录以下阶段。名字可以自定义,起止事件必须固定。

阶段建议起止点常见慢因
网关处理网关接收 → 向后端转发鉴权、限流、连接池、路由
业务前置业务服务接收 → 向引擎提交RAG 检索、工具调用、Prompt 拼接
前处理引擎接收 → 请求进入调度等待分词、多模态预处理、参数校验
初次排队入队 → 第一次被调度容量不足、优先级、KV 空间限制
Prefill首次相关执行 → 首 token 产生输入长度、前缀缓存、执行配置
Decode 生命周期首 token → 最后 token多轮调度、抢占、计算/访存/通信
流式交付引擎产生事件 → 网关转发/客户端收到输出队列、代理缓冲、网络、慢客户端

连续批处理、分块 Prefill、Prefill/Decode 分离和抢占会让阶段反复发生。此时记录事件与区间:入队、调度、暂停、恢复、首次输出、最后输出,而不是假定每个请求只有一次完整 Prefill 和一次连续 Decode。

请求生命周期时长也不等于该请求独占的 GPU 时间。多条请求共用一个 batch,一次 GPU 执行可能同时推进多个请求。若需要归因,可在采样追踪中记录 batch_id、调度步与参与请求,使用 span link 或事件关联;不要把整个 batch 的 GPU 时长重复相加后当成集群总耗时。

3.2 如何解释客户端与服务端的差值

同一请求的客户端 TTFT 明显高于服务端 TTFT,说明额外耗时存在于引擎测量范围之外,可能包含连接建立、网关、业务前置、转发缓冲、网络和客户端调度。

这个差值是缩小范围的线索,不能直接命名为“网络延迟”。下一步对比网关收到后端首内容、网关写出首内容、客户端读取首内容的事件,再检查连接与缓冲。

用单调时钟测本进程耗时,用同步后的墙钟关联不同主机的时间线。不要直接拿不同机器的单调时间戳相减;时钟偏差也会影响跨主机事件排序。

四、分层采集:每种工具负责一种证据

工具/数据适合回答不能单独证明
客户端与网关埋点用户看到首内容和持续输出的时间模型哪个 kernel 慢
推理框架指标排队、请求延迟、吞吐、缓存状态单个慢请求的完整因果链
OTel 与自定义阶段埋点请求经过哪些阶段,在哪里等待异步 GPU 的真实执行完成时间
DCGM
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 3:20:45

PJ85718DM与PIC18F87J11温控组合实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/11 3:17:57

产品知识培训实战:五十页PPT如何转化为销售卖货能力

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/11 3:15:32

MySQL排序深入解析:从ORDER BY语法到索引与Filesort性能优化

做后台系统这些年,我几乎每天都要跟MySQL里的查询结果排序打交道。文章列表按发布时间倒序,订单报表按金额降序,排行榜按浏览量取前N条——一句ORDER BY看上去简单,真正用起来,语法坑、性能坑、数据类型坑一个都不少。…

作者头像 李华
网站建设 2026/10/11 3:15:30

MFC图表控件ChartCtrl的VS2015移植实战:从修复到性能优化

简介:这是一套基于MFC的老牌ChartCtrl图表控件源码,已优化适配VS2015工程,面向具备基础C/MFC知识、需要在桌面程序中展示动态或静态数据的开发者,可直接嵌入Demo项目或自行编译运行。控件功能实用,支持折线图、柱状图、…

作者头像 李华
网站建设 2026/10/11 3:13:56

SpringBoot医疗就诊平台从0到1:表设计、并发控制与踩坑清单

简介:面向计算机专业毕业生的医疗就诊平台毕业设计论文,以SpringBootJavaMySQL实现,内容覆盖系统需求分析、功能设计、数据库设计及实现细节,适用于毕业设计选题、论文撰写参考和项目开发学习。压缩包内仅含1个docx文档&#xff0…

作者头像 李华