
在接触大模型工程落地的这几年里我最大的感受是训练一个模型只是起点真正决定业务价值的往往是模型训练完成之后的那一步——推理服务。无论是内部业务接入、对外 API 开放还是构建 Agent 应用推理服务的稳定性、吞吐量和成本控制几乎直接决定了一个 AI 项目能否长期健康运行。这也是为什么像 Gerred 这样长期深耕大规模推理服务领域的专家会被越来越多团队关注他们的经验不是某一次实验的成功而是把推理这件事从“能跑”做到“跑得稳、跑得快、跑得省”的系统方法论。这篇文章会围绕大规模推理服务展开从核心概念、架构难点、工具选型、环境准备到完整可复用的代码示例、性能优化思路、常见问题排查和工程最佳实践尽量讲清楚“为什么”和“怎么做”。如果你正在做大模型部署、AI 应用后端或者计划把模型真正推向生产环境这篇文章应该能给你一条相对完整的路径参考。1. 推理服务是什么为什么“大规模”这么难1.1 推理服务的基本概念推理服务Inference Service是指将训练好的模型部署到生产环境中对外提供预测能力的整套系统。用户发送一个请求进来服务加载模型进行计算然后返回结果。这个过程中涉及模型加载、请求处理、结果返回等多个环节。传统的推理服务通常基于 Web 框架比如 Flask、FastAPI简单地把模型封装成 HTTP 接口。这种方式在小流量、低并发、单模型场景下完全够用但在大规模真实业务中会遇到一系列问题并发请求量高单机处理能力成为瓶颈。模型越来越大显存与内存管理变得复杂。多模型、多版本共存时资源调度困难。推理耗时直接影响用户体感延迟抖动不可接受。算力成本高GPU 利用率低意味着钱在浪费。1.2 为什么“大规模推理服务”成为独立领域现在说“大规模推理服务”往往默认和 ChatGPT 这类大语言模型LLM相关但它并不只适用于 LLM。在推荐系统、图像识别、语音识别、AIGC 等场景推理服务同样是大规模架构中的核心环节。大规模推理服务与传统 Web 服务的最大区别在于计算密集、状态复杂、资源成本高。一个普通 CRUD 接口请求进来后主要是数据库读写CPU 占用有限而一次大模型推理可能涉及数亿甚至数千亿参数的计算显存占用、GPU 算力消耗都是数量级的提升。因此大规模推理服务需要专门的架构设计和优化手段来支撑高效的模型加载与生命周期管理使模型版本切换不中断服务。请求调度与动态批处理让 GPU 尽可能满负荷运转。显存管理与 KV Cache 复用在有限显存中塞下更大的模型和并发。推理引擎与算子优化让每次计算变快。弹性伸缩与故障转移保证服务在高流量下的稳定性。这些内容已经形成了一个独立的技术栈值得系统学习。2. 推理服务的整体架构与技术难点2.1 大规模推理服务的分层架构为了便于理解可以把一套完整的推理服务拆成下面几个层次第一层是接入层。它负责接收用户请求做认证鉴权、流量控制、请求预处理通常由 Nginx、API 网关、Ingress Controller 等组件承担。第二层是调度层。调度层决定把请求分发给哪个推理实例。当服务规模较大时需要根据实例的负载、GPU 显存余量、模型版本等因素进行智能路由。第三层是推理引擎层。这是核心中的核心负责真正执行模型计算。当前主流的推理引擎包括 vLLM、NVIDIA Triton Inference Server、TensorRT-LLM、SGLang、Ollama偏本地验证等。第四层是资源层。包括 GPU 服务器、CPU 服务器、存储、网络等基础设施。在做小规模验证时接入层和调度层可以简化有时甚至一台 GPU 机器 一个推理框架就能跑通但大规模场景下每一层都必须认真设计。2.2 推理服务最大的几个技术难点第一个难点是显存瓶颈。大模型参数动辄几十 GB再加上推理过程中的中间激活值、KV Cache单张 GPU 往往放不下需要张量并行、模型并行、量化等手段。第二个难点是吞吐量与延迟的平衡。单纯降低延迟可以通过 batch size1 实现但 GPU 利用率极低想提高吞吐量又需要增大 batch这会抬高单请求延迟。如何动态规划批处理策略是大规模推理服务持续优化的方向。第三个难点是动态请求的不确定性。LLM 推理是流式的每个请求生成长度不同计算量高度离散。这导致传统基于固定计算量的调度策略失效需要按迭代次数、缓存状态等进行动态调度。第四个难点是成本控制。GPU 很贵如何通过 Continuous Batching、Prefix Caching、投机采样等手段降低推理成本是绝大多数业务团队都非常关心的问题。了解了这些难点之后再回看 Gerred 在推理服务领域强调的“工程化”思路就会更加清晰推理不是一次模型调用而是一套需要考虑稳定性、延迟、成本和可观测性的完整系统工程。3. 推理服务环境准备与工具选型3.1 环境准备在正式动手之前先准备好环境。根据不同团队的情况环境会有差异下面给出一个比较常见的示例配置操作系统Ubuntu 20.04 / 22.04大多数 GPU 服务器和云主机常用GPUNVIDIA A100 / A800 / V100 / RTX 3090 / 4090 等深度学习框架PyTorch 2.xPython3.9 或 3.10建议 3.10避免部分 CUDA 扩展兼容问题CUDA11.8 或 12.1按显卡驱动和框架要求选择推理引擎vLLM高性能 LLM 推理、NVIDIA Triton通用模型推理部署方式Docker Docker Compose / Kubernetes环境版本需要根据你的项目实际情况调整。例如如果你的显卡驱动只支持到 CUDA 11.8就不要强行安装需要 CUDA 12.x 的轮子。建议先把 NVIDIA 驱动和 CUDA 版本确认好再安装对应版本的 PyTorch 和推理引擎。一个小建议如果你的业务主要是 LLM 服务可以优先尝试 vLLM如果业务包含多个不同类型的模型如 CV NLP 语音Triton 的统一管理能力更有优势。3.2 推理引擎选型对比目前最常见的推理服务工具可以从几个维度来对比在快速验证和小规模部署阶段Ollama、Text Generation Inference、vLLM 都很方便在大规模生产环境中vLLM 和 NVIDIA Triton 的生态更完整。需要说明的是技术选型变化很快具体性能以你实际测试为准这里只提供选型思路。4. 从零搭建一个推理服务完整示例纸上谈兵不够下面用一个完整的示例演示如何搭建推理服务。先从一个最简单的在线推理接口开始再升级到使用 vLLM 的高性能版本。4.1 项目结构先创建目录结构inference-demo/ ├── app.py # FastAPI 推理服务入口 ├── model_server.py # vLLM 高性能推理示例 ├── requirements.txt # Python 依赖 ├── docker-compose.yml # 容器编排 └── test_request.py # 客户端测试脚本4.2 版本一基于 FastAPI 的简单推理服务对于中小模型或初次验证可以用 FastAPI 快速封装一个推理服务。# 文件路径inference-demo/app.py import time from typing import Dict, Optional import torch from fastapi import FastAPI, HTTPException from pydantic import BaseModel app FastAPI(titleInference Demo Service) class PredictRequest(BaseModel): text: str max_new_tokens: Optional[int] 32 class PredictResponse(BaseModel): text: str latency_ms: float # 实际项目中模型加载通常放在 lifespan 钩子中 # 避免每次请求都重复加载模型。 model None tokenizer None def load_model(): 这里以 HuggingFace 的 AutoModel 为例实际上按模型类型调整。 model_name sshleifer/tiny-gpt2 global model, tokenizer try: from transformers import AutoModelForCausalLM, AutoTokenizer tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained(model_name) model.eval() if torch.cuda.is_available(): model model.cuda() except Exception as e: raise RuntimeError(f模型加载失败{e}) app.on_event(startup) def startup_event(): load_model() app.post(/predict, response_modelPredictResponse) def predict(req: PredictRequest): if model is None or tokenizer is None: raise HTTPException(status_code500, detail模型未加载) start time.time() try: inputs tokenizer(req.text, return_tensorspt) if torch.cuda.is_available(): inputs {k: v.cuda() for k, v in inputs.items()} with torch.no_grad(): outputs model.generate( **inputs, max_new_tokensreq.max_new_tokens, do_sampleFalse, ) generated_text tokenizer.decode(outputs[0], skip_special_tokensTrue) except Exception as e: raise HTTPException(status_code500, detailf推理失败{e}) latency_ms round((time.time() - start) * 1000, 2) return PredictResponse(textgenerated_text, latency_mslatency_ms) app.get(/health) def health(): return {status: ok}这段代码的思路是使用 FastAPI 封装 HTTP 接口。启动时加载模型。/predict接口接收文本使用 transformers 的generate完成生成。返回生成结果和耗时。依赖文件# 文件路径inference-demo/requirements.txt fastapi0.104.0 uvicorn0.24.0 torch2.0.0 transformers4.36.0 pydantic2.0.0启动服务cd inference-demo pip install -r requirements.txt python -m uvicorn app:app --host 0.0.0.0 --port 8000测试请求curl -X POST http://localhost:8000/predict \ -H Content-Type: application/json \ -d {text: Hello, my name is}这个版本适合小模型学习和调试但距离“大规模推理服务”还差得很远。原因很明显每次请求独立推理GPU 利用率不理想。没有动态批处理。显存管理依赖 PyTorch 默认策略。没有流式输出。缺少监控和自动扩缩容。所以接下来看看更接近生产形态的高性能推理服务怎么做。4.3 版本二基于 vLLM 的高性能推理服务vLLMVery Large Language Model是当前 LLM 推理服务中非常流行的引擎核心优势包括PagedAttention 显存管理大幅提升 KV Cache 利用率。Continuous Batching 动态批处理提高吞吐量。支持 OpenAI 兼容接口方便接入现有生态。内置流式输出、Prefix Caching 等能力。安装方式pip install vllm注意vLLM 对 PyTorch 和 CUDA 版本有对应关系要求安装之前最好查看官方文档确认版本匹配。这里给出的是一个示例写法实际版本以你的环境为准。下面用 vLLM 启动一个 OpenAI 兼容的推理服务python -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-2-7b-chat-hf \ --tensor-parallel-size 2 \ --gpu-memory-utilization 0.9 \ --port 8000 \ --max-model-len 4096参数解释--model模型名称或路径。--tensor-parallel-size张量并行规模。如果有多张 GPU可以设置成 GPU 卡数。--gpu-memory-utilization允许使用的 GPU 显存比例通常设置为 0.85 到 0.95留出余量给 CUDA context。--max-model-len最大上下文长度需要根据模型能力和显存设置。--port服务端口。启动后vLLM 会提供一个/v1/chat/completions接口兼容 OpenAI 格式。通过 Python 客户端调用# 文件路径inference-demo/test_request.py from openai import OpenAI client OpenAI( base_urlhttp://localhost:8000/v1, api_keyEMPTY, # 本地服务key 可随意 ) response client.chat.completions.create( modelmeta-llama/Llama-2-7b-chat-hf, messages[ {role: system, content: 你是一个有用的助手。}, {role: user, content: 请介绍一下推理服务。}, ], max_tokens256, temperature0.7, ) print(response.choices[0].message.content)如果希望实现更复杂的自定义逻辑也可以在 Python 代码中直接调用 vLLM 的LLM类# 文件路径inference-demo/model_server.py from vllm import LLM, SamplingParams # 创建 LLM 实例模型会加载到 GPU llm LLM( modelmeta-llama/Llama-2-7b-chat-hf, tensor_parallel_size2, # 双卡并行 gpu_memory_utilization0.9, # GPU 显存利用率 max_model_len4096, # 最大上下文长度 ) # 定义采样参数 sampling_params SamplingParams( temperature0.7, top_p0.9, max_tokens256, ) def run_inference(prompts: list): 批量推理入口 outputs llm.generate(prompts, sampling_params) return [output.outputs[0].text for output in outputs] if __name__ __main__: prompts [ 什么是推理服务, 如何提高 GPU 利用率, ] results run_inference(prompts) for prompt, result in zip(prompts, results): print(fPrompt: {prompt}\nAnswer: {result}\n)vLLM 的LLM.generate是批量接口传入一个 prompt 列表可以在一次调用里完成多段文本生成。在实际生产服务中我们还是推荐用 OpenAI 兼容 API 或者 FastAPI 包一层方便统一鉴权、限流和日志采集。4.4 用 Docker 部署推理服务生产环境很少直接裸机跑 Python 服务通常会用 Docker 打包保证环境一致性。# 文件路径inference-demo/Dockerfile.vllm FROM nvidia/cuda:12.1.0-base-ubuntu22.04 ENV DEBIAN_FRONTENDnoninteractive RUN apt-get update apt-get install -y \ python3.10 python3.10-dev python3-pip curl \ ln -s /usr/bin/python3.10 /usr/bin/python RUN pip3 install --no-cache-dir \ vllm \ fastapi \ uvicorn \ openai WORKDIR /app COPY . /app EXPOSE 8000 CMD [python3, -m, vllm.entrypoints.openai.api_server, --model, meta-llama/Llama-2-7b-chat-hf, --host, 0.0.0.0, --port, 8000]构建镜像docker build -f Dockerfile.vllm -t inference-demo:vllm .运行容器前请确认宿主机已安装 NVIDIA 驱动。Docker 已配置 NVIDIA Container Toolkit。显存足够加载目标模型。启动容器docker run --gpus all \ -p 8000:8000 \ --shm-size2g \ inference-demo:vllm--shm-size参数需要根据 DataLoader 或分布式通信需求调整太小时可能出现共享内存不足。4.5 运行结果说明服务启动后可以看到 vLLM 输出模型加载日志、GPU 显存占用等信息。调用/v1/chat/completions接口时返回内容包含id、object、choices、usage等字段。{ id: chatcmpl-xxx, object: chat.completion, created: 1710000000, model: meta-llama/Llama-2-7b-chat-hf, choices: [ { index: 0, message: { role: assistant, content: 推理服务是将训练好的模型部署到生产环境对外提供预测能力的服务…… }, finish_reason: stop } ], usage: { prompt_tokens: 23, completion_tokens: 128, total_tokens: 151 } }走到这一步一个可以应对较高并发的 LLM 推理服务就搭建起来了。接下来还需要考虑性能调优和稳定性保障。5. 大规模推理服务的性能优化原理在真实业务中仅仅把服务跑起来是不够的。下面从几个核心优化方向说明大规模推理服务怎么做深度优化。5.1 动态批处理Continuous Batching传统批处理是等待一定数量的请求后才开始计算batch 固定动态批处理则允许在生成过程中动态加入新请求、剔除已完成请求。因为 LLM 生成是逐 token 进行的假设 batch 里有 10 个请求其中 3 个已经生成结束那么剩余 7 个仍然可以用 GPU 并行计算。如果采用固定 batch新请求必须等到下一轮而动态批处理可以在结束请求的空闲算力上立刻插入新请求从而大幅提升吞吐量。vLLM、TGI、TensorRT-LLM 都实现了类似的调度机制。这也是它们比“普通 FastAPI 套 transformers”性能高出一大截的重要原因。5.2 PagedAttention 与 KV Cache在 LLM 推理中每个请求都维护一份 KV CacheKey-Value Cache用于存储历史 token 的注意力中间结果。如果不做管理KV Cache 随着请求数量增加会迅速占满显存。vLLM 提出的 PagedAttention 借鉴了操作系统的虚拟内存分页思想将 KV Cache 分成固定大小的块按需分配而不是预先分配整段连续显存从而极大减少了显存碎片提高了并发能力。5.3 算子优化与量化算子融合将多个计算单元合并成一个 kernel减少显存读写次数。比如 FlashAttention 就是显著提升注意力计算效率的经典方案。量化将模型权重从 FP16/BF16 压缩到 INT8、INT4降低显存占用并提升计算速度。常用工具包括 GPTQ、AWQ、bitsandbytes 等。TensorRT-LLM 通常会对模型图做编译优化比纯 PyTorch 模式更优。5.4 Prefix Caching在 Agent、多轮对话、RAG 场景中多个请求往往共享相同的前缀 token例如 System Prompt、检索到的文档。如果不做处理每个请求都会重复计算前缀部分的 KV Cache。Prefix Caching 会把前缀 token 的 KV Cache 保存起来新请求如果前缀一致可以直接复用省去重复计算。这个优化在长文档问答场景中收益很大。5.5 推理服务压测性能优化不能靠感觉必须用压测数据说话。常见压测工具有 Locust、wrk、Hey、Ollama Bench、LLMPerf 等。以hey为例先安装go install github.com/rakyll/heylatest然后对 vLLM 的接口发起压测hey -n 200 -c 20 \ -m POST \ -H Content-Type: application/json \ -d {model:meta-llama/Llama-2-7b-chat-hf,messages:[{role:user,content:请用一句话介绍自己}],max_tokens:128} \ http://localhost:8000/v1/chat/completions重点关注指标Requests/sec每秒请求数反映吞吐量。Average latency平均延迟。p99 latency99 分位延迟反映极端情况下的体验。Timeout超时请求数。建议在压测前记录 GPU 利用率压测后再记录一次确认 GPU 是否被打满。如果 GPU 利用率很低但延迟很高大概率是调度、批处理或网络环节出现了瓶颈。6. 常见问题与排查思路下面整理几个大规模推理服务的高频问题。问题现象常见原因解决思路服务启动 OOM模型太大单卡显存放不下增加张量并行卡数或开启量化请求后延迟很高并发批处理调度不优或模型权重过大升级到 vLLM/TensorRT-LLM开启动态批处理GPU 利用率偏低请求稀疏batch size 过小增加并发 token 数量设置合理的 max_num_seqs显存碎片化严重请求长尾分布明显KV Cache 分配过于零散使用支持 PagedAttention 的引擎服务频繁重启并发打满导致资源不足触发 OOMKill增加副本数、限制并发、优化显存占用多副本间负载不均简单轮询路由未考虑实际 GPU 负载根据 GPU 利用率/排队长度进行智能路由生成中途中断网络超时或服务端流式推送异常前端合理设置超时时间后端增加流式心跳6.1 排查思路遇到问题时建议按以下顺序排查先看日志。vLLM 等引擎通常会在启动和请求处理过程中打印详细日志包括显存分配、调度延迟等。再看监控。GPU 利用率、显存占用、请求量、排队长度、P99 延迟这些指标能快速定位瓶颈是在算力、调度还是网络。接着复现。用小批量请求逐步提高并发观察拐点出现的位置。最后针对性优化。如果是调度瓶颈增加 max_num_seqs如果是显存瓶颈开启量化或扩大 tensor parallel。6.2 如何避免问题再次出现上线前完成压测确定合理 QPS 上限和最大并发。配置好自动扩缩容不要等打爆之后再人工干预。为服务设置超时和熔断防止慢请求拖垮整体服务。定期统计并分析长尾请求及时调整模型参数和批处理策略。7. 大规模推理服务的最佳实践与工程建议7.1 分层部署与灰度发布大规模推理服务建议按模型、按业务线分层部署。例如专门部署小模型服务用于快速任务部署大模型集群用于复杂生成任务。模型版本升级时先跑灰度观察延迟和生成质量再全量切换。7.2 监控与可观测性除了常规的 CPU、内存、网络监控推理服务必须额外监控GPU 利用率、显存使用率、显存碎片率。请求排队长度、批处理大小。首 token 延迟、生成长度、端到端延迟。Token 吞吐量tokens/s。缓存命中率如果开了 Prefix Caching。服务可用性、错误码分布。建议将指标输出到 Prometheus再通过 Grafana 展示。日志统一采集方便跨服务追踪请求链路。7.3 安全与权限推理服务直接暴露在内网或公网时需要注意接口鉴权生产环境必须使用 Token 或 API Key 认证最简单的方式是网关层做统一鉴权。请求限流防止单用户或单 IP 占用过多算力。输入长度限制限制max_tokens和上下文长度避免超大请求拖垮服务。模型输出安全通过内容审核接口或规则过滤敏感内容。7.4 成本控制推理成本是大模型业务绕不开的话题。建议关注批量请求尽量复用连接减少重复建连开销。在低峰期使用可抢占实例或停机降配策略。合理设置gpu_memory_utilization不要留过多空闲显存。对离线负载使用异步任务队列削峰填谷。定期评估模型量化带来的收益用精度换成本。7.5 代码与配置管理推理服务是长期演进的工程系统建议模型文件、代码、配置三者分离。用环境变量管理敏感信息不要把 API Key 写死在代码中。Docker 镜像打标签便于版本回滚。关键服务配置做成模板通过 Git 管理变更。8. 总结与学习路线从 FastAPI 封装一个模型接口到 vLLM 高性能部署再到动态批处理、PagedAttention、量化、监控、灰度发布一条完整的大规模推理服务链路已经梳理清楚。这里面最核心的认识是推理服务不是“调用模型”那么简单它更接近一个需要考虑并发调度、显存管理、成本控制、稳定性和可观测性的系统工程。Gerred 在推理服务领域长期积累的经验核心也在于把这套工程体系沉淀成了可复制的方法论。对普通开发者来说下一步可以按这样的路线继续深入先跑通一个小模型推理服务理解请求到响应全流程。再用 vLLM 部署一个开源 LLM体验动态批处理和显存优化。学习 TensorRT-LLM 的算子融合与图优化原理。在 Kubernetes 上搭建多副本推理集群配置 HPA 自动扩缩容。建立完整的监控和告警体系用数据驱动优化。推理服务的技术栈还在快速演进今天的最优解可能半年后就会过时但底层思路是稳定的高吞吐、低延迟、低成本、高稳定性。沿着这四个方向持续深入你的推理服务会越来越接近生产级水平。