自己搭建一套推理集群:从单机到多节点的可复现实践

自己搭建一套推理集群:从单机到多节点的可复现实践

很多人第一次部署大模型服务,会直接寻找“最复杂的集群方案”。结果往往是组件先于问题出现:网关、队列、调度器、监控系统全部装上,真正的瓶颈却还没有测出来。

更稳妥的路径是从一台机器开始,把每一步扩展都建立在可观测的指标上。本文用一条从简单到复杂的路线,搭建一套能复现、能压测、能排障的推理集群。

1. 先做单机基线

先选一个明确的模型和推理运行时,例如 Ollama、llama.cpp 或 vLLM。单机阶段只解决三件事:模型能启动、接口能调用、指标能记录。

建议准备一个最小脚本,固定 prompt、输入长度和并发数,记录首 token 延迟(TTFT)、生成速度(tokens/s)、总延迟、显存占用和错误率。没有基线,后面每次扩容都无法判断收益。

1
2
3
curl http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen","messages":[{"role":"user","content":"解释什么是负载均衡"}],"stream":false}'

单机服务前面可以加一个极简反向代理,但先不要引入队列。把超时、最大输入长度和并发上限写进配置,并在日志中打印 request_id,后续排查会轻松很多。

2. 把入口和模型服务拆开

当请求量增加,第一步扩展不是复制所有组件,而是把入口层和模型层分离。入口层负责鉴权、限流、请求规范化和日志;模型服务只负责加载模型并生成结果。

可以用 Nginx、Caddy 或一个轻量 Python 网关完成入口层。网关通过 OpenAI 兼容协议转发请求,这样客户端无需感知后端替换。此时的部署拓扑很简单:

1
客户端 → 网关 → 模型服务

网关需要设置连接超时和读取超时,并区分 4xx、5xx、超时三类错误。对于流式输出,要确保代理不会因为缓冲导致首 token 延迟异常。

3. 增加副本和最小调度

第二台机器加入后,先采用静态副本:每个模型服务有一个地址,网关使用轮询或最少连接策略分发请求。静态配置虽然朴素,却最容易验证网络、显卡和模型版本是否一致。

当副本超过三个,再单独引入调度器。调度器维护副本状态,至少包含:可用/不可用、当前并发、队列长度、最近一次心跳和显存水位。路由决策优先考虑模型是否匹配,其次才是负载。

1
2
客户端 → 网关 → 调度器 → 副本 A/B/C
                         ↘ 统一日志与指标

不要一开始就做跨节点张量并行。多数业务先通过数据并行获得容量,模型副本之间互不影响,故障也更容易隔离。只有单卡无法容纳模型,或明确需要更低延迟时,才评估张量并行和流水线并行。

4. 处理显存、队列和流量峰值

推理集群最常见的故障不是 CPU 满载,而是显存碎片、KV Cache 耗尽和突发流量造成的排队。每个副本都应该暴露显存使用率、KV Cache 使用量、活动请求数和排队时间。

网关层设置全局并发上限,副本层设置单进程并发上限。队列必须有长度上限,超过上限就快速失败或降级到小模型。这样可以把“所有请求都变慢”变成“少量请求明确失败”。

对于长上下文请求,可以按输入长度分组,避免一个超长请求阻塞短请求。批处理要通过压测决定,批越大吞吐通常越高,但 TTFT 和显存压力也会增加。

5. 监控与故障演练

至少采集四类指标:请求量与错误率、TTFT 与总延迟、tokens/s 与队列长度、显存与进程状态。日志中统一记录 request_id、model、副本地址和耗时阶段,链路追踪可以后置。

每周做一次小型故障演练:停止一个副本、注入慢请求、填满队列、模拟模型进程重启。检查网关是否能摘除异常副本,客户端是否得到可理解的错误,恢复后副本是否自动回到服务池。

降级策略应提前写清楚,例如主模型超时后切换小模型,或只返回检索结果摘要。降级不是“出问题再临时决定”,而是系统设计的一部分。

6. 一套可复现的目录

建议把部署文件放在同一个仓库中:

1
2
3
4
5
6
7
inference-cluster/
├── gateway/          # 路由、鉴权、限流
├── scheduler/        # 副本心跳与选择
├── model-server/     # vLLM/Ollama 启动参数
├── observability/    # Prometheus、Grafana、日志配置
├── scripts/          # 基线压测、故障演练
└── compose.yaml      # 单机复现入口

先用 Docker Compose 在一台机器复现网关、两个模型副本和监控,再把 model-server 替换成不同主机上的服务。配置全部通过环境变量传入,模型版本和启动参数写入版本控制。这样从单机到多节点只是部署边界变化,应用接口和观测方式保持一致。

结语

推理集群的核心不是组件数量,而是每次扩展都能回答三个问题:瓶颈在哪里,新增组件解决了什么,出现故障时如何退回可用状态。沿着单机基线、入口拆分、副本调度、资源治理、监控演练这条路线推进,即使只有几台机器,也能搭出一套结构清晰、可以复现的系统。

参考资料

  • vLLM 文档:OpenAI 兼容服务与并行推理
  • Prometheus 文档:指标采集与告警规则
  • Docker Compose 文档:多服务本地复现

素材