恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
LLM 推理延迟监控体系:从 Metrics 采集到 SLO 驱动的告警策略(TaoToken 统一 Key 接入篇)
首页
资讯中心
/
LLM 推理延迟监控体系:从 Metrics 采集到 SLO 驱动的告警策略(TaoToken 统一 Key 接入篇)
LLM 推理延迟监控体系:从 Metrics 采集到 SLO 驱动的告警策略(TaoToken 统一 Key 接入篇)
发布时间:2026/10/5 21:46:46
1. 为什么均值会骗你LLM 推理延迟的分阶段视角如果你正在自建或调用大模型推理服务大概率遇到过这种场景监控面板上平均延迟只有 800ms看起来一切正常但用户群里不断有人抱怨“卡得没法用”。问题出在均值这个指标本身——它把排队 8 秒的请求和 200ms 返回的请求平均在一起得出一个谁都不满意的数字。LLM 推理延迟不是一个单一指标它至少由四段构成请求排队时间Queue Time、首 Token 延迟TTFT、单 Token 生成延迟TPOT、以及 Token 间抖动。这四段对应完全不同的工程瓶颈。Queue Time 高说明并发超限或 max-num-seqs 设置过小TTFT 高说明 Pre-fill 阶段计算压力大通常和 Prompt 长度、Batch 大小相关TPOT 高则指向 Decode 阶段的显存带宽或 KV Cache 命中率问题。我试过只监控总延迟结果一次线上劣化排查花了三个小时最后发现是 Queue Time 从 200ms 涨到了 4 秒而总延迟因为部分请求本身很快均值只涨了 15%。从那以后分阶段埋点成了标配。这篇文章面向正在搭建 LLM 推理可观测性的工程师无论你是用 vLLM 自建服务还是通过统一 API 通道调用模型。我会给出可复制的 Prometheus 采集配置、SLO 阈值定义、告警规则片段以及一套验证方法注入模拟延迟后核对指标和告警是否按预期触发。所有调用侧配置统一走 TaoToken 的 Key 和 Base URL避免多供应商切换时监控标签混乱。核心检索词先明确LLM 推理延迟监控体系是一套从 Metrics 采集、分位统计到 SLO 告警的完整链路适合需要保障推理服务稳定性的后端和运维同学。2. TaoToken 统一 Key 接入让监控标签不再碎片化在讲采集配置之前先解决一个容易被忽略但很致命的问题调用入口不统一导致监控维度爆炸。如果你同时用 OpenAI、Anthropic、国内某厂商的 API每个 SDK 的返回结构、错误码、超时行为都不一样你的延迟埋点代码里会塞满 if-else标签体系也会被供应商名称切得七零八落。TaoToken 在这里的角色是一个统一 API 通道。你只需要一个 Key、一个 Base URL就能调用多家模型。对监控体系来说这意味着你的 Metrics 标签可以保持干净model、endpoint、status 三个维度就够了不需要再加 provider 维度。接入方式很简单。Base URL 固定为https://taotoken.net/apiKey 在控制台生成。如果你用 OpenAI 兼容的 SDK只需要改两个环境变量export OPENAI_BASE_URLhttps://taotoken.net/api export OPENAI_API_KEYsk-你的TaoToken密钥对于 Claude Code 这类工具配置方式略有不同。你需要在 settings 里指定 Base URL 和 KeyModel ID 填你实际要调用的模型名。这里给出一个可复制的 settings 片段{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }如果你用 Cline 或 Roo Code 这类 VS Code 插件在 MCP 配置里同样填这三件套Base URL、API Key、Model ID。注意 Model ID 必须和你实际调用的模型一致否则监控里的 model 标签会对不上。为什么要在监控文章里花篇幅讲接入因为延迟埋点的准确性依赖于调用链的稳定性。如果每次请求都经过不同的 SDK、不同的超时设置你采集到的 TTFT 和 TPOT 就失去了可比性。统一通道之后你的 Histogram 桶边界只需要针对一套行为调优告警阈值也不会因为供应商切换而频繁误报。另外TaoToken 的 API Key 支持在控制台查看用量和调用记录这对排查“是网络问题还是模型问题”很有帮助。当你的监控告警触发时可以对照控制台的调用日志快速判断是客户端超时还是服务端延迟。3. 可复制配置Prometheus 采集 vLLM Metrics 分阶段埋点这一节是全文的技术核心。我会给出三部分配置vLLM 侧的 Prometheus 指标暴露、Python 客户端的分阶段延迟埋点、以及 Prometheus 的抓取和告警规则。3.1 vLLM 侧启用 /metrics 端点vLLM 默认在 8000 端口暴露 Prometheus 格式的指标。启动时确认没有禁用 metricspython -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-3.1-8B-Instruct \ --port 8000 \ --max-num-seqs 64 \ --enable-metrics启动后访问http://localhost:8000/metrics你应该能看到vllm:time_to_first_token_seconds_bucket、vllm:time_per_output_token_seconds_bucket、vllm:request_queue_time_seconds等指标。如果看不到检查 vLLM 版本是否低于 0.4.0旧版本指标名称不同。3.2 客户端侧分阶段延迟埋点服务端指标只能告诉你引擎内部的情况客户端侧需要自己埋点来捕获网络传输和端到端体验。下面是一个可复制的 Python 埋点模块import time from prometheus_client import Histogram, Counter TTFT_HIST Histogram( llm_client_ttft_seconds, Client-side Time To First Token, labelnames[model, endpoint], buckets[0.05, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0] ) TPOT_HIST Histogram( llm_client_tpot_seconds, Client-side Time Per Output Token, labelnames[model, endpoint], buckets[0.01, 0.015, 0.02, 0.025, 0.03, 0.05, 0.1, 0.2] ) QUEUE_HIST Histogram( llm_client_queue_seconds, Client-side Queue Waiting Time, labelnames[model], buckets[0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0] ) ERROR_COUNTER Counter( llm_client_errors_total, Client-side request errors, labelnames[model, error_type] ) def observe_streaming_call(model: str, endpoint: str, stream): t_start time.time() t_first_token None token_times [] for chunk in stream: now time.time() if t_first_token is None: t_first_token now TTFT_HIST.labels(modelmodel, endpointendpoint).observe(now - t_start) else: token_times.append(now) if len(token_times) 1: intervals [token_times[i] - token_times[i-1] for i in range(1, len(token_times))] avg_tpot sum(intervals) / len(intervals) TPOT_HIST.labels(modelmodel, endpointendpoint).observe(avg_tpot) return t_first_token - t_start if t_first_token else None这段代码的关键点TTFT 从请求发出到第一个 chunk 到达TPOT 取所有 token 间隔的均值Queue Time 在客户端侧较难精确测量通常用服务端指标补充。3.3 Prometheus 抓取配置在prometheus.yml中加入两个 jobscrape_configs: - job_name: vllm-server scrape_interval: 15s static_configs: - targets: [localhost:8000] labels: service: llm-inference tier: server - job_name: llm-client scrape_interval: 15s static_configs: - targets: [localhost:9091] labels: service: llm-client tier: client客户端侧需要启动一个prometheus_client.start_http_server(9091)来暴露指标。3.4 SLO 阈值定义不同场景的 SLO 差异很大。下面是一份可直接使用的阈值表场景TTFT P99TPOT P99Queue Time P95错误率交互式聊天 3s 50ms 1s 0.5%代码补全 500ms 30ms 200ms 0.1%批量分析 30s 200ms 5s 2%这些阈值不是拍脑袋来的。交互式聊天的 3s TTFT 来自用户等待心理研究超过 3s 用户会明显感到卡顿代码补全的 500ms 是因为 IDE 场景下超过这个值就会打断编码节奏。3.5 告警规则片段groups: - name: llm_inference_slo interval: 30s rules: - alert: HighTTFTTailLatency expr: | histogram_quantile(0.99, rate(vllm:time_to_first_token_seconds_bucket[5m]) ) 3.0 for: 5m labels: severity: warning annotations: summary: TTFT P99 3s检查 Pre-fill Batch 大小 - alert: HighTPOTTailLatency expr: | histogram_quantile(0.99, rate(vllm:time_per_output_token_seconds_bucket[5m]) ) 0.05 for: 5m labels: severity: warning annotations: summary: TPOT P99 50msDecode 阶段显存带宽可能饱和 - alert: HighQueueTime expr: avg(vllm:request_queue_time_seconds) 2.0 for: 2m labels: severity: critical annotations: summary: 请求排队 2smax-num-seqs 或显存不足 - alert: HighKVCacheUsage expr: vllm:gpu_cache_usage_ratio 0.90 for: 5m labels: severity: critical annotations: summary: KV Cache 90%即将 OOM注意for字段的差异Queue Time 用 2m 是因为排队恶化通常来得快需要快速响应TTFT 和 TPOT 用 5m 是为了过滤掉偶发毛刺。4. 验证请求注入模拟延迟并核对告警配置写完不代表能用。你需要一套验证流程来确认指标采集正确、告警按预期触发。下面是我实际用的验证步骤。4.1 注入模拟延迟最直接的方法是在客户端侧加一个 sleep。写一个测试脚本import time import openai client openai.OpenAI( base_urlhttps://taotoken.net/api, api_keysk-你的TaoToken密钥 ) def call_with_delay(delay_seconds: float): time.sleep(delay_seconds) stream client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: 用一句话解释什么是延迟}], streamTrue ) for chunk in stream: pass for i in range(20): call_with_delay(0.5 if i 10 else 3.0)前 10 次注入 0.5s 延迟后 10 次注入 3s 延迟。这样 TTFT 的 P99 应该会超过 3s。4.2 核对指标在 Prometheus 查询界面执行histogram_quantile(0.99, rate(llm_client_ttft_seconds_bucket{modelgpt-4o-mini}[5m]) )如果返回结果大于 3.0说明埋点生效。同时检查vllm:time_to_first_token_seconds_bucket是否有数据如果没有说明服务端指标没暴露或抓取配置有误。4.3 核对告警在 Prometheus 的 Alerts 页面等待for字段指定的时间后HighTTFTTailLatency应该从 Inactive 变为 Pending再变为 Firing。如果一直是 Inactive检查表达式里的指标名是否和实际暴露的一致。一个常见坑vLLM 不同版本的指标名有差异。0.4.x 用vllm:time_to_first_token_seconds0.5.x 之后可能变成vllm:time_to_first_token_seconds_histogram。用curl localhost:8000/metrics | grep ttft确认实际名称。4.4 验证成功标准一次完整的验证应该满足三个条件客户端 Histogram 的 P99 超过阈值服务端 Histogram 的对应分位数同步上升告警在预期时间内触发。三者缺一说明链路中有断点。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth配置过程中最容易卡住的不是 Prometheus 本身而是调用通道的认证和网络问题。下面按报错类型逐一排查。5.1 401 Unauthorized这是最常见的错误。原因通常是 Key 没传对或 Base URL 写错。检查两点OPENAI_API_KEY是否以sk-开头且没有多余空格OPENAI_BASE_URL是否精确为https://taotoken.net/api注意末尾不要加/v1除非你的 SDK 要求。如果你用 Claude Code401 还可能是因为ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN同时设置了后者覆盖前者。只保留一个。5.2 local proxy failed这个报错通常出现在客户端无法连接到 Base URL 时。先确认网络能通curl -I https://taotoken.net/api如果返回 200 或 401说明网络没问题问题在 SDK 配置。如果超时检查你的 DNS 和防火墙规则。注意不要在代码里硬编码任何代理地址统一走系统环境变量。5.3 reading choices 相关报错Error reading choices或choices is empty通常意味着流式响应解析出了问题。如果你用的是 OpenAI SDK 的streamTrue确保你遍历的是chunk.choices[0].delta.content而不是chunk.choices[0].message.content。流式和非流式的返回结构不同。另一个原因是模型返回了空内容。检查你的 prompt 是否触发了内容过滤或者 max_tokens 设置过小导致没有输出。5.4 OAuth 相关错误如果你用 Claude Code 的 OAuth 登录方式但同时又配置了 API Key可能会冲突。Claude Code 优先使用 OAuth token如果 token 过期就会报错。解决方案是在 settings 里明确使用 API Key 模式把ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY都配上不要混用 OAuth。5.5 指标采集侧的常见问题Prometheus 抓不到数据先检查 target 状态。在 Prometheus 的 Targets 页面如果 State 是 DOWN看 Error 信息。常见原因端口没开、防火墙拦截、metrics 路径不是/metrics。Histogram 分位数不准通常是桶边界设置不合理。TTFT 的桶如果最大只到 5s那 P99 超过 5s 时会被归到 Inf 桶估算值严重偏低。建议 TTFT 桶延伸到 30sTPOT 延伸到 200ms。告警不触发检查for字段和interval的关系。如果interval是 30sfor是 5m那至少需要 10 个采集点都满足条件才会触发。测试时可以把for临时改成 30s 加快验证。6. 从告警到根因让监控体系真正闭环监控体系建好之后最容易犯的错是“告警响了看一眼重启服务继续”。这样监控就退化成了一个通知工具而不是改进工具。我的做法是每次告警触发后强制关联三个维度的数据同时段的 GPU 指标利用率、温度、功耗、时钟频率、同时段的请求特征平均 Prompt 长度、并发数、模型分布、以及同时段的错误日志。这三份数据放在一起根因通常一目了然。比如 TTFT P99 飙升如果 GPU 利用率同时从 70% 涨到 95%说明是计算饱和需要扩容或限流如果 GPU 利用率没变但 Queue Time 涨了说明是并发调度问题检查 max-num-seqs如果 GPU 和 Queue 都正常但 TTFT 涨了那可能是 Prompt 长度分布变了Pre-fill 计算量增加。SLO 不是一成不变的。每次模型版本升级、GPU 硬件更换、或者业务场景变化都应该重新跑一次分桶分析调整 Histogram 桶边界和告警阈值。我习惯在每个季度做一次 SLO 回顾把过去三个月的告警记录拉出来看哪些阈值误报率高、哪些真实劣化被漏掉。最后给一个实用技巧在 Grafana 里做一个“延迟分解”面板把 Queue Time、TTFT、TPOT 三条曲线叠在一起。当总延迟劣化时哪条曲线先抬头根因就在哪个阶段。这个面板比任何告警都直观建议每个 LLM 推理服务都配一个。如果你还没有统一的调用通道可以从 TaoToken 的 API Keys 页面生成一个 Key把 Base URL 配成https://taotoken.net/api然后按本文的埋点代码接入。接入文档里有各语言 SDK 的完整示例模型对话页面可以直接测试连通性。长期做编码和 Agent 场景的话Coding Plan 的额度模型更适合高频调用。监控体系的第一步永远是让调用链路先稳定下来。