大模型落地必经之路:LLM 服务部署方案,从推理引擎到流量治理
大模型落地必经之路:LLM 服务部署方案,从推理引擎到流量治理
一、Token 账单与毫秒响应的双重夹击:大模型落地的"省钱"痛点
当大模型从 PoC 阶段走向生产环境,工程团队会立刻撞上两堵墙:一是推理成本居高不下,单次请求的 GPU 占用让账单飞速攀升;二是响应延迟不可控,P99 延迟动辄数秒,用户体验断崖式下跌。这两者看似矛盾——降成本需要提高 GPU 利用率,降延迟又需要预留计算冗余——但本质上都指向同一个核心问题:LLM 服务的部署架构是否足够精细。
在实际生产中,一个 7B 参数模型的推理服务,若采用最朴素的单实例部署,QPS 往往只有个位数。而企业级场景对吞吐和延迟的要求,迫使我们必须从推理引擎选型、模型量化、动态批处理、流量路由等多个层面进行系统性优化。这不是简单的"加机器"问题,而是架构层面的取舍博弈。
二、推理引擎选型与请求调度:从模型加载到 Token 流出
LLM 服务部署的核心链路可以概括为:模型加载 → 请求接收 → 调度排队 → 推理执行 → Token 流式返回。每个环节都有独立的优化空间,而引擎选型决定了整条链路的天花板。
flowchart TB
A[客户端请求] --> B[API Gateway]
B --> C[请求队列]
C --> D{动态批处理调度器}
D -->|Batch 组装| E[推理引擎 vLLM/TGI/TrtLLM]
D -->|超时降级| F[缓存命中检查]
F -->|命中| G[直接返回缓存结果]
F -->|未命中| E
E --> H[Token 流式输出]
H --> I[SSE 推送客户端]
G --> I
当前主流推理引擎的定位差异明显:
- vLLM:采用 PagedAttention 技术,通过虚拟内存分页管理 KV Cache,显存利用率高,适合多并发场景。其 Continuous Batching 机制可以在不等待整个 batch 完成的情况下插入新请求,显著提升吞吐。
- Text Generation Inference (TGI):HuggingFace 出品,原生支持 Flash Attention 和水印校验,部署简单,社区生态好,但极限吞吐不如 vLLM。
- TensorRT-LLM:NVIDIA 官方方案,深度优化 kernel,支持 FP8 量化,单卡性能极致,但编译周期长、灵活性低,适合模型稳定后的极致优化阶段。
选型不是"哪个最好"的问题,而是"当前阶段最需要什么"的问题。PoC 阶段优先 TGI 快速验证,规模化阶段转向 vLLM 提升吞吐,极致优化阶段再考虑 TensorRT-LLM。
三、生产级部署:从单实例到弹性伸缩的完整实现
以下是基于 vLLM 的生产级部署方案,包含动态批处理、健康检查与弹性伸缩配置:
# docker-compose.yml — vLLM 生产部署核心配置
version: "3.8"
services:
vllm-server:
image: vllm/vllm-openai:latest
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
command: >
--model /models/qwen2-7b-instruct
--served-model-name qwen2-7b
--max-model-len 8192
--gpu-memory-utilization 0.90
--max-num-seqs 64
--enable-prefix-caching
--dtype float16
environment:
- VLLM_WORKER_MULTIPROC_METHOD=spawn
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
ports:
- "8000:8000"
volumes:
- ./models:/models
// Spring Boot — LLM 请求客户端,含重试、超时与熔断
@Service
public class LlmInferenceClient {
private final WebClient webClient;
private final CircuitBreaker circuitBreaker;
public LlmInferenceClient(WebClient.Builder builder,
CircuitBreakerRegistry registry) {
this.webClient = builder
.baseUrl("http://vllm-server:8000")
// 连接超时 5 秒,读取超时 60 秒(流式响应需要较长窗口)
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.responseTimeout(Duration.ofSeconds(60))))
.build();
this.circuitBreaker = registry.circuitBreaker("llm-inference");
}
/**
* 流式调用 LLM 推理接口,通过 SSE 逐 Token 返回结果
* 熔断器保护:连续 5 次失败后进入 OPEN 状态,30 秒后尝试半开恢复
*/
public Flux<String> streamChat(String prompt, int maxTokens) {
Map<String, Object> requestBody = Map.of(
"model", "qwen2-7b",
"messages", List.of(Map.of("role", "user", "content", prompt)),
"max_tokens", maxTokens,
"stream", true
);
return circuitBreaker.decorateSupplier(() ->
webClient.post()
.uri("/v1/chat/completions")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody)
.retrieve()
.bodyToFlux(String.class)
// 过滤 SSE 心跳帧,只保留有效 Token
.filter(line -> line.startsWith("data: ") && !line.contains("[DONE]"))
.map(line -> extractContent(line))
.onErrorResume(WebClientRequestException.class, e ->
Flux.just("[ERROR] 推理服务暂时不可用,请稍后重试"))
).get();
}
private String extractContent(String sseLine) {
// 从 SSE 帧中提取 content 字段
String json = sseLine.substring(6);
return JsonPath.read(json, "$.choices[0].delta.content");
}
}
关键配置说明:--gpu-memory-utilization 0.90 预留 10% 显存给系统开销,避免 OOM;--enable-prefix-caching 对重复前缀的 Prompt 启用 KV Cache 复用,可降低 30%-50% 的重复推理成本;--max-num-seqs 64 控制最大并发序列数,防止显存溢出。
四、显存墙与冷启动:部署方案的隐性代价
任何 LLM 部署方案都不是免费的午餐,以下是必须正视的 Trade-offs:
显存墙问题:GPU 显存是硬约束。7B 模型 FP16 约需 14GB 显存,加上 KV Cache 和运行时开销,单卡 A100(80GB)在 max-model-len=8192 下最多支撑约 60 并发序列。若业务需要 128K 上下文,单请求的 KV Cache 就可能吃掉半张卡。解决方案是量化(INT8/INT4),但量化会带来精度损失,尤其是对长尾知识的召回率下降。
冷启动延迟:模型加载到 GPU 的耗时通常在 30-120 秒。弹性伸缩场景下,新 Pod 启动期间流量会被已有实例承担,可能导致级联过载。生产环境中需要预热池(Warm Pool)策略,保持一定数量的待命实例。
批处理与延迟的矛盾:Dynamic Batching 通过合并请求提升吞吐,但等待组 batch 的窗口会增加首 Token 延迟。vLLM 的 Continuous Batching 缓解了这一问题,但在低 QPS 时,批处理收益有限,反而增加了调度开销。
成本与一致性的取舍:Prefix Caching 能显著降低重复 Prompt 的推理成本,但缓存失效策略(LRU)可能导致相同 Prompt 在不同时刻得到不同结果(缓存命中时跳过了部分推理步骤),在需要严格确定性的场景中需要谨慎使用。
五、总结
LLM 服务部署是一项系统工程,核心决策链路为:推理引擎选型 → 量化策略 → 批处理调度 → 弹性伸缩 → 流量治理。落地建议如下:
- 起步阶段:用 TGI 或 vLLM 默认配置快速上线,优先验证模型效果与业务匹配度,不必过早优化。
- 规模化阶段:启用 Prefix Caching 和 Continuous Batching,将 GPU 利用率从 30% 提升到 80% 以上,同时引入熔断与降级机制保障可用性。
- 极致优化阶段:评估 TensorRT-LLM + INT8/FP8 量化方案,配合 Warm Pool 策略解决冷启动问题,最终实现成本与延迟的平衡。
部署没有银弹,每个阶段的选择都意味着对某些指标的妥协。关键是明确当前阶段的核心矛盾,用数据驱动决策,而非盲目追求"最优方案"。
更多推荐


所有评论(0)