vLLM 容器化部署实战:如何在云服务器上跑起高并发大模型推理服务

云服务器 GPU 资源那么贵,怎么部署大模型才能兼顾性能与成本?本文用 vLLM + Docker 实战部署 Qwen2.5/DeepSeek 等主流模型,附完整配置文件与压测数据,手把手教你把模型跑出生产级性能。


为什么选 vLLM?

目前主流的大模型推理框架有三个:

框架 特点 适用场景
vLLM PagedAttention、Tensor Parallelization、连续批处理 高并发、生产级部署
HF Transformers 简单易用、生态丰富 实验、小规模推理
TGI (Text Generation Inference) 量化优化、OpenAI 兼容 HuggingFace 模型快速部署

vLLM 的核心优势:

markdown 复制代码
vLLM = PagedAttention(显存管理革命)
     + Continuous Batching(吞吐量提升 10-23 倍)
     + Tensor Parallelism(多卡并行)
     + 量化支持(AWQ/SGPTQ)

实测数据(单卡 A100 80G,Qwen2.5-7B):

指标 HF Transformers vLLM 提升
Throughput (tokens/s) 28 312 11x
Latency P50 (ms) 850 95 9x
Latency P99 (ms) 2100 280 7.5x
GPU Memory 14.8 GB 8.2 GB 节省 45%

环境准备

硬件要求

ini 复制代码
最低配置:
├── GPU:NVIDIA A100 40G 或 L20 48G(推荐)
├── CPU:8 核 +(推理调度用)
├── 内存:32 GB+
└── 存储:50 GB+(模型文件)

生产推荐:
├── 双卡 A100 80G(TP=2)
└── 或单卡 H100 80G

安装 NVIDIA 驱动和 Docker

bash 复制代码
# 1. 安装 NVIDIA 驱动(Ubuntu 22.04)
sudo apt update
sudo apt install -y nvidia-driver-535

# 重启后验证
nvidia-smi
# 预期输出:
# +------------------------------------------------------------------+
# | NVIDIA-SMI 535.161.06   Driver Version: 535.161.06   CUDA: 12.2 |
# +------------------------------------------------------------------+
# | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Unc. |
# |   0  NVIDIA A100 80G...  Off  | 00000000:00:07.0 Off |            0 |
# +------------------------------------------------------------------+

# 2. 安装 NVIDIA Container Toolkit
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/nvidia-docker/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-keyring.gpg
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt update
sudo apt install -y nvidia-container-toolkit
sudo systemctl restart docker

# 3. 验证 Docker + NVIDIA 集成
docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi

vLLM 快速启动(Docker 方式)

方法一:直接用 PyTorch 镜像

bash 复制代码
# 拉取镜像(推荐 vLLM 最新版)
docker pull nvidia/cuda:12.1.0-base-ubuntu22.04

# 方式一:快速体验(以 Qwen2.5-7B 为例)
docker run --gpus all \
    -p 8000:8000 \
    -v ~/.cache/huggingface:/root/.cache/huggingface \
    --env HF_TOKEN="your_huggingface_token" \
    vllm/vllm-openai:latest \
    --model Qwen/Qwen2.5-7B-Instruct \
    --tensor-parallel-size 1 \
    --port 8000

方法二:Dockerfile 定制(生产推荐)

dockerfile 复制代码
# Dockerfile.vllm
FROM nvidia/cuda:12.1.0-base-ubuntu22.04

ENV DEBIAN_FRONTEND=noninteractive
ENV PYTHON_VERSION=3.10

# 安装依赖
RUN apt-get update && apt-get install -y \
    python3.10 \
    python3-pip \
    python3.10-venv \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/*

# 安装 vLLM
RUN pip3 install vllm==0.6.3.post1

# 预下载模型(可选,减少首次启动时间)
ARG MODEL_NAME="Qwen/Qwen2.5-7B-Instruct"
ENV MODEL_NAME=${MODEL_NAME}

WORKDIR /app

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

EXPOSE 8000

CMD ["python3", "-m", "vllm.entrypoints.openai.api_server", \
     "--model", "${MODEL_NAME}", \
     "--tensor-parallel-size", "1", \
     "--port", "8000", \
     "--gpu-memory-utilization", "0.9"]
bash 复制代码
# 构建镜像
docker build -t my-vllm:latest \
    --build-arg MODEL_NAME="Qwen/Qwen2.5-7B-Instruct" \
    -f Dockerfile.vllm .

# 运行
docker run -d \
    --gpus all \
    --name vllm-qwen \
    -p 8000:8000 \
    -v /data/models:/root/.cache/huggingface \
    --restart unless-stopped \
    --shm-size=16g \
    my-vllm:latest

OpenAI 兼容 API 使用

vLLM 提供与 OpenAI API 100% 兼容的接口:

python 复制代码
# 安装客户端
pip install openai

# Python 调用示例
from openai import OpenAI

client = OpenAI(
    api_key="EMPTY",  # vLLM 不需要 API Key
    base_url="http://localhost:8000/v1"
)

# 同步调用
response = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=[
        {"role": "system", "content": "你是一个有帮助的AI助手。"},
        {"role": "user", "content": "用 Python 写一个快速排序"}
    ],
    temperature=0.7,
    max_tokens=512
)

print(response.choices[0].message.content)

流式输出

python 复制代码
# 流式调用(适合实时展示)
stream = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=[{"role": "user", "content": "解释一下什么是 RESTful API"}],
    stream=True,
    max_tokens=1024
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

批量推理

python 复制代码
# 批量请求(提升吞吐量)
import asyncio

async def batch_inference(prompts: list, batch_size: int = 10):
    """批量推理:比逐条调用快 5-10 倍"""
    results = []
    
    for i in range(0, len(prompts), batch_size):
        batch = prompts[i:i + batch_size]
        tasks = [
            client.chat.completions.create(
                model="Qwen/Qwen2.5-7B-Instruct",
                messages=[{"role": "user", "content": p}],
                max_tokens=256
            )
            for p in batch
        ]
        batch_results = await asyncio.gather(*tasks)
        results.extend([r.choices[0].message.content for r in batch_results])
    
    return results

# 使用示例
prompts = [
    "什么是 Kubernetes?",
    "Docker 和 Podman 有什么区别?",
    "如何优化 PostgreSQL 查询性能?",
]

results = asyncio.run(batch_inference(prompts))
for q, a in zip(prompts, results):
    print(f"Q: {q}\nA: {a[:100]}...\n")

多卡并行部署(Tensor Parallelism)

当模型太大,单卡放不下时,使用 Tensor Parallelism:

bash 复制代码
# 8B 模型,单卡 A100 80G 够用
# 14B+ 模型,需要多卡

# 2 卡并行部署 DeepSeek-14B
docker run -d \
    --gpus '"device=0,1"' \
    --name vllm-deepseek \
    -p 8000:8000 \
    -v /data/models:/root/.cache/huggingface \
    --shm-size=32g \
    vllm/vllm-openai:latest \
    --model deepseek-ai/DeepSeek-V2.5 \
    --tensor-parallel-size 2 \
    --port 8000 \
    --gpu-memory-utilization 0.9
python 复制代码
# 多卡部署时,代码无需修改,vLLM 自动处理
client = OpenAI(base_url="http://localhost:8000/v1")

# 14B 模型(2卡),吞吐量是单卡的 1.8x
response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V2.5",
    messages=[{"role": "user", "content": "写一个 Web 服务器"}],
    max_tokens=1024
)

性能压测与调优

压测脚本

python 复制代码
#!/usr/bin/env python3
"""vLLM 性能压测工具"""
import time
import statistics
from openai import OpenAI

client = OpenAI(
    api_key="EMPTY",
    base_url="http://localhost:8000/v1"
)

def benchmark_concurrent(num_requests: int, concurrent: int):
    """并发压测"""
    import concurrent.futures
    
    def single_request():
        start = time.time()
        client.chat.completions.create(
            model="Qwen/Qwen2.5-7B-Instruct",
            messages=[{"role": "user", "content": "写一个快速排序"}],
            max_tokens=512
        )
        return time.time() - start
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=concurrent) as executor:
        start_time = time.time()
        futures = [executor.submit(single_request) for _ in range(num_requests)]
        latencies = [f.result() for f in futures]
        total_time = time.time() - start_time
    
    print(f"=== 压测结果 ===")
    print(f"总请求数:{num_requests}")
    print(f"并发数:{concurrent}")
    print(f"总耗时:{total_time:.2f}s")
    print(f"QPS:{num_requests/total_time:.2f}")
    print(f"P50 延迟:{statistics.median(latencies)*1000:.0f}ms")
    print(f"P99 延迟:{sorted(latencies)[int(len(latencies)*0.99)]*1000:.0f}ms")
    print(f"平均延迟:{statistics.mean(latencies)*1000:.0f}ms")

# 运行压测
benchmark_concurrent(num_requests=100, concurrent=10)

常见调优参数

bash 复制代码
# vLLM 关键参数说明

--gpu-memory-utilization 0.9    # GPU 显存利用率,越高吞吐量越大
--max-num-batched-tokens 8192   # 单批最大 token 数
--max-num-seqs 256              # 最大并发序列数
--block-size 16                 # KV Cache 块大小(影响显存碎片)
--enable-chunked-prefill        # 启用分块预填充,降低首 token 延迟
--enforce-eager                 # 禁用 CUDA Graph(调试用)
--trust-remote-code             # 允许执行远程代码(某些模型需要)

与腾讯云 GPU 云服务器集成

在腾讯云 CVM 上部署

bash 复制代码
# 1. 创建 GPU 实例(GN7vwL 或 GN10Xp)
# 推荐:GN10Xp(双卡 V100 32G)或 GN7vwL(单卡 A100 40G)

# 2. 连接服务器
ssh root@your-server-ip

# 3. 安装 Docker(Ubuntu 22.04)
curl -fsSL https://get.docker.com | sh

# 4. 验证 GPU
nvidia-smi

# 5. 部署 vLLM
docker run -d \
    --gpus all \
    --name vllm-production \
    -p 8000:8000 \
    -v /root/.cache/huggingface:/root/.cache/huggingface \
    --restart unless-stopped \
    --shm-size=16g \
    -e HF_TOKEN="your_token" \
    vllm/vllm-openai:latest \
    --model Qwen/Qwen2.5-14B-Instruct \
    --tensor-parallel-size 2 \
    --port 8000 \
    --gpu-memory-utilization 0.85 \
    --max-num-batched-tokens 16384

# 6. 配置 nginx 反向代理(可选)
# apt install nginx
# 配置负载均衡和多实例

配置 systemd 服务(生产环境)

ini 复制代码
# /etc/systemd/system/vllm.service
[Unit]
Description=vLLM OpenAI API Server
After=network.target docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/docker start vllm-production
ExecStop=/usr/bin/docker stop vllm-production
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
bash 复制代码
sudo systemctl daemon-reload
sudo systemctl enable vllm.service
sudo systemctl start vllm.service
sudo systemctl status vllm.service

量化部署(省钱方案)

INT8 / AWQ 量化

bash 复制代码
# vLLM 支持 AWQ 量化,显存占用减少 60%,速度反而更快
docker run -d \
    --gpus all \
    --name vllm-quantized \
    -p 8001:8000 \
    vllm/vllm-openai:latest \
    --model Qwen/Qwen2.5-14B-Instruct-AWQ \
    --quantization awq \
    --tensor-parallel-size 1 \
    --port 8000
模型版本 显存占用 吞吐量 精度损失
Qwen2.5-14B (FP16) 28 GB 180 tok/s
Qwen2.5-14B (INT8) 16 GB 220 tok/s < 1%
Qwen2.5-14B (AWQ) 11 GB 260 tok/s < 2%
Qwen2.5-7B (FP16) 14 GB 310 tok/s
Qwen2.5-7B (AWQ) 5 GB 380 tok/s < 2%

结论:AWQ 量化后,一张 A100 可以跑 14B 模型,显存节省 60%,吞吐量反而更高!


总结

lua 复制代码
vLLM 部署最佳实践:
├── 环境:Docker + NVIDIA Container Toolkit + A100/H100
├── 推荐镜像:vllm/vllm-openai:latest
├── 并发优化:--max-num-batched-tokens 调大
├── 显存优化:--gpu-memory-utilization 0.85-0.9
├── 量化:AWQ 量化是性价比最高的选择
├── 监控:Prometheus + Grafana 监控 QPS 和延迟
└── 多卡:--tensor-parallel-size N(N卡并行)

推荐配置(按场景):
├── 7B 模型 → 单卡 A100 40G / L20,Docker 直接跑
├── 14B 模型 → 双卡 A100 40G 或单卡 A100 80G
├── 72B 模型 → 四卡 A100 80G,TP=4
└── 成本敏感 → AWQ 量化,单卡跑 14B!

关于作者

长期关注大模型应用落地与云服务器实战,专注技术在企业场景中的落地实践。

个人博客:yunduancloud.icu ------ 持续更新云计算、AI大模型实战教程,欢迎访问交流。

相关推荐
LIO1 小时前
Pinia 极简指南:Vue 3 官方状态管理库
前端·vue.js
燐妤2 小时前
前端HTML编程2:深入学习表单与表格
前端·学习·html5
朝阳392 小时前
react【实战】首页 -- 响应式导航栏(含带联动动画的搜索框)
前端·react.js·前端框架
贾铭2 小时前
如何实现一个网页版的剪映(五)如何跳转到视频某一帧
前端·后端
林恒smileZAZ2 小时前
CSS 滚动驱动动画(scroll-timeline):无 JS 实现滚动特效
前端·javascript·css
俺不会敲代码啊啊啊2 小时前
el-table实现行拖拽(包含展开项)
前端·vue.js·typescript
LIO2 小时前
React Router 极简指南(v6+)
前端·react.js
明月_清风2 小时前
从 AST 视角看透前端工程化:一条编译管线如何串联起所有工具
前端
架构源启2 小时前
2026 进阶篇:Spring Boot响应式编程 + Spring AI 1.1.4 流式实战 + Vue前端完整实现(避坑指南)
java·前端·vue.js·人工智能·spring boot·spring·ai编程