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

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

本地部署 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 48GB1× 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 24GB1× 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):

Terminal window
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):

Terminal window
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 接口、量化支持好、监控指标齐全。

服务架构(单机版)#

客户端
│ HTTPS
Nginx (反向代理 + 限流 + TLS 终结)
vLLM (OpenAI 兼容 :8000) ──► Prometheus 指标 /metrics
├── 模型权重(Qwen2.5-27B FP8/AWQ)
└── 可选: 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 直接暴露给业务,中间要加一层「业务网关服务」。

分层架构#

客户端/前端
│ HTTPS
┌─────────────────────────────┐
│ BFF / 业务服务 (FastAPI) │ ← 后端开发的主战场
│ 鉴权 · 租户 · 限流 · 计费 · │
│ 编排 · 缓存 · 路由 · 重试 │
└──────────────┬──────────────┘
│ internal HTTP (OpenAI 兼容)
┌─────────────────────────────┐
│ 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 裸奔。

数据流与状态管理#

业务请求 → 校验 → 限流 → 并发闸门 → 拼 prompt → 调 vLLM → 解析 → 校验输出 → 缓存 → 落库 → 返回
  • 无状态业务服务:业务服务本身无状态(可水平扩展多个副本),有状态的部分(会话、缓存、配额)全部放 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 即可覆盖,成本可控。
本地部署 LLM 服务:从硬件到后端的完整基建指南
https://sgjki547.top/posts/2026-08-04-本地部署llm服务完整基建指南/
Author
SGJki
Published at
2026-08-04
License
CC BY-NC-SA 4.0