共计 4633 个字符,预计需要花费 12 分钟才能阅读完成。
上个月我们的线上 Agent 业务差点被搞崩:某个主流大模型 API 供应商因为海外骨干网抖动,返回延迟直接飙到了 45 秒,甚至大量抛出 HTTP 504 错误。更要命的是,前端大量用户在焦急等待中频繁刷新页面,成百上千个 SSE(Server-Sent Events)长连接处于半死不活的悬挂状态,迅速把后端 FastAPI 服务的连接池全部榨干。
很多小团队做 AI 应用,早期图快直接在业务代码里硬编码 openai.OpenAI(api_key=...)。但业务跑一段时间后,你就会遇到跟我一模一样的麻烦:厂商偶发断流、多模型计费难以分拆核算、缺乏多 Key 轮询与并发限流、重复 Prompt 严重烧钱。为了从根源上解决这些烂摊子,我花了几天时间彻底改造了我们的架构,把网关层全盘迁移到 LiteLLM Proxy。这篇文章梳理了从零搭建、生产调优到真实压测的全过程,建议直接收藏备用。
一、为什么选 LiteLLM 做生产级网关?
在技术选型时,我横向对比过 Cloudflare AI Gateway、One-API 以及 LiteLLM:
- Cloudflare AI Gateway:开箱即用,全球边缘网络加速很爽,但国内直连延迟感人,且私有化部署受限,对于敏感数据合规是个死穴。
- One-API / New-API:基于 Go 语言,面板做得非常漂亮,但它的代码逻辑深度绑定了 UI,定制化扩展拦截器、配合 Prometheus 抓取特定指标相对别扭。
- LiteLLM Proxy:原生 Python 生态,深度拥抱 AsyncIO。它本质上是一个高性能的异步反向代理,天生对齐 OpenAI 规范,支持数十种主流大模型与自建 vLLM/Ollama 实例。更重要的是,它的配置文件非常声明式,不仅原生支持 Redis 语义缓存、自动失败重试与冷却机制,而且对 Langfuse、Prometheus 的集成几乎是零成本。
二、生产级 Docker Compose 部署实操
别用裸命令直接跑 LiteLLM,生产环境必须上 Redis 做限流状态共享与结果缓存,同时挂载独立的配置文件。以下是我在单台 4C8G 云主机上运行稳固的编排配置。
1. 编写 docker-compose.yml
version: '3.8'
services:
litellm-proxy:
image: ghcr.io/berriai/litellm:main-v1.45.0
container_name: litellm-proxy
restart: unless-stopped
ports:
- "4000:4000"
environment:
- DATABASE_URL=postgresql://litellm:litellm_pass@postgres:5432/litellm_db
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=YourStrongRedisPass123
- LITELLM_MASTER_KEY=sk-MasterKeyForAdminAccessOnly999
volumes:
- ./litellm-config.yaml:/app/config.yaml
command: ["--config", "/app/config.yaml", "--port", "4000", "--num_workers", "4"]
depends_on:
- redis
- postgres
redis:
image: redis:7.2-alpine
container_name: litellm-redis
restart: unless-stopped
command: redis-server --requirepass YourStrongRedisPass123 --maxmemory 2gb --maxmemory-policy allkeys-lru
ports:
- "127.0.0.1:6379:6379"
postgres:
image: postgres:16-alpine
container_name: litellm-postgres
restart: unless-stopped
environment:
POSTGRES_USER: litellm
POSTGRES_PASSWORD: litellm_pass
POSTGRES_DB: litellm_db
volumes:
- ./pgdata:/var/lib/postgresql/data
2. 编写核心配置文件 litellm-config.yaml
这里有两个极其核心的设计:模型别名虚拟化 与 降级重试机制。上层业务代码无论调 DeepSeek、Claude 还是 GPT-4o,一律只请求统一的别名(如 gpt-4o-auto),网关会根据健康状况自动分流与降级。
model_list:
# 优先节点:OpenAI 官方 GPT-4o
- model_name: gpt-4o-auto
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY_1
rpm: 500
timeout: 30
# 备用节点:Azure OpenAI 部署的 GPT-4o
- model_name: gpt-4o-auto
litellm_params:
model: azure/my-gpt4o-deployment
api_base: https://your-endpoint.openai.azure.com/
api_key: os.environ/AZURE_API_KEY
api_version: "2024-02-15-preview"
rpm: 1000
timeout: 25
# 兜底节点:自建高吞吐 vLLM / DeepSeek-V3
- model_name: gpt-4o-fallback
litellm_params:
model: openai/deepseek-ai/DeepSeek-V3
api_base: http://192.168.1.100:8000/v1
api_key: "EMPTY"
router_settings:
routing_strategy: "least-busy" # 优先调度到当前负载最低的端点
num_retries: 2 # 失败重试次数
timeout: 30 # 统一超时阈值
cooldown_time: 60 # 某个节点连续报错后自动熔断冷却 60 秒
fallbacks:
- gpt-4o-auto: ["gpt-4o-fallback"] # 当主通道全部炸裂时,静默降级到兜底模型
litellm_settings:
cache: true
cache_type: "redis"
cache_params:
host: "redis"
port: 6379
password: "YourStrongRedisPass123"
supported_call_types: ["completion", "acompletion"]
ttl: 3600 # 相同 Prompt 缓存 1 小时
三、流式传输(SSE)与连接防泄露调优
在没有反向代理介入时,Python 的 aiohttp 或 httpx 处理流式响应很容易遇到一个坑:客户端(前端)断开 WebSocket 或中断 EventSource 时,后端请求仍在默默向远端大模型跑推理,直到整段文字跑完才发现 pipe broken。这白白消耗了宝贵的 Token 额度。
我在 LiteLLM 前面通常还会垫一层轻量级的 Nginx,做生产级网关接入。Nginx 的关键参数配置如下:
server {
listen 80;
server_name api.nassky.top;
location / {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
# 禁用 Nginx 自身的缓存与缓冲,保证 SSE 能够像水流一样无延迟下发
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
# 针对长文本推理,放宽读写超时
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
四、实战压测:启用缓存前后的性能差异
我们在沙盒环境使用 Locust 对网关进行压测,并发用户数设置为 200,模拟常见的多轮对话问答场景(其中包含约 25% 的高频常见重合提问)。
| 指标项 | 未启用网关直连 OpenAI | 接入 LiteLLM + Redis 缓存 | 优化幅度 |
|---|---|---|---|
| 平均首字延迟 (TTFT) | 1420 ms | 430 ms | 下降 69.7% |
| 高并发 P99 响应耗时 | 4850 ms | 1120 ms | 下降 76.9% |
| API 异常报错率 (5xx) | 3.2% (触发厂商限频) | 0.00% (触发熔断切换) | 故障归零 |
| 每日 Token 账单总支出 | $124.50 | $88.30 | 节省约 29% |
实测可以明显看出,高频常见问题的 Redis 命中,不仅把首字输出响应砍到了毫秒级,而且最重要的是抹平了公网链路抖动带来的恶劣体验。即使主节点被限额拉黑,least-busy 与 cooldown_time 也能在 200 毫秒内把请求转移到备用 API,业务层毫无感知。
五、上云踩坑与运维避坑指南
在近三个月的持续运行中,我整理了以下几条极具参考价值的填坑记录:
- Master Key 与虚拟 Key 的权限收敛:千万不要把
LITELLM_MASTER_KEY给业务系统直接用。应该通过网关的/key/generate接口,为不同的应用场景(例如:内部知识库、客服机器人、爬虫萃取)生成独立的虚拟 Key。为这些 Key 设置月度消费上限(max_budget)和限制访问的模型范围,这样即使某一个业务服务被黑客刷接口,也不会直接倾家荡产。 - 内存泄漏与 Worker 数量陷阱:在低内存机型(如 2G/4G 内存的 NAS 或轻量云 VPS)上,不要盲目按照 CPU 核心数无脑拉大
--num_workers。每个 Worker 都维护着异步网络池,过多的 Worker 会在 Redis 命中较低的大并发场景下耗尽内存并被 Linux OOM Killer 强行中断。4C8G 规格推荐稳定维持在 4 个 Worker。 - 避免对高随机度需求启用 Exact Cache:如果你的业务场景需要高
temperature(比如小说创作、头脑风暴),缓存收益极低甚至会产生“回答千篇一律”的负面体验。我们通常在请求头中动态下发no-cache: true,或者在 LiteLLM 路由规则里按模型维度关闭缓存。
总结与结语建议
如果你的应用架构还停留在“把大模型当做一个单纯带 API Key 的 HTTP 接口调”这个阶段,那么一旦遇到公网超时、多厂商账单拆分或是高并发洪峰,系统的稳定性必然脆如薄纸。LiteLLM 的轻量级介入并没有给系统带来明显的延迟劣势(实测反向代理耗时仅 2~4ms),但它换来的熔断、容灾、负载均衡和精确的 Token 消费追踪,能够让你彻底把精力抽离出来,专注于 Agent 上层业务逻辑的打磨。
建议今晚就可以在你的测试服开一个容器跑跑看,把之前散落在各个项目里的 API Key 收拢到一起,体验一下统一网关带来的清爽掌控感。