生产级 LLM Serving 不只是启动推理引擎,还需要保证服务的安全性、可靠性、扩展性和可观测性。
1. 整体架构
LLM Production Serving
├── API Layer
│ ├── OpenAI-compatible API
│ ├── SSE / Streaming
│ ├── Authentication
│ └── Rate Limiting
│
├── Request Management
│ ├── Queue / Concurrency
│ ├── Timeout / Cancellation
│ ├── Load Balancing
│ └── Backpressure
│
├── Runtime & Resources
│ ├── GPU Scheduling
│ ├── Model Replicas
│ └── Autoscaling
│
└── Operations
├── Health Checks
├── Metrics / Monitoring
├── Logging / Tracing
└── Deployment / Rollback
典型架构:
Internet
↓
API Gateway
┌──────────┼──────────┐
│ │ │
Auth TLS Rate Limit
└──────────┼──────────┘
↓
Load Balancer
↓
┌───────────┼───────────┐
↓ ↓ ↓
vLLM-1 vLLM-2 vLLM-3
↓ ↓ ↓
GPU GPU GPU
Metrics → Prometheus → Grafana
Logs → Logging System
Health → Load Balancer / Orchestrator
Scaling ← Queue / Latency / GPU Metrics
2. OpenAI-compatible API
现代推理引擎通常提供与 OpenAI API 风格兼容的 HTTP 接口。
例如:
POST /v1/chat/completions
Authorization: Bearer <api-key>
Content-Type: application/json
请求:
{
"model": "qwen",
"messages": [
{
"role": "user",
"content": "Hello"
}
],
"stream": false
}
响应通常包含:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "Hello!"
}
}
]
}
常见 Endpoint:
| Endpoint | 作用 |
|---|---|
/v1/chat/completions | 聊天生成 |
/v1/completions | 文本补全 |
/v1/embeddings | Embedding,需兼容模型 |
/v1/models | 模型列表 |
OpenAI-compatible 不意味着所有引擎对 Tool Calling、Structured Outputs 和 Reasoning 的支持完全一致。
3. SSE / Streaming
LLM 通常使用 SSE 风格的 HTTP Streaming,将生成内容逐步发送给客户端。
Client Request
↓
Server Prefill
↓
First Token
↓
Token 1
↓
Token 2
↓
Token 3
↓
Stream Complete
请求:
{
"model": "qwen",
"messages": [
{
"role": "user",
"content": "Hello"
}
],
"stream": true
}
响应通常使用:
Content-Type: text/event-stream
示例:
data: {"choices":[{"delta":{"content":"Hello"}}]}
data: {"choices":[{"delta":{"content":" world"}}]}
data: [DONE]
这里传输的是增量消息 Chunk,不保证一个 Chunk 恰好对应一个 Token。
Nginx Streaming
location /v1/ {
proxy_pass http://vllm:8000;
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 300s;
}
关键配置:
proxy_buffering off:避免 Nginx 缓冲生成内容。proxy_read_timeout:限制连续两次上游读取之间的等待时间。proxy_http_version 1.1:使用 HTTP/1.1 代理上游。
流式请求也需要处理客户端主动断开连接的情况,避免用户已经取消生成,而 GPU 仍然继续工作。
4. Authentication 与 Rate Limiting
推理资源通常比较昂贵,不能直接把未经保护的模型服务暴露到公网。
Authentication
常见方式:
- API Key。
- JWT。
- OAuth / OIDC。
- 内部服务身份认证。
例如:
Authorization: Bearer <api-key>
Rate Limiting
可以限制:
| 维度 | 含义 |
|---|---|
| RPM | Requests Per Minute |
| TPM | Tokens Per Minute |
| Concurrent Requests | 同时进行的请求数量 |
| Max Input Tokens | 单请求最大输入长度 |
| Max Output Tokens | 单请求最大输出长度 |
例如:
User A:
60 RPM
100,000 TPM
5 Concurrent Requests
对于 LLM Serving,仅限制 RPM 可能不够。
因为两个请求的成本可能差异巨大:
Request A: 100 Input + 50 Output Tokens
Request B: 100K Input + 8K Output Tokens
因此最好同时约束 Token 预算和并发量。
安全边界
vLLM 的 --api-key 仅保护部分 API 路径,并非所有服务端点都经过认证。生产环境不能只依赖这一参数,需要通过反向代理和网络策略保护其他管理端点。
5. Queue、Concurrency 与 Backpressure
一个推理服务通常有有限的 GPU 计算和 KV Cache 资源。
Incoming Requests
↓
Admission Control
↓
Queue
↓
Scheduler
↓
Running Requests
↓
GPU
Concurrency
Concurrency 表示同时处于处理过程中的请求数量。
需要区分:
- API 层的 In-flight Requests。
- 推理引擎中正在运行的 Sequences。
- 正在排队的 Requests。
这些数量不一定相同。
Queue
当请求超过 GPU 当前处理能力时,部分请求需要等待。
Queue 可以吸收短时间的流量突发,但排队时间过长会使 TTFT 恶化。
Backpressure
Backpressure 是系统过载时主动限制新工作进入的机制。
例如:
Queue < Limit
↓
Accept Request
Queue >= Limit
↓
Reject / Throttle
↓
HTTP 429 / 503
常见措施:
- 限制最大并发量。
- 设置最大排队请求数。
- 限制排队等待时间。
- 拒绝超过容量的新请求。
- 对可信的可重试错误使用退避策略。
无限增加 Queue 并不能增加 GPU 计算能力,只会让延迟持续增长。
6. Timeout 与 Cancellation
LLM 请求通常存在多个不同的超时。
| Timeout | 作用 |
|---|---|
| Connection Timeout | 建立连接的最长等待时间 |
| Queue Timeout | 请求允许排队多久 |
| TTFT Timeout | 等待第一个输出的最长时间 |
| Read / Idle Timeout | 两次数据读取之间允许的空闲时间 |
| Total Request Timeout | 整个请求的最大执行时间 |
不同 API Gateway 和推理引擎不一定原生支持所有类型,需要按具体系统实现。
Cancellation
用户关闭页面或点击 Stop Generation 时:
Browser Cancel
↓
API Gateway
↓
Inference Server
↓
Cancel Request
↓
Release KV Cache / Scheduler Resources
生产服务应确保取消信号能够传递到推理引擎。
对于 Streaming 请求,尤其需要关注网络断开与服务端任务清理之间的关系。
Retry
不是所有失败都应该立即重试。
例如 GPU 已经过载,如果大量客户端同时重试,可能形成 Retry Storm。
常见做法是:
- Exponential Backoff。
- Jitter。
- Retry Limit。
- 仅对适合重试的错误重试。
对于已经部分输出的流式生成,重试还可能产生重复内容或额外计费,需要谨慎处理。
7. Load Balancing
多实例推理部署:
Load Balancer
↓
┌────────────┼────────────┐
↓ ↓ ↓
vLLM-1 vLLM-2 vLLM-3
↓ ↓ ↓
GPU GPU GPU
常见策略:
| 策略 | 说明 |
|---|---|
| Round Robin | 轮流分配 |
| Least Connections | 选择连接更少的实例 |
| Least Loaded | 根据实际负载分配 |
| Queue-aware Routing | 根据等待请求数分配 |
| Cache-aware Routing | 尽量提高 Prefix Cache 命中率 |
对于 LLM,普通 Round Robin 不一定最优。
因为请求长度差异大,两个拥有相同连接数的 GPU 实例,实际负载可能完全不同。
Cache-aware Routing 则可以利用多个请求间相似的 Prompt Prefix,减少重复计算。
但负载均衡策略也需要兼顾缓存命中率与负载公平性。
8. GPU Scheduling 与 Autoscaling
GPU Scheduling
推理引擎内部 Scheduler 负责将请求安排到 GPU 执行。
例如:
Queue
↓
Continuous Batching
↓
Prefill / Decode
↓
KV Cache Allocation
↓
GPU Execution
这与 Kubernetes 等平台的 GPU Pod 调度不是同一件事:
- 推理引擎 Scheduler:调度 Token 和请求。
- 容器编排 Scheduler:调度容器到 GPU 节点。
Autoscaling
Autoscaling 根据负载增加或减少推理实例。
例如:
Incoming Traffic ↑
↓
Queue Length ↑
↓
Scale Out
↓
More Model Replicas
常用扩缩容依据:
- Queue Length。
- TTFT / TPOT。
- Requests/s。
- Tokens/s。
- GPU Memory / KV Cache Usage。
- GPU Utilization。
不建议只使用 GPU Utilization 作为唯一指标,因为 GPU 忙碌程度不一定能反映排队和用户体验。
LLM Autoscaling 的特殊问题
启动新的模型实例可能需要:
- 分配 GPU。
- 拉取或加载模型权重。
- 初始化推理引擎。
- 分配 KV Cache。
- 完成预热。
因此 LLM 实例的冷启动成本可能很高。
扩容不是瞬时完成的,需要结合流量预测和合理的最小副本数。
9. Health Check
需要区分:
| 类型 | 含义 |
|---|---|
| Liveness | 进程是否仍然正常运行 |
| Readiness | 实例是否准备好接收请求 |
| Startup | 模型初始化是否完成 |
例如:
Model Loading
↓
Startup Not Ready
↓
Model Loaded
↓
Readiness Passed
↓
Receive Traffic
vLLM 提供 /health 等用于服务健康检查的端点。
注意:健康检查成功不代表实例一定有足够 KV Cache 容量接收新请求。
因此生产环境还需要结合 Queue 和资源指标判断实际服务能力。
10. Metrics、Logging 与 Monitoring
Metrics
生产环境通常使用:
vLLM Metrics
↓
Prometheus
↓
Grafana
↓
Dashboards / Alerts
vLLM 提供 Prometheus-compatible /metrics Endpoint。
重点监控:
| 分类 | 核心指标 |
|---|---|
| 请求 | Requests/s、Error Rate |
| 延迟 | TTFT、TPOT、P95/P99 Latency |
| 队列 | Waiting / Running Requests |
| 吞吐 | Input / Output Tokens/s |
| 显存 | KV Cache Usage、GPU VRAM |
| 缓存 | Prefix Cache Hit Rate |
| 资源 | GPU Utilization、GPU Memory |
| 质量保障 | Timeout、OOM、Rejected Requests |
其中 Running Requests、KV Cache 使用率、Prefix Cache Hits 等均属于 vLLM 可观测指标。
Logging
日志用于记录具体请求和系统事件,例如:
Request ID
Timestamp
Model Version
Status Code
Latency
Input / Output Token Count
Error Type
生产环境不应该默认完整记录用户 Prompt 和模型回复,尤其当其中可能包含敏感数据时。
Tracing
Tracing 关注单个请求经过不同服务的执行路径。
Request ID
↓
API Gateway
↓
Application
↓
Retriever / Tools
↓
Inference Server
↓
Response
对于 RAG 和 Agent 应用,Tracing 有助于判断延迟究竟来自检索、工具调用、排队还是模型生成。
11. Deployment、Rolling Update 与 Rollback
发布流程
Model / Container Version
↓
Deployment
↓
Model Loading
↓
Readiness Check
↓
Accept Traffic
↓
Monitoring
生产环境应明确固定:
- Model Revision / Weight Version。
- Tokenizer / Chat Template。
- Quantization Format。
- Inference Engine Version。
- Serving Configuration。
只记录模型名称通常不足以保证可复现部署。
Rolling Update
多实例情况下可以逐步更新:
vLLM-1: Old → New
vLLM-2: Old
vLLM-3: Old
新实例准备好后,再逐步替换其他旧实例。
Graceful Shutdown / Draining
停止旧实例时:
Stop Accepting New Requests
↓
Allow In-flight Requests to Finish
↓
Release Resources
↓
Terminate Instance
对于长时间 Streaming 的请求,还需要设置合理的最长 Drain 时间。
Rollback
如果新模型质量下降或性能出现异常:
New Model Version
↓
Monitoring Detects Problem
↓
Rollback
↓
Previous Stable Version
回滚不仅涉及 Docker Image,也需要保证模型权重、Tokenizer 和服务配置版本一致。
12. 部署方案选择
| 规模 | 常见架构 | 重点 |
|---|---|---|
| 学习 / 单用户 | 单 vLLM + GPU | 模型加载、API、性能测试 |
| 小型服务 | Reverse Proxy + vLLM | 认证、限流、日志 |
| 多 GPU 单实例 | vLLM/SGLang + TP | 模型容量与多 GPU |
| 多实例 Serving | Gateway + LB + 多个 Replica | 路由、容量、健康检查 |
| 大规模集群 | Kubernetes + GPU Operator + Serving | 扩缩容、调度、运维 |
Kubernetes 不是 LLM Serving 的必要条件。对于单 GPU 或少量实例,Docker Compose 加反向代理通常已经能够满足初期部署需求。
总结
生产级 LLM Serving 主要需要解决五个问题:
| 问题 | 关键技术 |
|---|---|
| 如何安全提供 API? | Authentication、TLS、Rate Limiting |
| 如何防止请求过载? | Queue、Concurrency、Backpressure、Timeout |
| 如何扩展吞吐量? | Load Balancing、GPU Replicas、Autoscaling |
| 如何发现性能与可靠性问题? | Metrics、Logging、Tracing、Health Check |
| 如何安全上线新版本? | Version Pinning、Readiness、Draining、Rollback |
核心架构:
Client
↓
API Gateway
↓
Authentication / Rate Limit
↓
Load Balancer
↓
Inference Server
├── Queue / Scheduler
├── KV Cache Manager
└── GPU Execution
↓
Streaming Response
Observability:
Metrics + Logs + Traces
Operations:
Health Check + Scaling + Deployment
生产级 LLM Serving 的目标不只是让模型能够运行,而是在给定 GPU 资源下,持续提供安全、可预测、可扩展的推理服务。