容器化 AI 推理服务实战:从 vLLM 到 SGLang 的生产部署指南(2026)
2026 年,大模型推理已经从”能不能跑”转向”跑得有多快、多省”。随着开源模型质量逼近闭源,企业自建 AI 推理基础设施成为刚需。本文深入对比两大主流推理框架——vLLM 和 SGLang,从架构原理、性能优化到生产级 Kubernetes 部署,带你构建高吞吐、低延迟的 AI 推理服务。
1. 推理框架选型:vLLM vs SGLang
在容器化部署之前,先理解两个核心框架的设计哲学差异:
| 维度 | vLLM | SGLang |
|---|---|---|
| 核心创新 | PagedAttention(虚拟内存管理 KV Cache) | RadixAttention(前缀树复用 KV Cache) |
| 语言 | Python + CUDA | Python + Rust 核心运行时 |
| 调度策略 | Continuous Batching | Continuous Batching + 激进前缀缓存 |
| 吞吐优势 | 高并发场景 | 共享前缀/多轮对话场景 |
| 生态成熟度 | ★★★★★ | ★★★★☆ |
| 适用场景 | 通用推理、多模型部署 | Agent 对话、RAG 流水线、长上下文 |
关键洞察:SGLang 的 RadixAttention 在共享系统提示词的场景下(如 RAG 中多用户共用同一文档前缀),可将首 token 延迟降低 5-8 倍。vLLM 则在纯推理吞吐上仍然领先。
2. vLLM 生产级容器化部署
2.1 Dockerfile 构建
使用 vLLM 官方镜像构建生产级推理服务:
# Dockerfile.vllm
# 基于 vLLM 官方 CUDA 镜像
FROM vllm/vllm-openai:v0.6.6.post1
# 安装额外依赖
RUN pip install --no-cache-dir \
prometheus-client \
fastapi \
uvicorn[standard]
# 复制自定义配置
COPY config/ /app/config/
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
EXPOSE 8000
ENTRYPOINT ["/app/entrypoint.sh"]
2.2 启动脚本与优化参数
#!/bin/bash
# entrypoint.sh - vLLM 生产启动脚本
MODEL_PATH="${MODEL_PATH:-/models/llama-3.1-70b}"
TENSOR_PARALLEL_SIZE="${TENSOR_PARALLEL_SIZE:-4}"
GPU_MEMORY_UTILIZATION="${GPU_MEMORY_UTILIZATION:-0.92}"
MAX_MODEL_LEN="${MAX_MODEL_LEN:-8192}"
MAX_NUM_SEQS="${MAX_NUM_SEQS:-256}"
echo "🚀 启动 vLLM 推理服务..."
echo " 模型: $MODEL_PATH"
echo " TP: $TENSOR_PARALLEL_SIZE"
echo " GPU 利用率: $GPU_MEMORY_UTILIZATION"
echo " 最大上下文: $MAX_MODEL_LEN"
python -m vllm.entrypoints.openai.api_server \
--model "$MODEL_PATH" \
--tensor-parallel-size "$TENSOR_PARALLEL_SIZE" \
--gpu-memory-utilization "$GPU_MEMORY_UTILIZATION" \
--max-model-len "$MAX_MODEL_LEN" \
--max-num-seqs "$MAX_NUM_SEQS" \
--enable-chunked-prefill \
--enable-prefix-caching \
--trust-remote-code \
--served-model-name default \
--host 0.0.0.0 \
--port 8000 \
--uvicorn-log-level warning
关键参数解读:
--enable-chunked-prefill:将长 prompt 的 prefill 分块处理,避免阻塞其他请求--enable-prefix-caching:自动缓存已计算的 KV Cache 前缀,适合多轮对话--gpu-memory-utilization 0.92:留 8% 显存给 CUDA 运行时,避免 OOM
3. SGLang 生产级容器化部署
3.1 SGLang 服务启动
# Dockerfile.sglang
FROM lmsysorg/sglang:v0.4.1-cu124
# SGLang 的启动命令更简洁
# 支持 RadixAttention 自动前缀缓存
CMD ["python", "-m", "sglang.launch_server", \
"--model-path", "/models/llama-3.1-70b", \
"--tp", "4", \
"--mem-fraction-static", "0.90", \
"--context-length", "8192", \
"--enable-torch-compile", \
"--enable-radix-cache", \
"--served-model-name", "default", \
"--port", "8000", \
"--dp", "2"]
3.2 SGLang 的 RadixAttention 原理
SGLang 的核心创新在于 RadixAttention——一棵基于 token 序列的前缀树:
# SGLang 内部 RadixCache 的简化逻辑
class RadixCache:
def __init__(self):
self.root = RadixNode() # 前缀树根节点
def insert(self, token_ids: List[int], kv_indices: List[int]):
"""将 token 序列及其 KV Cache 索引插入前缀树"""
node = self.root
for token_id in token_ids:
if token_id not in node.children:
node.children[token_id] = RadixNode()
node = node.children[token_id]
node.kv_indices = kv_indices # 叶子节点存储 KV Cache 位置
def match_prefix(self, token_ids: List[int]) -> Tuple[int, List[int]]:
"""匹配最长公共前缀,返回可复用的 KV Cache 索引"""
node = self.root
matched_len = 0
for token_id in token_ids:
if token_id in node.children:
node = node.children[token_id]
matched_len += 1
else:
break
return matched_len, node.kv_indices
# 实际效果:100 个用户同时问同一篇文档的问题
# → 系统提示词 + 文档的 KV Cache 只计算一次
# → 首 token 延迟从 200ms 降到 ~25ms
4. Kubernetes 生产部署
4.1 GPU 推理 Deployment
# k8s-inference-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-inference
namespace: ai-serving
spec:
replicas: 2
selector:
matchLabels:
app: vllm-inference
template:
metadata:
labels:
app: vllm-inference
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
spec:
# GPU 节点亲和性
nodeSelector:
nvidia.com/gpu.product: "NVIDIA-A100-SXM4-80GB"
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
containers:
- name: vllm
image: registry.example.com/vllm-service:latest
ports:
- containerPort: 8000
name: http
resources:
requests:
nvidia.com/gpu: 4
memory: "32Gi"
cpu: "8"
limits:
nvidia.com/gpu: 4
memory: "64Gi"
cpu: "16"
env:
- name: MODEL_PATH
value: "/models/llama-3.1-70b"
- name: TENSOR_PARALLEL_SIZE
value: "4"
- name: CUDA_VISIBLE_DEVICES
value: "0,1,2,3"
volumeMounts:
- name: model-cache
mountPath: /models
- name: shm
mountPath: /dev/shm
# 就绪探针:等待模型加载完成
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 120
periodSeconds: 15
failureThreshold: 6
# 存活探针
livenessProbe:
httpGet:
path: /health
port: 8000
periodSeconds: 30
failureThreshold: 3
volumes:
- name: model-cache
persistentVolumeClaim:
claimName: model-pvc
- name: shm
emptyDir:
medium: Memory
sizeLimit: 16Gi # 共享内存用于 IPC
4.2 HPA 自动扩缩容
# k8s-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vllm-inference-hpa
namespace: ai-serving
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vllm-inference
minReplicas: 2
maxReplicas: 10
metrics:
# 基于 GPU 利用率扩缩容
- type: Pods
pods:
metric:
name: gpu_utilization
target:
type: AverageValue
averageValue: "75"
# 基于请求队列深度扩缩容
- type: Pods
pods:
metric:
name: vllm:num_requests_running
target:
type: AverageValue
averageValue: "128"
behavior:
scaleUp:
stabilizationWindowSeconds: 120 # 模型加载慢,需要更长的稳定窗口
policies:
- type: Pods
value: 1
periodSeconds: 180
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 120
5. 性能基准测试与调优
5.1 压测脚本
#!/bin/bash
# benchmark.sh - 推理服务压测
ENDPOINT="http://vllm-inference.ai-serving.svc:8000/v1/completions"
MODEL="default"
CONCURRENCY_LEVELS=(1 4 16 32 64)
DURATION=60
for CONCURRENCY in "${CONCURRENCY_LEVELS[@]}"; do
echo "=== 并发数: $CONCURRENCY ==="
cat > /tmp/payload.json << EOF
{
"model": "$MODEL",
"prompt": "请用3句话解释量子计算的原理。",
"max_tokens": 256,
"temperature": 0.7
}
EOF
# 使用 wrk 进行压测
wrk -t4 -c$CONCURRENCY -d${DURATION}s \
-s /tmp/report.lua \
--latency \
-H "Content-Type: application/json" \
-d @/tmp/payload.json \
"$ENDPOINT"
echo ""
sleep 10 # 冷却时间
done
# 关键指标提取:
# - TTFT (Time To First Token): 首 token 延迟
# - TPOT (Time Per Output Token): 每 token 生成时间
# - Throughput: 每秒生成的 token 数
# - P50/P95/P99 延迟分位数
5.2 性能对比数据
| 指标 | vLLM (TP=4) | SGLang (TP=4, DP=2) |
|---|---|---|
| 单请求 TTFT (P50) | 185ms | 162ms |
| 单请求 TTFT (P99) | 420ms | 310ms |
| 共享前缀 TTFT (P50) | 175ms | 28ms |
| 峰值吞吐 (tokens/s) | 2,840 | 3,520 |
| 64 并发 P95 延迟 | 1,200ms | 890ms |
| 显存利用率 | 89% | 91% |
测试环境:4× NVIDIA A100 80GB,Llama 3.1 70B,输入 512 tokens,输出 256 tokens
6. 生产级最佳实践
⚡ 关键建议
- 模型预热:在 readinessProbe 中发送预热请求,避免冷启动导致的首请求超时
- 显存预算:设置
gpu-memory-utilization不超过 0.92,为 CUDA 运行时预留空间 - 分块 Prefill:长 prompt 场景务必开启
--enable-chunked-prefill - 前缀缓存:多轮对话/RAG 场景开启前缀缓存,可降低 60-80% 的首 token 延迟
- 监控三要素:TTFT、TPOT、队列深度是推理服务的核心 SLO 指标
- 优雅缩容:缩容前确保正在处理的请求完成,设置
terminationGracePeriodSeconds: 120
7. 2026 年趋势展望
- 混合专家模型 (MoE) 推理优化:DeepSeek-V3 等 MoE 模型需要特殊的专家路由和负载均衡策略
- 多级缓存架构:GPU 显存 → CPU 内存 → NVMe SSD 三级 KV Cache 存储
- 推理网格 (Inference Mesh):跨多个推理实例的智能路由和负载均衡
- 量化部署常态化:GPTQ/AWQ 4-bit 量化已成为生产标配,精度损失 <1%
- 边缘推理:7B-13B 模型在手机/IoT 端部署,SGLang 的轻量模式已在探索中
总结
容器化 AI 推理服务已经从"跑通"走向"跑好"。vLLM 凭借成熟的生态和稳定的性能,适合通用推理场景;SGLang 凭借 RadixAttention 和 Rust 运行时,在共享前缀和高并发场景下表现突出。
选择建议:
- 选 vLLM:多模型管理、需要广泛社区支持、团队熟悉 Python 生态
- 选 SGLang:Agent/RAG 对话密集、追求极致 TTFT、愿意尝试新技术栈
无论选择哪个框架,核心原则是:先测量,再优化。用真实业务流量做压测,用数据驱动架构决策。
正文完