AI 网关工程实战:把多模型路由、缓存、限流、可观测性装进生产架构
一篇关于 LLM 应用基础设施层——AI Gateway——的工程实战指南。覆盖多模型路由、语义缓存、统一可观测性、限流与降级、Guardrails 五大主题,结合 LiteLLM、Portkey、Cloudflare AI Gateway、OpenRouter 四种主流方案的真实接口形态与代码示例。
约 21 分钟阅读6,025 字18 次阅读博主
一篇关于 LLM 应用基础设施层——AI Gateway——的工程实战指南。覆盖多模型路由、语义缓存、统一可观测性、限流与降级、Guardrails 五大主题,结合 LiteLLM、Portkey、Cloudflare AI Gateway、OpenRouter 四种主流方案的真实接口形态与代码示例。
2025 年之前,大多数团队调用 OpenAI、Anthropic 还是直接在业务代码里写"fetch + API key"。一年过去,这种"裸调"模式在生产环境里暴露出三类问题:
解决方案在 2024–2026 年逐渐收敛成一层独立的"AI Gateway"。它像七层网络里的反向代理 + WAF:单点入口、统一鉴权、智能路由、可观测、限流降级。不同开源/商业实现已经把这个抽象做到了可生产状态。
本文选四种典型方案做工程拆解:LiteLLM(Python 生态的事实标准)、Portkey(TypeScript 的现代选择)、Cloudflare AI Gateway(边缘网关 / SaaS)、OpenRouter(多供应商聚合平台)。重点不是"哪家最好",而是把每家在工程上要解决的同一类问题——路由、缓存、可观测、限流、Guardrails——落到具体接口、具体字段、具体 YAML/TypeScript 配置上。
截至 2026 年中,几乎所有主流供应商都提供 OpenAI Chat Completions 兼容端点。这意味着网关层的"翻译"工作被极大压缩——网关只需要处理鉴权、请求体字段差异(如 Anthropic 的 `system` 顶级字段)、响应字段差异(如 Anthropic 的 `content[].text` vs OpenAI 的 `choices[0].message.content`)。
LiteLLM 把这种"翻译"做到极致——它本身是一个 Python SDK + Proxy 双形态的库,对外暴露 OpenAI 兼容的 `/v1/chat/completions` 端点,把 `openai/gpt-4o`、`anthropic/claude-sonnet-4.5`、`bedrock/anthropic.claude-3` 等命名直接路由到对应供应商。GitHub 数据(2026-06-13 拉取):50,208 stars / 8,837 forks。
```python
from litellm import completion import os
os.environ["OPENAI_API_KEY"] = "sk-..." os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."
resp = completion( model="anthropic/claude-sonnet-4.5", messages=[{"role":"user","content":"用一句话介绍 AI Gateway"}], ) print(resp.choices[0].message.content) ```
Portkey(12,049 stars / 1,125 forks,MIT,TypeScript 实现,截至 2026-06-13)的定位稍有不同——它强调"AI Gateway + Guardrails 一体化",自称支持 1,600+ 模型、50+ 内置 Guardrails。它的 SDK 也兼容 OpenAI,但更突出 production-grade 特性:fallback chains、conditional routing、automatic retries、semantic caching。
```typescript // Portkey TypeScript SDK import { Portkey } from 'portkey-ai';
const client = new Portkey({ apiKey: process.env.PORTKEY_API_KEY!, config: 'pc-***', // Portkey Config ID(路由/重试策略保存云端) });
const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [{ role: 'user', content: '你好' }], }); ```
| 方案 | 形态 | 适合场景 |
|---|---|---|
| LiteLLM Proxy | 自托管 Python 服务 | 完全控制 / 内部网络 / 数据合规 |
| Portkey | 云端 SaaS + 开源 Gateway | 多区域低延迟 + 不愿自运维 |
| Cloudflare AI Gateway | 边缘 SaaS(基于 CF Workers) | 已用 CF 生态 / 全球边缘缓存 / 零运维 |
| OpenRouter | 多供应商聚合 SaaS | 个人开发者 / 小团队 / 想"一键试遍所有模型" |
```mermaid graph LR A[业务代码] -->|OpenAI 格式 HTTP| B(AI Gateway) B -->|OpenAI 格式| C[OpenAI] B -->|Anthropic 格式| D[Anthropic] B -->|Vertex 格式| E[Google Vertex] B -->|自建 vLLM 格式| F[自托管 vLLM] B --> G[统一日志 / 计量] B --> H[语义缓存层] ```
判断标准:数据合规要求高(金融/医疗)→ LiteLLM Proxy 自托管;已有 Cloudflare 生态 → AI Gateway;团队 < 5 人且不愿运维 → OpenRouter;需要 guardrails / 复杂 fallback 链 → Portkey。
网关层最重要的工程价值是在多个上游之间做决策,而不是单纯转发。
LiteLLM Router 支持 `fallbacks` 配置:定义一个模型列表,按顺序重试,第一个失败自动切到下一个:
```python
from litellm import Router
model_list = [ {"model_name": "gpt4o-prod", "litellm_params": {"model": "openai/gpt-4o", "api_key": os.environ["OPENAI_API_KEY"]}}, {"model_name": "claude-prod", "litellm_params": {"model": "anthropic/claude-sonnet-4.5", "api_key": os.environ["ANTHROPIC_API_KEY"]}}, {"model_name": "deepseek-prod", "litellm_params": {"model": "deepseek/deepseek-chat", "api_key": os.environ["DEEPSEEK_API_KEY"]}}, ]
router = Router( model_list=model_list, fallbacks=[{"gpt4o-prod": ["claude-prod"]}, {"claude-prod": ["deepseek-prod"]}], num_retries=2, timeout=30, ) ```
Portkey 的 `config` JSON 表达力更强:
```json { "strategy": { "mode": "fallback" }, "targets": [ { "provider": "openai", "model": "gpt-4o", "weight": 0.7 }, { "provider": "anthropic", "model": "claude-sonnet-4.5", "weight": 0.3 } ], "retry": { "attempts": 3, "on_status_codes": [429, 500, 502, 503] } } ```
当一个模型多家供应商都提供时(例如 Llama-3-70B 同时在 Together / Fireworks / Groq 上),可以通过权重或"价格优先"策略动态分配。
```python
model_list = [ {"model_name": "llama3-70b", "litellm_params": {"model": "together_ai/meta-llama/Meta-Llama-3-70B", "api_key": "..."}}, {"model_name": "llama3-70b", "litellm_params": {"model": "fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct", "api_key": "..."}}, {"model_name": "llama3-70b", "litellm_params": {"model": "groq/llama3-70b-8192", "api_key": "..."}}, ] router = Router(model_list=model_list, routing_strategy="usage-based-routing-v2") ```
`usage-based-routing-v2` 是 LiteLLM 内置策略,会把请求发往"最近最少用"的上游,避免单一供应商触发限流。
Cloudflare AI Gateway 提供两种调用模式:Unified API(OpenAI 兼容)和 Provider Native(直接代理到目标供应商,仅做日志/缓存/计费增强)。后者对已有 Anthropic SDK 的迁移成本为零——只把 `base_url` 改成 CF 的 endpoint 即可。
```typescript // 把 Anthropic SDK 指向 Cloudflare AI Gateway(Provider Native 模式) import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({ apiKey: process.env.CF_AIGATEWAY_TOKEN, // CF Gateway 颁发的 token baseURL: 'https://gateway.ai.cloudflare.com/v1/<account_id>/<gateway_id>/anthropic', });
const msg = await anthropic.messages.create({ model: 'claude-sonnet-4.5', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello' }], }); ```
Cloudflare 官方文档(截至 2026-06-13)支持的供应商列表包括:OpenAI、Anthropic、Workers AI、Amazon Bedrock、Google Vertex AI、Azure OpenAI、Groq、HuggingFace、Mistral、Replicate、xAI、DeepSeek 等——基本覆盖了 2026 年所有主流选项。
LLM 调用最大的隐性成本是重复提问。客服 FAQ、文档问答、代码补全都存在大量相似请求。如果每次都重新调用模型,等于在烧钱。
LiteLLM Proxy 内置语义缓存(基于 embedding 相似度),可通过配置启用:
```yaml
litellm_settings: cache: True cache_params: type: qdrant-semantic # 需配合 Qdrant 向量库 qdrant_url: http://localhost:6333 qdrant_collection_name: llm-cache similarity_threshold: 0.95 # 余弦相似度阈值
model_list:
支持的 backend 列表包括 Redis、Qdrant、Postgres(pgvector)、S3、In-memory。`similarity_threshold` 是核心旋钮——0.95 意味着"几乎相同问题才命中",0.85 可能误命中。
Portkey 默认开启 simple cache(精确匹配),开启 semantic cache 需在 config 里指定:
```json { "cache": { "mode": "semantic", "max_age": 3600, "similarity_threshold": 0.85 } } ```
Portkey 的优势是缓存粒度可配置到 namespace + user 维度——同一问题在客户 A 的对话里命中一次,不会污染客户 B 的上下文。
Cloudflare 的缓存策略最"激进"——基于响应头的 `Cache-Control` 或自定义 `cf-aig-cache-ttl` header 决定 TTL。命中发生在 300+ 边缘节点,对全球用户延迟极低。
```typescript // 在请求里设置缓存 TTL fetch('https://gateway.ai.cloudflare.com/v1/.../openai/chat/completions', { method: 'POST', headers: { 'Authorization': 'Bearer *** 'cf-aig-cache-ttl': '86400', // 24 小时 'Content-Type': 'application/json', }, body: JSON.stringify({...}), }); ```
坑:语义缓存绝不适合"用户特定上下文"的请求(如个性化推荐、用户历史对话)。要按 `user_id` 或 `session_id` 划分缓存 namespace,否则不同用户会读到对方的回答。
AI 网关把"调用一次 LLM"这件事的全链路元数据沉淀下来——这一步是从 demo 走向 production 的分水岭。
LiteLLM Proxy 支持把每次请求/响应转发到 Langfuse(28,999 stars / 3,006 forks,截至 2026-06-13)。在 `config.yaml` 里加几行:
```yaml litellm_settings: success_callback: ["langfuse"] failure_callback: ["langfuse"]
environment_variables: LANGFUSE_PUBLIC_KEY: pk-lf-*** LANGFUSE_SECRET_KEY: sk-lf-*** LANGFUSE_HOST: https://cloud.langfuse.com ```
启用后 Langfuse UI 里会出现:trace ID、prompt、completion、token 数、latency、成本估算、按 tag/user/model 聚合的 dashboard。Helicone 集成方式类似(一个 callback 字符串切换即可)。
Cloudflare 的优势是零配置就有 dashboard——每个 Gateway 在 CF 控制台自带:
实战经验:CF AI Gateway 的"自定义日志字段"是杀手锏——在请求里加 `cf-aig-metadata: {"feature":"customer-support","tier":"pro"}`,dashboard 就能按 feature/tier 切分成本。这对"算 AI 账"是刚需。
OpenRouter 提供公开的 Rankings 页面,统计每个模型/应用商的调用量。截至 2026-06-13 抓取的官方数据:月 token 量 100T+,全球用户 8M+,覆盖 60+ 供应商 / 400+ 模型。对选型决策("哪个模型性价比最好")很有参考价值。
LiteLLM Proxy 的限流颗粒度可到"虚拟 key"——给每个团队/项目/客户分配独立的 API key,分别设置 RPM/TPM 上限:
```yaml general_settings: master_key: sk-litellm-master database_url: postgresql://...
litellm_settings: key_generation_settings: team_key_generation: true
```
Cloudflare AI Gateway 的"Rate limiting"是 Beta 阶段的能力(在 `/features` 列表标记 Beta),通过 Workers 脚本绑定自定义规则。
当上游连续失败 N 次,网关应该自动切断一段时间(circuit open),避免雪崩。LiteLLM 的 `Router` 默认带这个能力:
```python router = Router( model_list=[...], fallbacks=[{"gpt4o": ["claude-sonnet-4.5"]}], num_retries=2, timeout=15, allowed_fails=3, # 连续失败 3 次后切到下一个 cooldown_time=30, # 冷却 30 秒 ) ```
Portkey 内置 50+ Guardrails(截至 2026-06-13 仓库 README 描述),覆盖:
```json { "input_guardrails": [ { "id": "pii-redaction", "params": { "entities": ["email", "phone"] } }, { "id": "prompt-injection-detection", "params": { "threshold": 0.9 } } ], "output_guardrails": [ { "id": "json-schema", "params": { "schema": {...} } } ] } ```
Cloudflare AI Gateway 把 Guardrails 放在"Workers AI Binding"层——通过 Cloudflare Workers 脚本插入 DLP(数据丢失防护)逻辑。Portkey 的优势是开箱即用 + 50+ 内置规则,自定义 Workers 更灵活但需要写代码。
| 维度 | LiteLLM Proxy | Portkey Gateway | Cloudflare AI Gateway | OpenRouter |
|---|---|---|---|---|
| 部署 | 自托管 Python | 自托管/云 SaaS | 边缘 SaaS | 云 SaaS |
| GitHub stars | 50,208 | 12,049 | — | — |
| License | MIT | MIT | 商业 | 商业 |
| 模型覆盖 | 100+ | 1,600+ | 20+ 主流 | 400+ |
| 语义缓存 | ✓(需外部向量库) | ✓(内置) | ✓(边缘缓存) | ✗ |
| Guardrails | 需外部 | ✓ 50+ 内置 | Workers 自定义 | 基础 |
| 可观测性 | callback 集成 | 内置 | 内置 dashboard | 基础 |
| 限流 | 虚拟 key | 虚拟 key | Workers | 配额 |
| 适合 | 自托管 / 合规 | 现代 TypeScript 栈 | CF 生态 / 全球边缘 | 个人 / 小团队 |
注:GitHub star 数为 2026-06-13 通过 `api.github.com/repos/...` 实时拉取;模型覆盖数字源自各方案官方 README/官网,截至 2026-06 中。
踩过的几个真实坑,按重要性排序:
不要在 `config` JSON 里硬编码 API key——用环境变量或密钥管理(Vault / AWS Secrets Manager)。LiteLLM Proxy 的 `config.yaml` 里支持 `os.environ/OPENAI_API_KEY` 这种语法,是惯例。
缓存 namespace 必须包含 `user_id` 或 `session_id`——否则会跨用户污染(pitfall 见 LiteLLM cache docs)。最简单的工程做法是把 user_id 拼进缓存 key。
fallback 链不要超过 3 层——3 层以上说明上游选型有问题,应该收敛供应商。复杂 fallback 链在生产事故时排查极困难。
Cloudflare AI Gateway 的 Rate Limiting 还在 Beta(截至 2026-06-13 官方文档标记)——生产用前关注 changelog。
Portkey 的 `config` JSON 通过 API 存云端——意味着你的路由策略是托管在 Portkey 平台的;如果需要"完全自托管策略",必须用 Portkey 开源 Gateway 自部署。
OpenRouter 不是"免费替代品"——它是聚合层,最终还是调用上游模型,定价随上游波动。把它当"统一接口"用,不要期待"更便宜"。
不要把 prompt 模板塞进 config——很多团队图省事把完整 system prompt 写进网关 config JSON 里。问题是:prompt 迭代频率远高于路由策略,写在 config 里会让 review 与 diff 变得困难。正确做法是 prompt 模板作为独立资产(Langfuse 的 prompt management 模块、或自建的 prompt registry),网关 config 只引用 prompt ID 与变量。
多供应商切换时成本模型会变——Anthropic 的 prompt cache 命中按 1.25 倍计费、写入按 1.25 倍计费;OpenAI 的 prompt cache 命中按 0.5 倍、写入按 2 倍计费。如果生产代码在两个供应商之间频繁切换,记得把"cost calculation"逻辑也搬到网关层统一算,不要每个业务调用点自己乘系数。
Worker / 边缘缓存在 streaming 场景下不友好——Cloudflare AI Gateway 的边缘缓存在 streaming 响应场景下会等待完整 body 才返回,对长生成场景会显著增加首 token 延迟。要么关闭 streaming,要么接受这个延迟代价,或者把"是否可缓存"做成 prompt 级别的属性——例如分类场景可缓存、对话生成不可缓存。
AI Gateway 不是银弹,但它解决了一类被反复踩过的工程问题:多供应商管理、成本可观测、故障降级、缓存加速、安全防护。2026 年这个赛道已经清晰收敛到 4 类玩家——开源自托管(LiteLLM)、现代 SaaS(Portkey)、边缘集成(Cloudflare)、聚合平台(OpenRouter)。
对工程团队的实际建议:
不要等到第一次"上游挂了导致整站崩溃"才补这层。
Conversation
0 条