Chapter 12

生产最佳实践:把 LiteLLM 跑成工业级

前面 11 章讲完了"怎么用"。这一章讲"怎么用得住":秘钥不能硬编码、限流要分层、发布要灰度、容量要规划、故障要演练。最后附一份能直接改成你家样子的生产 config.yaml。

秘钥管理:绝不能硬编码

所有 API Key 走密钥管理服务,绝不 commit 到仓库、绝不写到镜像、绝不明文出现在配置文件里:

场景推荐方案LiteLLM 支持方式
AWSSecrets Manager / Parameter Storeuse_aws_secret_manager: True
GCPSecret Manageruse_google_kms: True
AzureKey Vaultuse_azure_key_vault: True
自建 K8sExternal Secrets + VaultHelm secretKeyRef 注入 env
本地开发direnv / 1Password CLI.envos.environ
# config.yaml 里引用即可, Proxy 启动时自动去 Secrets Manager 取
general_settings:
  use_aws_secret_manager: True

model_list:
  - model_name: gpt-4o
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY    # 背后是 Secrets Manager
密钥轮换演练每季度一次。真出事故时"我们没做过轮换"是最惨的。建一个 CronJob 每季度滚一次 API key,Proxy 自动重读 —— 业务零感知。

分层限流

LLM 服务不能只在一个地方限流。至少 4 层:

限什么工具生效时机
1. Ingress / API Gateway按 IP/user 的 RPSNginx / Kong / Cloudflare最早挡 DDoS
2. LiteLLM Virtual Key按 key 的 RPM/TPM/budgetProxy 内置业务级硬限
3. Router deployment按 provider 部署的 RPM/TPMRouter model_list保护上游不超配额
4. Provider 原生provider 自己的限制Azure/OpenAI 后台最后一道保险

4 层里第 2 和第 3 层最关键,前者保护你(不被单个业务烧死),后者保护上游(不被打挂)。

灰度与发布

LLM 产品发版的危险源:prompt 改了模型换了LiteLLM 升级了。每一项都可能让答案质量骤降。

  1. 模型切换要灰度:gpt-4o → gpt-4o-2024-11-20。用 tag-based routing,流量 1% → 10% → 50% → 100%。
  2. prompt 改了要跑 eval:至少 200 条金标样本,自动化对比前后分数,掉了就 block。
  3. Proxy 升级要双写:新老版本并行跑,流量镜像,对比结果一致再切。
  4. 回滚要 1 分钟内:出事时不是 debug 时间,先回滚再复盘。Helm 一条命令。
# 灰度示例: 50% 流量走新 prompt 版本
router_settings:
  enable_tag_filtering: true

model_list:
  - model_name: chat-v1          # 老版本
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
    model_info:
      tags: ["stable"]
  - model_name: chat-v2          # 新版本
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
    model_info:
      tags: ["canary"]

业务代码按 user_id hash 模 100 决定 tag:

tag = "canary" if hash(user_id) % 100 < 10 else "stable"   # 10% 灰度

resp = client.chat.completions.create(
    model="chat",
    messages=msgs,
    extra_body={"metadata": {"tags": [tag]}},
)

多活与容灾

"一个 region 的 Proxy 挂了,业务不能跟着挂"——基本要求:

容量规划

开容量会议前,至少算 3 个数:

  1. 峰值 RPS:历史数据的 P99 峰值 × 3(预留 headroom)。
  2. TPM 消耗:峰值 RPS × 平均 token / 60——你会知道至少要开几个 Azure deployment。
  3. 月预算:日均 RPS × 平均 cost × 30 × 业务增长系数。

举例:日 500 万请求,平均 1500 token,用 gpt-4o-mini:

QPS(峰值) ≈ 500w / 86400 × 3 ≈ 173
TPM 消耗  ≈ 173 × 1500 × 60 ≈ 1560w token/分钟

⇒ 需要至少 16 个 Azure GPT-4o-mini deployment(每个 100w TPM)
⇒ 月预算  ≈ 500w × 0.0006 × 30 = 9w 美元

这个表"月度 Review"一次,数字一漂移就提前加 deployment / 调预算,不然某天业务涨了预算烧完,服务突然 429。

故障演练

LLM 产品至少每季度演练 3 个场景:

演练注入方式期望恢复
OpenAI 全球故障把 OpenAI api_base 改成 404 假地址< 30s 切到 Claude
Azure East-US 配额爆发 100 并发打 East-US< 5s 切到 West-US
Redis 挂重启 Redis Sentinel 主节点限流/缓存降级模式,主流程可用
Postgres 挂主节点 killVirtual Key 校验降级,新 key 不能生成但老 key 能用
Proxy pod OOMkill -9 podHPA 自动拉新 pod,请求丢失 < 1s

每个演练写一份 runbook,新值班人第一周必须看完。

性能调优要点

生产 config.yaml 完整模板

下面是一个能直接改成你家情况的完整生产配置,覆盖了前面 11 章的所有要点:

###############################################################
# LiteLLM Proxy 生产配置 (config.yaml)
# ─────────────────────────────────────────────────────────────
# • 4 provider × 6 deployment (Azure/OpenAI/Anthropic/Gemini/DeepSeek)
# • fallback 链 / context_window 切长 / content_policy 旁路
# • Redis 限流+缓存, Postgres 存 Virtual Keys
# • Langfuse 观测 + Prometheus 指标 + S3 归档
# • Slack + PagerDuty 告警分级
###############################################################

model_list:
  # ── 聊天主模型: Azure 三部署 + OpenAI 备
  - model_name: chat
    litellm_params:
      model: azure/gpt4o-east
      api_key: os.environ/AZURE_EAST_KEY
      api_base: os.environ/AZURE_EAST_BASE
      api_version: "2024-10-21"
      rpm: 1000
      tpm: 2000000
    model_info:
      tags: ["stable", "region:east"]
  - model_name: chat
    litellm_params:
      model: azure/gpt4o-west
      api_key: os.environ/AZURE_WEST_KEY
      api_base: os.environ/AZURE_WEST_BASE
      rpm: 800
      tpm: 1500000
    model_info:
      tags: ["stable", "region:west"]
  - model_name: chat
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
    model_info:
      tags: ["stable", "provider:openai"]

  # ── 备用大模型: Claude Sonnet
  - model_name: claude-sonnet
    litellm_params:
      model: anthropic/claude-sonnet-4-5
      api_key: os.environ/ANTHROPIC_API_KEY
      rpm: 500
      tpm: 500000

  # ── 廉价模型: Gemini Flash / DeepSeek
  - model_name: cheap
    litellm_params:
      model: gemini/gemini-2.5-flash
      api_key: os.environ/GEMINI_API_KEY
  - model_name: cheap
    litellm_params:
      model: deepseek/deepseek-chat
      api_key: os.environ/DEEPSEEK_API_KEY

  # ── 长上下文特供
  - model_name: long-context
    litellm_params:
      model: gemini/gemini-2.5-pro
      api_key: os.environ/GEMINI_API_KEY

  # ── 推理模型
  - model_name: reasoner
    litellm_params:
      model: openai/o3
      api_key: os.environ/OPENAI_O3_KEY
      max_budget: 200.0
      budget_duration: 1d

###############################################################
router_settings:
  routing_strategy: usage-based-routing-v2
  num_retries: 3
  retry_after: 5
  timeout: 60
  cooldown_time: 60
  allowed_fails: 3
  enable_pre_call_checks: true
  enable_tag_filtering: true

  redis_host: os.environ/REDIS_HOST
  redis_port: 6379
  redis_password: os.environ/REDIS_PASSWORD

  fallbacks:
    - chat: [claude-sonnet, cheap]
    - reasoner: [claude-sonnet]
    - cheap: [chat]

  context_window_fallbacks:
    - chat: [long-context]               # 超 128K 自动切 gemini-pro

  content_policy_fallbacks:
    - chat: [claude-sonnet]              # Azure 审核拦, 走 Claude

###############################################################
litellm_settings:
  drop_params: true
  set_verbose: false
  request_timeout: 60
  telemetry: false

  cache: true
  cache_params:
    type: redis
    host: os.environ/REDIS_HOST
    port: 6379
    password: os.environ/REDIS_PASSWORD
    ttl: 1800
    namespace: "prod:llm"

  success_callback: ["langfuse", "prometheus", "s3"]
  failure_callback: ["langfuse", "sentry"]

  s3_callback_params:
    s3_bucket_name: company-llm-audit
    s3_region_name: us-east-1

  turn_off_message_logging: false         # 全文留存 (已有脱敏 callback)

###############################################################
general_settings:
  master_key: os.environ/LITELLM_MASTER_KEY
  database_url: os.environ/DATABASE_URL
  database_connection_pool_limit: 100
  database_connection_timeout: 60

  use_aws_secret_manager: true
  store_model_in_db: true                  # 支持 UI 改模型

  ui_access_mode: admin_only
  allow_user_auth: true
  enforce_user_param: true                 # 每请求必须带 user

  alerting: ["slack", "pagerduty"]
  alerting_threshold: 60
  alert_types:
    - "llm_exceptions"
    - "llm_too_slow"
    - "llm_requests_hanging"
    - "budget_alerts"
    - "cooldown_deployment"
    - "daily_reports"

  environment_variables:
    LANGFUSE_PUBLIC_KEY: os.environ/LANGFUSE_PK
    LANGFUSE_SECRET_KEY: os.environ/LANGFUSE_SK
    LANGFUSE_HOST: https://langfuse.internal
    SLACK_WEBHOOK_URL: os.environ/SLACK_WEBHOOK_URL

这份配置可以直接用在一个中等规模公司的 AI 网关上——把 Key/URL 替换成你自己的、把 tag 改成贴合你业务的,就能上生产。

Launch checklist:上线前最后一遍核对

上线当天,请逐条确认:
  1. [ ] config.yaml 里没有明文 key,全部 os.environ/
  2. [ ] Postgres + Redis 已高可用部署,备份策略已开。
  3. [ ] Proxy ≥ 3 replica,跨 AZ / HPA 已开。
  4. [ ] Virtual Keys 已全部发放,Master Key 只在管理员手中。
  5. [ ] 每个业务的 budget / RPM / TPM / 模型白名单都写死。
  6. [ ] fallbacks 链验证过(手动 404 主模型测试)。
  7. [ ] context_window_fallbacks / content_policy_fallbacks 配好。
  8. [ ] Langfuse / Prometheus / S3 callback 都能收到数据。
  9. [ ] Slack / PagerDuty 告警测过一次。
  10. [ ] eval 金标跑过,分数合格。
  11. [ ] /health/liveliness 和 /health/readiness 都通。
  12. [ ] Grafana 五图(RPS/cost/p95/error/cooldown)已搭好。
  13. [ ] 回滚脚本验证过,< 1 分钟能滚。
  14. [ ] Runbook 已写,含 5 个主要故障场景。
  15. [ ] 预算报表已 schedule 每日自动发给财务/主管。

常见架构反模式

  1. 每个业务自己接 OpenAI:key 散、账散、无审计。第一步永远是上 Proxy 统一入口。
  2. Proxy 和业务混部:一个业务 OOM 把整个 AI 网关带挂,全公司瘫。独立部署。
  3. 只有 1 个 provider:OpenAI 全球故障那一晚你就知道代价。至少三家。
  4. 没 fallback 跑生产:任何 provider 抖一下业务全报错。每个关键 model_name 都要有 fallback。
  5. 没 eval 发 prompt:靠肉眼测几条上线,幻觉率翻倍还不知。自动化 eval 卡发布。
  6. 不设日预算:月预算可能前 3 天就烧光,后 27 天 429。日/月双限。
  7. 不做灰度:prompt 改一次全量发,回滚才发现线上掉 20% 质量。永远灰度。
  8. callback 同步 IO:日志系统慢 500ms,AI 跟着慢 500ms。async + 超时 + drop。
  9. 把 user 字段省了:出事抓不到人。gateway 强制塞 user。
  10. 只看 mean 延迟:mean 2s p99 30s,用户体验全看 p99。

写在最后

LiteLLM 不是银弹——它是一把把散装 provider 组装成可运维系统的扳手。这 12 章讲的事情总结成一句话:

业务代码只关心"调 chat 模型回答用户",其他事(路由、容灾、限流、缓存、观测、成本、合规)全部下沉到基础设施。出事时一处调配置、一次灰度、一条回滚——而不是去改 12 个业务仓库。

你可能一开始只会用到其中的 30%——那是好事。不要一上来就把 config.yaml 抄成 300 行。先用 SDK 解决跨 provider 的问题,流量上来了换 Proxy,规模再大加 Virtual Keys 和 Admin UI。按需演进才是工程上的美德。

本章小结