← blog AI Agent · 2026-08-04

本地部署 LLM 服务:从硬件到后端的完整基建指南

从硬件选型、显存估算、推理引擎选型到后端业务服务设计的完整本地 LLM 部署指南,以 27B 模型 + 8K 上下文 + 10 并发场景为线索,给出可落地的配置清单、成本估算、Docker Compose 编排和 FastAPI 业务服务骨架。

14 min read

本地部署 LLM 提供服务,基础设施分硬件、软件、运维三层。本文以「27B 模型 + 8K 上下文 + 最大 10 并发」的具体场景为线索,从显存估算、硬件选型、推理引擎、服务架构到后端业务代码,给出完整可落地的方案。

一、硬件基建

1. GPU / 算力

  • 核心瓶颈:显存(VRAM)决定能跑多大的模型、多大的并发。
  • 显存估算:参数量 × 精度字节数 ≈ 权重占用。
    • 7B 模型 FP16 ≈ 14GB,INT8 ≈ 7GB,INT4 ≈ 3.5GB。
    • 70B 模型 FP16 ≈ 140GB,需多卡(如 4×A100 80G)。
  • 常见卡型:
    • 消费级:RTX 4090(24GB)、RTX 5090(32GB)——适合小模型/实验。
    • 专业级:A100/H100(80GB)、L40S(48GB)、H20——适合正式服务。
    • 国产替代:昇腾 910B、寒武纪、沐曦等(需适配国产软件栈)。
  • KV Cache 也要占显存,长上下文 + 高并发会显著抬高需求。

2. 主机与扩展

  • CPU:多核(≥16 核)用于数据预处理、调度、tokenizer。
  • 内存:≥ 256GB 起步,用于加载权重到 CPU、KV cache 溢出、数据集。
  • 存储:NVMe SSD(Gen4/Gen5),模型加载和权重读取速度关键。
  • 扩展能力:选购带 8×PCIe 或 NVLink 的服务器,便于多卡改造。

3. 网络

  • 多卡互联:NVLink / PCIe 直连,跨卡张量并行时带宽决定性能。
  • 机房网络:万兆网卡,服务对外吞吐、集群通信。
  • 对外:负载均衡、CDN、带宽按需求估算。

4. 机房与供配电

  • 散热:GPU 发热量大,需液冷或高功率风冷。
  • 供电:单卡 350–700W,多卡需 UPS + 冗余电源。
  • 机架、制冷、消防、监控。

二、软件基建

1. 推理引擎(核心)

  • vLLM:业界主流,PagedAttention 高吞吐,支持连续批处理。
  • TGI(Hugging Face Text Generation Inference):工业级,功能全。
  • SGLang:RadixAttention,长上下文/多轮对话性能好。
  • TensorRT-LLM:NVIDIA,性能极致但部署复杂。
  • llama.cpp:CPU/边缘端轻量,适合小模型。
  • Ollama / LM Studio:快速上手,适合测试,生产慎用。

2. 量化与优化

  • 工具:GPTQ、AWQ、GGUF(llama.cpp)、bitsandbytes。
  • 目的:降显存、提吞吐,代价是精度损失。

3. 服务框架

  • API 层:OpenAI 兼容接口(vLLM/TGI 原生支持)。
  • 网关:Nginx / Kong / Envoy 做反向代理、限流、负载均衡。
  • 编排:Docker / Kubernetes(K8s + GPU 插件 nvidia-device-plugin)。

4. 模型获取与存储

  • 模型来源:Hugging Face、ModelScope(国内镜像)、本地私有化权重。
  • 管理:Model Registry、版本管理。

5. 前后端应用层

  • 框架:FastAPI / LangChain / LlamaIndex。
  • RAG:向量数据库(Milvus、Qdrant、pgvector)+ Embedding 模型。
  • 前端:Web UI(如 Open WebUI、Gradio)。

6. 监控与日志

  • 观测:Prometheus + Grafana、MLflow。
  • 指标:吞吐(tokens/s)、延迟(TTFT、TPOT)、GPU 利用率、显存占用。

三、运维与合规

  • 鉴权:API Key 管理、认证、租户隔离。
  • 治理:内容安全、敏感词过滤、审计日志。
  • 备份与容灾:模型权重备份、数据快照。
  • 安全:容器隔离、防火墙、密钥管理(Vault)。

四、按规模选型建议

场景参考配置
私域小服务(7B)1 张 RTX 4090 / A10,vLLM + Ollama
中型生产(13B–70B)双卡 A100/H100,vLLM + K8s
大型生产(70B+ 高并发)4×A100/H100 + NVLink,TensorRT-LLM + K8s + 网关
超大规模/多租户GPU 集群 + 调度(Ray/K8s)+ 弹性伸缩

关键提醒:显存是最大的成本与决策点;先明确模型规模、并发量、上下文长度,再反推硬件。生产环境优先选 vLLM + Docker/K8s + 监控 这套成熟组合。

五、27B 模型 10–20 并发:显存重算

针对 27B 模型 + 10–20 并发 这个具体场景,关键变量是量化精度和上下文长度。这个规模处于「单卡/双卡」交界处。

以 27B 模型为例(如 Qwen2.5-27B / Llama-3-27B):

项计算占用
权重 FP1627B × 2B~54GB
权重 INT8/FP827B × 1B~27GB
权重 INT427B × 0.5B~13.5GB
KV Cache(每并发@8K)约 0.9MB/token × 8192~7GB/序列
KV Cache 20 并发 @8K7GB × 20~140GB

关键点:20 并发 × 8K 上下文时,KV Cache 会吃掉 140GB,比权重还大。所以并发数和上下文长度是显存的最大变量,务必先定死。

推荐配置(生产主力,INT8 权重 + FP8 KV)

假设:8K 上下文、峰值 20 并发、连续批处理(vLLM 平均实际占用远低于保守值)。

组件推荐说明
GPU2× L40S 48GB 或 1× H20 96GB权重 27GB + KV 余量充足,单实例即可跑满 20 并发
内存256GB DDR5权重加载 + KV 溢出缓冲
CPU32 核(如 EPYC 7443)调度、tokenizer、预处理
存储2× NVMe SSD 1TB(Gen4)模型权重 + 数据
网络万兆网卡对外吞吐
供电/散热双电源冗余 + 常规风冷不选液冷(L40S/H20 功耗可控)

为什么不用 H100/A100 80G:能吃下,但 80G 单卡跑 27B+20 并发比较紧,H20 96G 或双 L40S(96G 合计)更从容,且性价比高。

软件栈

  • 推理引擎:vLLM(开放 Discourse,高吞吐,原生 OpenAI 兼容接口)
  • 重量级可选:SGLang(长上下文/多轮更优)
  • 量化:FP8/INT8 权重 + FP8 KV cache(vLLM 内置,几乎无损)
  • 部署:Docker + Nginx(限流/负载均衡),不需要上 K8s(单实例规模)
  • 监控:Prometheus + Grafana(vLLM 暴露 tokens/s、TTFT、TPOT、GPU 利用率)
  • 模型:从 ModelScope 拉取(国内快)或 Hugging Face

预算配置(INT4 权重,单卡)

假设:缩短上下文到 4K、峰值并发降到 15。

硬件配置
GPU1× RTX 4090 24GB 或 1× L40S 48GB
权重 INT4~13.5GB
KV Cache 15 并发 @4K~37GB
合计24GB 卡偏紧,48GB 卡舒适

这档适合内部测试 / 低并发原型,不建议作为正式对外服务。

成本估算(人民币,含整机)

方案GPU裸机约价说明
推荐2× L40S 48GB¥12–16 万单机即可,运维简单
推荐1× H20 96GB¥10–14 万国产可控,单卡省电
高配1× H100 80G¥25–30 万性能最强但贵
预算1× RTX 4090 24GB¥3–5 万仅原型

云上(阿里云/火山/华为云 GPU 实例)按需租用 H20 或 A10 即可,月租约 ¥1.5–3 万,适合先验证再自购。

六、收紧到 8K 上下文 + 最大 10 并发

参数收紧到 8K 上下文 + 最大 10 并发后,结论大幅简化:单卡即可搞定,成本比上一版降一半以上。原因是 KV Cache 从「20 并发 × 8K」的 ~140GB 降到了 ~10GB,不再是瓶颈。

显存重算(以 Qwen2.5-27B 为例)

27B 模型是 GQA 架构(64 层、4 个 KV 头),KV Cache 每 token 约 128KB(FP16):

项计算占用
权重 FP1627B × 2B~54GB
权重 FP8/INT827B × 1B~27GB
权重 INT4 (AWQ)27B × 0.5B~13.5GB
KV Cache 10 并发 @8K FP16128KB × 8192 × 10~10.5GB
KV Cache 同上但 FP8减半~5GB

结论:10 并发 × 8K 时 KV 只占 5–10GB,权重成了唯一大头 → 单卡路线成立。

推荐配置(生产,FP8 权重)

组件配置说明
GPU1× L40S 48GB(或 1× H20 96GB)权重 27GB + KV ~5GB + 开销 ≈ 35GB,48GB 卡留 ~13GB 余量,可临时扩到 20 并发或 16K 上下文
CPU16–32 核调度、tokenizer,够用
内存128–256GB DDR5权重加载 + 数据缓冲
存储1× NVMe SSD 1TB(Gen4)模型 + 日志
软件vLLM + Docker + Nginx + Prometheus/Grafana单实例,不需要 K8s

预算配置(INT4 AWQ,单卡 4090)

组件配置说明
GPU1× RTX 4090 24GB权重 13.5GB + KV(FP8) ~5GB + 开销 ≈ 20GB,能塞进 24GB,但余量小
前提必须用 AWQ/GPTQ INT4 量化模型 + FP8 KV cache精度损失可接受(约 1–2 分)
适用内部工具、原型、低敏场景10 并发满负荷时较紧,建议把 --max-num-seqs 限到 8

成本估算(人民币)

方案GPU整机约价云上按需月租
生产1× L40S 48GB¥5–8 万约 ¥1–1.5 万/月
生产1× H20 96GB¥8–12 万约 ¥1.5–2 万/月
预算1× RTX 4090 24GB¥2.5–4 万约 ¥0.5–1 万/月

vLLM 启动命令(参数已定死,直接可用)

生产方案(FP8):

vllm serve Qwen/Qwen2.5-27B-Instruct-FP8 \
  --max-model-len 8192 \
  --max-num-seqs 10 \
  --kv-cache-dtype fp8_e5m2 \
  --gpu-memory-utilization 0.9 \
  --port 8000 \
  --served-model-name qwen27b

预算方案(INT4 AWQ):

vllm serve Qwen/Qwen2.5-27B-Instruct-AWQ \
  --max-model-len 8192 \
  --max-num-seqs 10 \
  --kv-cache-dtype fp8_e5m2 \
  --gpu-memory-utilization 0.95 \
  --port 8000 \
  --served-model-name qwen27b

模型从 ModelScope 拉取更快:modelscope download --model Qwen/Qwen2.5-27B-Instruct,本地路径替换仓库名即可。

七、软件基建再细化

推理引擎选型

引擎适配度说明
vLLM⭐ 首选高吞吐 + OpenAI 兼容接口,8K/10 并发场景性能足够,生态最成熟
SGLang备选多轮对话/长上下文更优,但你这规模优势不明显,复杂度略高
llama.cpp排除偏 CPU/边缘,不适合服务化
Ollama排除测试用,生产不推荐

结论:vLLM,理由:单卡吞吐够、原生 OpenAI 接口、量化支持好、监控指标齐全。

服务架构(单机版)

graph TD
    A["客户端"] -->|HTTPS| B["Nginx (反向代理 + 限流 + TLS 终结)"]
    B --> C["vLLM (OpenAI 兼容 :8000)"]
    C -->|指标| D["Prometheus 指标 /metrics"]
    C --> E["模型权重 (Qwen2.5-27B FP8/AWQ)"]
    C --> F["可选: RAG 侧车 (Milvus/Qdrant + Embedding)"]

三层:

  1. 网关层(Nginx):对外统一入口,隐藏内部端口;TLS 证书 + 限流(limit_req,防止打爆);按路径路由到推理服务。
  2. 推理层(vLLM):核心服务,OpenAI 兼容 /v1/chat/completions、/v1/completions;暴露 /metrics 给监控。
  3. 可选应用层:RAG(外接知识库时加向量库)与业务代码(FastAPI 做业务封装、鉴权、多租户)。

一键部署(Docker Compose)

这是最省心的方案,不需要 K8s(单实例规模)。

docker-compose.yml:

services:
  vllm:
    image: vllm/vllm-openai:latest
    entrypoint: ["python", "-m", "vllm.entrypoints.openai.api_server"]
    command:
      - --model=/models/Qwen2.5-27B-Instruct
      - --max-model-len=8192
      - --max-num-seqs=10
      - --kv-cache-dtype=fp8_e5m2
      - --gpu-memory-utilization=0.9
      - --served-model-name=qwen27b
      - --port=8000
    volumes:
      - /data/models:/models:ro
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    ports:
      - "127.0.0.1:8000:8000"   # 只暴露内网,对外走 Nginx

  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "443:443"
    depends_on:
      - vllm

  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prom-data:/prometheus
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=<PASSWORD>
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  prom-data:
  grafana-data:

nginx.conf(限流 + 反代):

worker_processes auto;
events { worker_connections 1024; }

http {
  limit_req_zone $binary_remote_addr zone=llm:10m rate=20r/s;

  upstream vllm {
    server vllm:8000;
    keepalive 32;
  }

  server {
    listen 443 ssl;
    # ssl_certificate /etc/nginx/ssl/server.crt;
    # ssl_certificate_key /etc/nginx/ssl/server.key;

    location /v1/ {
      limit_req zone=llm burst=20 nodelay;
      proxy_pass http://vllm;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      proxy_read_timeout 300s;   # 长生成需放宽
    }
  }
}

部署要点

环节关键点
模型加载从 ModelScope 拉 Qwen2.5-27B-Instruct(FP8 或 AWQ 版),挂载只读目录,避免每次启动重下载
连续批处理vLLM 默认开启,--max-num-seqs 10 即并发上限,10 并发接近满是因为单实例
鉴权对外上线务必加 API Key(Nginx 层校验或 vLLM --api-key),别裸奔
限流Nginx limit_req 兜底,防 DDoS 和误刷
监控vLLM 自带 /metrics(tokens/s、TTFT、TPOT、GPU 利用率),Prometheus 抓取 + Grafana 看板
日志Docker 日志 + 可选接入 Loki/ELK,审计算法调用
GPU 驱动宿主机装 NVIDIA 驱动 + nvidia-container-toolkit,这是 Docker 用 GPU 的前提

验证与上线路径

  1. 本地冒烟:curl http://127.0.0.1:8000/v1/chat/completions 发一条测试消息。
  2. 压测:用小工具打 10 并发,看 TTFT / TPOT / 显存(vLLM 指标里都有)。
  3. 调整:显存紧张就降 --gpu-memory-utilization 或 --max-num-seqs。
  4. 上线:Nginx 挂 TLS + API Key,Prometheus/Grafana 看板挂好。

八、后端开发视角的服务方案

把推理服务当成自己团队要维护的一个后端系统来设计。不要把 vLLM 直接暴露给业务,中间要加一层「业务网关服务」。

分层架构

graph TD
    A["客户端/前端"] -->|HTTPS| B["BFF / 业务服务 (FastAPI)  ← 后端开发的主战场<br/>鉴权 · 租户 · 限流 · 计费 · 编排 · 缓存 · 路由 · 重试"]
    B -->|internal HTTP (OpenAI 兼容)| C["vLLM 推理服务 (单实例)  ← 基础设施,屏蔽细节"]

核心原则:业务服务是「唯一入口」,vLLM 是「可替换的推理后端」。这样以后换引擎(SGLang/TensorRT)、换模型、加 GPU,前端和业务代码都不用动。

统一 API 层(对外契约)

对外暴露你自己的接口,而不是直接把 vLLM 的 OpenAI 接口透传出去——这样你可以控制协议、加字段、做版本管理。

# 请求体设计
class ChatRequest(BaseModel):
    messages: list[Message]      # 对话历史
    temperature: float = 0.7     # 白名单参数,别让用户传任意值
    max_tokens: int = 2048       # 有上限,防烧钱
    user_id: str                 # 租户/用户标识(计费、限流用)
    stream: bool = False         # 是否流式

# 响应体
class ChatResponse(BaseModel):
    id: str
    reply: str
    usage: Usage                 # token 数,用于计费/审计
    latency_ms: int

设计要点:

  • 参数白名单化:只暴露 Temperature / Top_P / Max_Tokens 等几个,不暴露 --gpu-memory-utilization 这类基础设施参数。
  • 统一 Trace ID:每个请求带 x-request-id,贯穿业务服务 → vLLM → 日志 → 监控,排查问题全靠它。

流式与协议处理

  • 流式:stream=True 时用 SSE(Server-Sent Events)转发 vLLM 的 token 流,逐 token 吐给前端,改善首字延迟体感。
  • 非流式:等 vLLM 完整返回再回包。
  • 超时控制:vLLM 单请求可能生成很久,业务层要设超时(如 120s)和取消传播(asyncio 取消请求时同步取消上游 fetch)。

鉴权与多租户

  • API Key 鉴权:业务层先校验 Key → 映射到租户/用户 → 生成请求上下文。
  • 租户隔离:不同租户的 QPS、并发、token 配额分开限制(concurrency 按租户切分,防止一个租户打满 10 并发饿死别人)。
  • 配额/计费:按 usage.total_tokens 记 Mock 计费,写审计日志。

限流与并发控制(关键!)

vLLM 只有 10 并发,这是全系统最硬的约束,业务层必须做并发闸门:

# 轻量信号量做并发闸门,超过即排队或返回 429
semaphore = asyncio.Semaphore(10)

async def chat(req):
    if semaphore.locked():
        # 超额定,返回 429 + Retry-After,或进队列
        raise HTTPException(429, "server busy")
    async with semaphore:
        return await engine_call(req)
  • 队列 vs 拒绝:10 并发满时,选「排队(带超时)」还是「直接 429」?建议:短请求排队、长请求 429,避免队头阻塞。
  • 区分层:业务层限流(限业务量)+ vLLM 内部 --max-num-seqs(兜底),两层叠闸。

缓存层

  • 精确命中缓存:相同 prompt 的重复请求(如常见 QA)直接返回缓存,不进推理,省 GPU 又降延迟。
  • 语义缓存(可选):RAG 场景做 embedding 相似度去重,能大幅降负载。
  • 会话管理:多轮对话的历史存 Redis,别每次全量重传。

错误处理与重试

  • vLLM 侧错误:区分「可重试」(超时、503 瞬时)和「不可重试」(400 参数错误、模型加载失败)。
  • 重试策略:指数退避 + 抖动,但要小心——生成到一半的重试会浪费 token,只对「未开始生成」的请求重试。
  • 降级:vLLM 挂了时,返回友好错误或降级到小模型/规则回复,别让用户看到 500 裸奔。

数据流与状态管理

graph LR
    A["业务请求"] --> B["校验"] --> C["限流"] --> D["并发闸门"] --> E["拼 prompt"] --> F["调 vLLM"] --> G["解析"] --> H["校验输出"] --> I["缓存"] --> J["落库"] --> K["返回"]
  • 无状态业务服务:业务服务本身无状态(可水平扩展多个副本),有状态的部分(会话、缓存、配额)全部放 Redis/DB。
  • 单点瓶颈:vLLM 是唯一有状态单点。如果未来要扩并发,要么加 GPU 做多实例 + 负载均衡,要么上 vLLM 的分布式(PVC/DeepSeek 风格),但 10 并发阶段不需要。

后端工程化要点

维度方案
语言/框架Python + FastAPI(生态与 vLLM/SDK 最搭);追求性能可换 Go,但开发成本高
异步全链路 asyncio,一个请求不阻塞其他;vLLM 调用用 httpx.AsyncClient
配置管理pydantic-settings + 环境变量,模型名、并发、显存参数全走配置,别写死
测试vLLM 契约测试(mock 掉推理,测业务逻辑);集成测试打真实 vLLM
CI/CDDocker 镜像 + GitLab CI/GitHub Actions,自动构建、跑测试、部署
日志结构化日志(JSON),带 trace_id、user_id、latency、token 数
可观测业务指标:QPS、P95/P99 延迟、缓存命中率、429 率、token 消耗;vLLM 指标:TTFT/TPOT/GPU 利用率
告警429 率上升、GPU 利用率高、P99 延迟超阈值 → 告警

目录结构(可直接落地的骨架)

app/
├── main.py              # FastAPI 入口
├── config.py            # 配置(pydantic-settings)
├── api/
│   ├── chat.py          # 对话路由
│   └── health.py        # 健康检查
├── core/
│   ├── auth.py          # API Key 鉴权
│   ├── ratelimit.py     # 限流
│   ├── concurrency.py   # 并发闸门
│   └── tracing.py       # trace_id 注入
├── services/
│   ├── llm_client.py    # vLLM 客户端(OpenAI 兼容)
│   ├── cache.py         # 缓存
│   └── quota.py         # 配额/计费
├── models/
│   └── schemas.py       # Pydantic 模型
├── tests/
│   ├── docker-compose.yml
│   └── nginx.conf

九、关键决策回顾

  1. 业务服务必须独立于 vLLM:别把认证、限流逻辑塞进 vLLM 配置里,它们职责不同,分开才能各自演进。
  2. 并发闸门是核心:10 并发是硬限制,业务层用信号量做闸门,配合 429/排队策略,这比任何调优都重要。
  3. 流式优先:首字延迟(TTFB)对用户体验影响最大,后端默认支持 SSE 流式。
  4. 先做契约测试再联调:vLLM 用 mock 掉,业务单测先跑通,最后再真机联调,省大量时间。
  5. 可观测性从第一天就上:trace_id + 结构化日志 + 延迟/token 指标,比事后补容易得多。
  6. 先定死参数再选硬件:上下文长度、并发上限、量化精度是决定显存成本的最大变量,先定死再反推配置。
  7. 10 并发是单卡分水岭:收敛到 8K 上下文 + 10 并发后,单卡 L40S 即可覆盖,成本可控。

Sources

No external sources for this entry.

Related