
大模型调用量正在从行业讨论里的一个抽象数字变成许多开发团队必须直接面对的线上指标。当你看到“大模型调用量连续多周增长”这类信息时不必急着只把它当作趋势新闻它背后其实是一整类工程问题支撑成百上千个请求的推理服务是否稳定不同调用方之间会不会互相抢占资源流量增长后成本怎么核算服务抖动时应该先看哪个指标。这篇文章围绕大模型调用量的完整生命周期展开从部署一个能对外提供 API 的模型服务开始到用压测判断容量上限再到通过网关做限流和计量把调用量整理成可观测的指标与成本数据最后补充高并发阶段的优化顺序、生产排错和上线检查清单。适合正在做大模型应用开发、推理服务部署或 AI 基础设施建设的工程师参考。这里有一个容易忽略的前提调用量不只是“请求成功了多少次”。一次请求消耗多少 Token、占用 GPU 多长时间、返回延迟是否可接受往往比单纯计数更能反映服务质量。因此整篇文章的计算口径会同时覆盖请求次数、Token 消耗、并发能力和延迟分布只有把这几个维度凑齐调用量才能真正帮助团队做容量规划和故障定位。1. 把“调用量”拆开看次数、Token、并发不是一回事1.1 一次大模型调用的实际消耗为什么波动很大从用户角度理解调用一次大模型只是“提问一次”。但从服务端观察一次请求的消耗可能相差上百倍。一个请求可能只包含几十个 Token也可能因为“总结一份长文档”带入几万个 Token一个回答可能只生成几个字也可能在流式模式下持续输出上百秒。也就是说同样是 1 万次调用如果任务类型不同模型的显存占用、GPU 计算时长、带宽压力、计费金额都会完全不同。如果团队一开始只用“请求数”设计容量很容易在长上下文场景集中出现时被打穿。实际工程里通常使用兼容 OpenAI 风格的接口模型服务在每次请求结束时返回 usage 信息。常见结构如下{ usage: { prompt_tokens: 328, completion_tokens: 86, total_tokens: 414 } }prompt_tokens 是输入侧消耗completion_tokens 是生成侧消耗。这两个字段是调用量治理的基础后续做成本核算、用户配额、上限控制时都离不开它们。1.2 看调用量至少需要四类数据如果一个统计报表只写“调用次数”它能反映业务活跃度但无法回答“系统还能扛多久”。建议粒度拆成四类指标常见观察方式典型单位主要用途请求次数API 网关日志、Prometheus Counter次/分钟业务活跃度、用户用量Token 消耗量模型返回的 usage 字段累计tokens/小时成本核算、用户限额并发与吞吐网关连接数、GPU 监测、压测结果req/s容量评估、资源预警延迟分布中间件打点、服务端日志ms用户体验、SLA 判断这四类数据不是互相替代的关系。请求次数可以说明用户是否在增长Token 消耗量直接对应 GPU 算力和计费并发吞吐决定服务是否扩容“首 Token 延迟”和“完整响应延迟”则决定用户体感。1.3 当调用量持续增长时团队要先回答哪些问题外部统计说调用量连续多周增长里面往往是一个组织或一个平台的汇总结果。落到具体团队需要回答的问题通常是高峰期每秒请求数预计到多少现在的基础设施是否匹配。每类请求的平均输入 Token 和输出 Token 是多少会不会出现长上下文把显存打满的情况。调用方更在意首 Token 速度还是整体响应时间。超过容量后系统是温和地限流还是直接超时、报错、拖垮所有请求。这些问题没有一个能靠“次数”单独回答但都建立在调用量治理体系之上。所以在讨论高并发“怎么优化”之前先把部署和观测基础打好更重要。2. 部署层先跑通用 Ollama 验证用 vLLM 做容量测试对象2.1 本地部署选型先看三个前提大模型服务不一定都要自己部署。是否需要本地部署通常取决于三个前提数据是否允许离开内网。业务数据敏感时云端 API 方案会受到数据合规限制这时候本地部署几乎是必选项。Token 成本与硬件成本的平衡。云端 API 按 Token 付费自建服务需要前期购买 GPU 或使用已有集群资源。如果调用量稳定且持续增长自建方案通常更划算。团队是否有 GPU 运维能力。自建推理服务涉及驱动、CUDA、显存管理、模型版本升级、服务重启等多类问题不像调用云端 API 那样零运维。学习环境和生产环境应采用不同策略。个人开发机可以先验证模型效果和接口协议预发环境再使用更高吞吐的推理框架否则很容易把“模型能跑通”误认为“服务能抗住线上请求”。2.2 开发环境用 Ollama 快速验证调用链路Ollama 是目前最容易跑通本地模型的工具之一适合在开发机上验证模型选择、Prompt 效果和接口格式。安装后先启动服务ollama serve另一个终端拉取模型并运行ollama pull qwen2.5:7b ollama run qwen2.5:7bOllama 提供了兼容 OpenAI 风格的接口开发阶段可以用 curl 快速验证curl http://127.0.0.1:11434/v1/chat/completions \ -H Content-Type: application/json \ -d { model: qwen2.5:7b, messages: [{role: user, content: 用一句话解释什么是大模型调用量}], stream: false }返回结果里带有模型名称、回复内容和 usage 字段。这里要注意Ollama 更适合单机学习和小流量验证它在多用户、多并发、精细显存控制方面并不适合直接作为生产高并发入口。因此在搭建压测环境时建议单独选择吞吐能力更强的推理服务。2.3 vLLM 作为更高吞吐的推理服务当调用量开始具备明显的并发特征vLLM 是常见的选择。它通过 PagedAttention 管理 KV Cache并支持 Continuous Batching让多个请求在一个批次里持续推理吞吐明显高于简单的逐请求串行方案。启动命令示例vllm serve /data/models/qwen2.5-7b-instruct \ --served-model-name my-llm \ --port 8000 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --max-num-seqs 32参数含义如下参数作用注意事项--served-model-name对外暴露的模型名应用层不直接依赖真实权重路径后续换模型不影响调用方--max-model-len允许的最大上下文长度过小会导致长文档无法处理过大会占用显存--gpu-memory-utilization允许使用的显存比例加载权重后剩余显存会分配给 KV Cache--max-num-seqs每个迭代最多处理的序列数增大可提高吞吐但会放大排队延迟--portHTTP 服务端口默认 8000按环境调整服务启动后验证接口curl http://127.0.0.1:8000/v1/models如果返回模型列表说明服务可用。之后再调用/v1/chat/completions做业务验证。注意这里的模型 ID、端口、路径只是示例。落地前要结合自己下载的权重文件、GPU 型号和镜像版本确认参数不同版本的 vLLM 对参数名和默认值可能有差异。如果机器上有 GPU启动前先确认环境nvidia-smi python -c import torch; print(torch.cuda.is_available())第 2 行代码用于判断 PyTorch 是否能看到 GPU。如果输出 False说明 CUDA 驱动或 PyTorch 版本有问题推理服务即使启动也会回退到 CPU 模式性能会退化得非常明显。3. 用压测验证真实调用容量不要被“理论上限”带偏3.1 压测前按四个维度定义规则建好服务后下一步是搞清楚服务能承受多少调用量。压测不能只盯着“最高每秒并发”否则测试结果落不了地。建议在开始前定义四个维度目标吞吐期望单个实例支撑多少 req/s。延迟边界可接受的 p50、p95 和 p99 是多少。失败定义哪些情况算失败比如网络超时、非 200 状态、返回结构缺失。降级边界并发达到多少时开始拒绝新请求。大模型服务有一个特殊性延迟受输出长度影响很大。同一个模型输出 10 个 Token 和输出 500 个 Token单次占用时间不同。因此压测时要为请求固定一个 max_tokens并且要区分短文本和长文本两类场景。3.2 一个最小压测脚本用并发请求验证服务上限下面是一个基于 asyncio 和 aiohttp 的压测脚本作用是并发发送固定数量的请求统计成功数、平均延迟和分位延迟。import asyncio import time import aiohttp URL http://127.0.0.1:8000/v1/chat/completions CONCURRENCY 20 TOTAL 200 MODEL my-llm PAYLOAD { model: MODEL, messages: [{ role: user, content: 请用一句话回答为什么大模型调用量要关注 Token 消耗 }], temperature: 0.2, max_tokens: 128, stream: False, } async def one(session): start time.perf_counter() async with session.post(URL, jsonPAYLOAD) as resp: data await resp.json() cost time.perf_counter() - start usage data.get(usage, {}) or {} return cost, resp.status, usage.get(total_tokens, 0) async def main(): connector aiohttp.TCPConnector(limitCONCURRENCY) async with aiohttp.ClientSession(connectorconnector) as session: tasks [one(session) for _ in range(TOTAL)] results await asyncio.gather(*tasks, return_exceptionsTrue) ok [r for r in results if isinstance(r, tuple) and r[1] 200] latencies sorted(r[0] for r in ok) tokens sum(r[2] for r in ok) print(total:, len(results), success:, len(ok)) if latencies: print(avg latency: %.3fs % (sum(latencies) / len(latencies))) print(p50: %.3fs p90: %.3fs p99: %.3fs % ( latencies[int(len(latencies) * 0.50)], latencies[int(len(latencies) * 0.90)], latencies[int(len(latencies) * 0.99)], )) print(total_tokens:, tokens) if __name__ __main__: asyncio.run(main())这个脚本的目的是快速观察服务在指定并发下的表现不是完整的压测方案。正式项目里可以改用 Locust、k6 或 wrk 这类工具它们对分布式压测、实时曲线和报告生成支持更好。注意压测不要直接在线上服务上做。至少要先在预发环境完成一轮确认瓶颈和扩容建议后再选择业务低峰期用少量流量做线上校验。3.3 从压测结果推算节点数量假设压测结果显示单个节点在 p95 小于 3 秒的前提下能稳定支撑 5 req/s。线上高峰期预估为 80 req/s预留 30% 余量节点数 峰值 QPS / (单节点安全 QPS × 冗余系数) 80 / (5 × 0.7) ≈ 23 个节点这里的冗余系数不是绝对值要根据团队对延迟的容忍度、故障切换能力、是否有多副本调度等因素调整。关键是先有一个可量化的“单节点安全吞吐”而不是根据模型参数量拍脑袋估算。4. 在模型服务前面加流量治理层4.1 为什么需要网关层调用量增长后如果直接把模型服务的端口暴露给所有客户端会出现几个问题无法区分不同调用方个别应用把并发拉满后其他业务全部排队。没有统一入口计费、配额、限流、审计逻辑散落在业务代码里。后端节点调整 IP 或端口时调用方也要跟着改配置。模型服务异常时缺少统一的重试和降级策略。网关在这里的作用是收口。它在客户端与模型服务之间增加一层统一策略常见的任务包括路由到不同模型、按调用方限流、统计 Token 用量、隐藏后端细节、做故障摘除。4.2 Nginx 反向代理与限流配置示例在小型项目里Nginx 可以承担一部分网关职能。下面配置先定义限流区域然后把请求代理到 vLLM 服务。limit_req_zone $binary_remote_addr zonellm_api:10m rate5r/s; upstream llm_backend { server 127.0.0.1:8000; keepalive 64; } server { listen 9000; location /v1/chat/completions { limit_req zonellm_api burst10 nodelay; proxy_pass http://llm_backend; proxy_http_version 1.1; proxy_set_header Connection ; proxy_read_timeout 300s; proxy_send_timeout 300s; client_max_body_size 5m; } }这里有几个容易出错的位置。第一limit_req的rate5r/s表示同一 IP 每秒只能通过 5 个请求burst10允许临时积压 10 个请求nodelay表示不额外排队处理。它适合做基本防护但大模型场景中仅按 IP 限流不够必须结合用户维度。第二proxy_read_timeout很关键。普通接口默认超时通常够用但大模型生成时间可能超过 60 秒。如果不调大这个值Nginx 会在模型还没返回时就断开连接客户端看到的就是超时。第三keepalive 64配合proxy_set_header Connection 可以让 Nginx 与后端模型服务之间复用连接避免每次请求都重新建立 TCP 连接。注意Nginx 只是一个轻量示例。多节点、多租户、复杂路由时建议使用 Kong、APISIX 或云厂商网关并配合统一配置中心否则每个实例手动维护 Nginx 配置成本会迅速上升。4.3 配额怎么做次数配额、Token 配额与并发配额调用量治理里限流不能只看次数。大模型请求的消耗差异很大一个调用方可能一次只消耗 100 Token另一个调用方可能一次带进 10 万 Token 的上下文。如果只限制每分钟请求数后一类请求会轻易挤占系统资源。建议按三个维度同时设配额配额维度含义典型限制对象每分钟请求数控制接口被频繁调用的频率普通聊天类应用每分钟 Token 数控制输入与输出总消耗文档处理、批量任务每个请求最大上下文防止单个请求吃掉全部显存所有调用方网关或配额服务在实现时一般先判断请求属于哪个调用方再读取对应的 RPM 和 TPM 阈值。超过次数限制时返回 429并且要在响应头里告诉客户端何时可以重试例如Retry-After: 30。在实际项目里不要把配额逻辑写在模型服务内部。模型服务本身的职责是高效推理配额的判断、错误提示、用量记录应该尽可能前置到网关或独立 API 服务中。5. 让调用量可以被观测指标、日志与成本报表5.1 usage 字段是计量的基础所有调用量分析都要建立在准确记录 usage 的基础上。每次请求完成后至少需要记录以下字段{ timestamp: 2025-06-01T12:00:00.123Z, client_id: project-a, model: my-llm, request_id: req-0001, status_code: 200, latency_ms: 8720, prompt_tokens: 328, completion_tokens: 86, total_tokens: 414 }这里有一个隐藏问题usage 字段只有请求成功完成后才会返回。如果请求在生成中途超时、连接断开或模型报错可能拿不到完整的 usage 数据。因此在计量链路里必须把“请求进入”和“Token 统计”分成两件事请求进入立刻记录 request 次数Token 消耗在成功返回后再异步累计。生产环境还建议接入消息队列把访问日志异步发送到日志平台或时序数据库。不要在业务线程里同步写数据库否则一次模型调用已经够慢再叠加同步存储会让服务吞吐下降。5.2 用 Prometheus 指标暴露核心数据如果不想只依赖日志检索可以在 API 服务里暴露 Prometheus 指标。下面是用 prometheus_client 定义的基础指标示例。from prometheus_client import Counter, Histogram REQUESTS_TOTAL Counter( llm_requests_total, Total number of LLM requests, [model, status], ) TOKEN_USAGE Counter( llm_tokens_total, Total token usage, [model, token_type], ) DURATION Histogram( llm_request_duration_seconds, LLM request duration in seconds, [model], buckets(0.5, 1, 2, 5, 10, 30, 60, 120), )请求结束时记录指标def record(model: str, status: int, duration: float, usage: dict): REQUESTS_TOTAL.labels(modelmodel, statusstatus).inc() DURATION.labels(modelmodel).observe(duration) if usage: TOKEN_USAGE.labels(modelmodel, token_typeprompt).inc( usage.get(prompt_tokens, 0) ) TOKEN_USAGE.labels(modelmodel, token_typecompletion).inc( usage.get(completion_tokens, 0) )之所以把请求次数和 Token 消耗分成两个指标是因为它们生命周期不同。请求进入时可以很快确定 status但 Token 消耗必须等响应完成后才能统计。分成两个 Counter可以避免“请求失败了但 token 归零导致请求数丢失”的问题。接入 Prometheus 后Grafana 大盘至少需要以下几块每分钟请求数、成功率、p50/p95 延迟、Token 消耗趋势、GPU 利用率、排队中的请求数。这些数据组合起来才能回答“调用量到顶了吗”和“顶在哪里”。5.3 从指标换算成本成本报表的输入不是请求次数而是 Token 数。假设内部结算规则如下计费项目单价输入 Token0.003 元/千 Token输出 Token0.012 元/千 Token如果某应用一天消耗 5 亿输入 Token 和 1 亿输出 Token那么当日成本估算为输入成本 500000000 / 1000 * 0.003 1500 元 输出成本 100000000 / 1000 * 0.012 1200 元 当日总成本 2700 元这里的单价只是示例实际项目要按照自己模型的部署成本和供应商价格调整。更重要的是流程把 Token 用量按 client_id 和 model 分组后每天生成用量报表。否则调用量增长越快成本失控的风险越大。6. 高调用量阶段的优化和排错6.1 瓶颈判断先看首 Token 延迟还是总延迟流量上来后如果接口变慢不要直接去调模型参数。先定位延迟增长发生在哪个阶段。如果首 Token 延迟明显增大多半是服务端排队严重或预处理太慢。如果首 Token 很快但总延迟增长可能是输出长度变长、生成速度受限于 GPU 计算。如果所有延迟都增大先看 CPU、GPU 利用率、网络连接数和日志里的错误。实际排查时可以观察推理服务日志中的排队时间。vLLM 等框架会输出每个请求的等待时间如果等待时间占整个响应时间的大部分说明需要扩容节点而不是改 max_tokens 或调整模型。6.2 值得实测的优化项以下优化方向不是万能药建议先做压测再决定是否上线。开启前缀缓存。如果很多请求共享同一段长 Prompt例如系统提示词相同启用前缀缓存可以复用已被计算过的 KV Cache减少重复计算。限制单个请求的最大上下文长度。上游传来的文本不能无限制放大要在 API 层做长度校验或截断避免一个超长请求拖垮整个批次。拉长服务的批次窗口但控制等待时间。Continuous Batching 能提升吞吐但每个请求不能等待太长时间否则延迟指标会变差。为不同业务设置合理的 max_tokens。不是所有场景都需要输出 2000 Token短输出任务可以设更小的上限让单次请求占用更短时间。对重复性高的问题做语义缓存。在网关层设置相似问题命中缓存可以直接返回结果减少去模型服务的真实调用量。这些动作都要以监控数据为判断依据。如果瓶颈是显存和 GPU 算力单纯增加缓存没有意义如果瓶颈是客户端排队优化模型本身也不会有效果。6.3 生产环境高频问题对照表问题现象常见原因先检查哪里处理建议调用方出现大面积 429网关限流配置过严或后端已过载网关日志、限流规则、模型服务 GPU 利用率区分配额限制与过载限流配额 429 要看调用方用量过载 429 要扩容请求长时间挂起后超时模型生成时间超过代理层超时时间Nginx 或网关的 proxy_read_timeout调大读超时时间配置更合理的重试策略显存突然升高到 OOM长上下文请求过多max-model-len 设置过大vLLM 启动日志、CUDA OOM 报错降低 max-model-len限制单用户上下文长度减少单实例最大序列数指标显示请求次数但 Token 数据缺失只统计了成功响应超时或错误请求没有记录 usage查看中间件统计入口请求次数与 Token 消耗拆成两个统计过程除此之外生产环境还有一个常见坑冷启动。模型权重加载完成后第一批请求往往很慢因为显存分配、KV Cache 初始化和 CUDA 上下文预热都还没有完成。正式发布前可以主动发若干次请求做预热再接入真实流量。7. 上线前检查清单与下一步建议7.1 发布前检查清单调用量治理最怕在流量高峰时才发现某个基础环节没打通。下面是一份可以复用的上线检查清单。检查项目检查内容常见遗漏接口连通性curl 调用 /v1/chat/completions确认 usage 有返回值只验证模型能回答没有验证 token 统计压测数据记录单节点安全 QPS、p95 延迟、失败率压测时输出长度固定无法覆盖长文本场景网关配置超时时间、keepalive、请求体大小限制默认读超时不够长长生成任务被切断限流配额按调用方设置 RPM、TPM、最大上下文只限次数不限 Token可观测性Prometheus 指标、Grafana 大盘、错误日志只记录请求数不记录延迟和 Token成本报表按 client_id 和 model 汇总日 Token 用量成本只在月底手动统计日志安全日志中不输出完整敏感对话内容只记录长度或脱敏信息业务日志里打印了整段用户输入日志安全经常被忽略。大模型请求日志可能包含敏感信息不建议直接把完整 Prompt 和完整回答打进 ELK 或日志文件。日志里保留 request_id、client_id、时间、长度、延迟即可真正的请求内容如果需要审计应单独加密保存并严格控制访问权限。7.2 下一阶段可以扩展什么当调用量治理基础已经具备下一步可以沿着三个方向扩展。第一接入多模型路由。同一个请求可能是普通对话、代码生成、文档总结等不同用途可以按意图或按成本阈值把请求路由到不同模型而不是所有请求都打到大模型上。第二建设自动化扩缩容。大模型服务的扩容依据不能只看 CPU要结合 GPU 利用率、排队请求数、队列深度等指标综合判断是否需要新增实例。第三引入语义缓存和结果复用。高频问题、重复文档处理这类场景存在明显的缓存收益。先通过监控找到相似度和命中率再逐步推广到更多业务。如果团队刚接触这个方向建议先从最小闭环开始用一套测试环境部署一个模型服务写一次压测脚本把请求次数、Token 消耗、延迟和成功率接到 Grafana 上。这个闭环跑通后所有关于扩容、限流和成本的讨论都会变得具体不会再停留在“调用量增长了”这个数字表面。