597457.xyz

Back

自建 OpenRouter 智能网关:自动选最优 Provider、防盗刷、自动自建 OpenRouter 智能网关:自动选最优 Provider、防盗刷、自动

本文只讲方法:如何在 Cloudflare Workers 上从零搭一个 OpenRouter 代理网关。所有密钥、域名都请替换成你自己的,文中用 <...> 标注占位。它不依赖任何第三方服务,代码可直接复制部署。

如果你用过 OpenRouter 就会发现一个尴尬的事实:同一个模型(比如 deepseek/deepseek-v4-flash)背后挂着好几家 Provider,每家价格不同、是否支持隐式缓存不同、稳定性也不同。OpenRouter 默认会在它们之间随机/轮流调度——这对长会话、吃 KV Cache 的项目很不友好:缓存命中率一掉,成本和延迟双双起飞。

自己搭一个轻量网关,就能把这件事完全掌控起来。下面是一套已在生产流量上跑通的设计与实现。

网关解决的三件事#

  1. 自动选最优 Provider:定时拉取 OpenRouter 的模型端点列表,按「缓存友好 + 价格优先」打分,锁定单一 Provider 并保持一个锁定期不换(长会话实测 KV Cache 命中率可达 98%)。
  2. 防盗刷:客户端只持有一个自定义的 CUSTOM_ACCESS_KEY,网关转发给上游时再替换成真正的 OPENROUTER_API_KEY。真实 Key 永远不下发到客户端。
  3. 自动容错:上游 429 限流自动退避重试;卡顿 / 超时 / 5xx 连续若干次自动熔断,冷却该 Provider 并立即换锁,客户端基本无感。

多模型支持:任意模型第一次请求时自动寻优并锁定,之后一直锁着;每个模型独立寻优、独立锁、独立熔断,互不干扰。用过的模型自动记录,/v1/models 和 /stats 按模型返回。

架构概览#

客户端(Cherry Studio 等 OpenAI 兼容客户端)
        │  Authorization: Bearer <CUSTOM_ACCESS_KEY>
        ▼
Cloudflare Worker(openrouter-gateway)
   ├─ Cron 每 3 小时:拉端点列表 → 打分 → 写候选
   ├─ 请求路径:鉴权 → 读锁/寻优 → 强制 provider.order=[锁] → 转发上游
   └─ KV(PROVIDER_KV):锁 / 候选 / 失败计数 / 冷却 / 统计
        │
        ▼
OpenRouter /api/v1/chat/completions(Bearer <OPENROUTER_API_KEY>)
plaintext

对外完全兼容 OpenAI 的 /v1/chat/completions,所以任何支持自定义 Base URL 的客户端都能直接接。

核心设计决策#

决策点结论原因
寻优周期Cron 每 3 小时大项目要跑 2–3 小时,太频繁会中途换 Provider 丢缓存
锁定机制候选制 + 活跃续期cron 结果只写候选;活跃请求续期当前锁(锁永不掉),空闲后锁过期才换新。彻底避免大项目中途换上游
打分公式Score = 吞吐量 / (有效输入价×0.4 + 输出价×0.6 + ε)有效输入价 = 命中率×缓存读取价 + (1−命中率)×输入价
命中率取值支持隐式缓存的按 98%,不支持的按 0避免选中「便宜但没缓存」的 Provider,实际反而更贵
缓存奖励CACHE_BONUS=2支持隐式缓存的得分 ×2,让缓存友好优先于纯低价(可调)
时段价格按当前 UTC 时段取价部分官方端点有峰/闲时半价,闲时官方自然胜出,峰值便宜第三方也能翻盘
429 vs 卡顿429 原地重试不切换;卡顿熔断切换429 是暂时限流等几秒就好,切换会丢缓存;真卡顿才值得换
KV 结构每模型一套:BEST_PROVIDER:{model} / PROVIDER_CANDIDATE:{model} / PROVIDER_FAILURE:{model} / PROVIDER_COOLDOWN:{model} / STATS:{model};全局 MODELS_SEEN全部 JSON 字符串,多模型互不干扰
寻优节流候选 10 分钟内新鲜则复用,不重复拉 API避免并发首次请求重复寻优,控制 OpenRouter API 调用量

几个实测确认的关键事实(与 OpenRouter 平台本身有关,不涉及任何私有部署):

  • OpenRouter 按 Provider 各自的价格计费(pass-through,无加价),所以端点价格参与打分是真实有效的。
  • /api/v1/models/{model}/endpoints 是公开接口(无需 key),返回每个 Provider 的:独立定价(prompt/completion/input_cache_read)、supports_implicit_caching、status、uptime、throughput(可能为 null)。
  • provider.order 接受 slug(端点 tag 的第一段,如 deepseek),不是显示名。
  • 部分官方端点有分时段定价(overrides):闲时半价。
  • 实测某些模型(如 DeepSeek V4 Flash)无法连通其官方端点,但不可用端点会被 status / 熔断自动排除,无需担心被锁到。

从零部署#

前置:本机已装 Node.js(v22+)与 npm。

1. 初始化并安装 wrangler

mkdir openrouter-gateway && cd openrouter-gateway
npm init -y
npm install -D wrangler
bash

2. 登录 Cloudflare

npx wrangler login
bash

会弹出浏览器 OAuth 授权页,手动点 Allow 即可。wrangler login 会等回调,不要在前台让它超时被杀。

3. 创建 KV 命名空间

npx wrangler kv namespace create PROVIDER_KV
bash

wrangler 4.x 语法是 kv namespace(带空格),不是 kv:namespace。成功后把输出的 id = "xxx" 填到 wrangler.toml。若报 already exists,先注释掉 wrangler.toml 里的 [[kv_namespaces]] 段再跑。

4. 设置两个密钥(交互式输入,不会落盘到代码)

npx wrangler secret put OPENROUTER_API_KEY   # 粘贴你的 sk-or-v1-...
npx wrangler secret put CUSTOM_ACCESS_KEY    # 自定义访问密钥,自己生成一段足够长的随机串
bash

也支持管道输入:echo "$key" | npx wrangler secret put OPENROUTER_API_KEY。

5. 编写 wrangler.toml

routes 必须放在 [triggers] 之前,否则会被解析进 triggers 报 warning。绑定自定义域名后,workers.dev 默认地址会自动停用(更干净、防污染)。

6. 部署

npx wrangler deploy
bash

部署输出应包含你的自定义域名与 schedule: 0 */3 * * *。

7. 部署后立即验证

# ① 手动触发一次寻优(同步等待返回)
curl -X POST -H "Authorization: Bearer <你的 CUSTOM_ACCESS_KEY>" https://<你的网关地址>/__cron

# ② 查看价格对比(含当前锁、剩余时间;支持 ?model= 过滤)
curl -H "Authorization: Bearer <你的 CUSTOM_ACCESS_KEY>" https://<你的网关地址>/stats

# ③ 发一个真实对话请求(非流式)
curl https://<你的网关地址>/v1/chat/completions \
  -H "Authorization: Bearer <你的 CUSTOM_ACCESS_KEY>" -H "Content-Type: application/json" \
  -d '{"model":"deepseek/deepseek-v4-flash-0731","messages":[{"role":"user","content":"hi"}],"max_tokens":10}'

# ④ 连发 3 次,确认响应里 provider 字段始终一致(锁定生效)
# ⑤ 测流式:加 "stream":true,应返回 text/event-stream
bash

完整 Worker 代码#

把下面内容保存为 src/index.js。它不含任何密钥——OPENROUTER_API_KEY 与 CUSTOM_ACCESS_KEY 都来自第 4 步的 wrangler secret,运行时以环境变量注入。

可调参数(wrangler.toml → [vars])#

变量默认说明
TARGET_MODELdeepseek/deepseek-v4-flash-0731默认模型(客户端未指定时兜底;保证 cron 至少寻优它)
HIT_RATE0.98支持隐式缓存的 Provider 的命中率假设
CACHE_BONUS2缓存奖励系数(越大越缓存友好)
MIN_UPTIME90Provider 最低可用性(%),低于则排除
SLOW_THRESHOLD20卡顿判定:等待上游响应头超过 N 秒视为慢(0 = 禁用)
FAIL_LIMIT3连续失败 N 次触发熔断换 Provider
COOLDOWN_SECONDS600被熔断 Provider 的冷却时间(秒)

调参后重新 npx wrangler deploy 生效。比如某项目输出 token 特别多、嫌官方贵,可把 CACHE_BONUS 调低(如 1.2)让便宜 Provider 胜出;想更激进地保缓存就调高。

客户端怎么用#

任何 OpenAI 兼容客户端(Cherry Studio、OpenWebUI、各种 SDK)都能直接接,只需三步:

  • Base URL:https://<你的网关地址>
  • API Key:<你的 CUSTOM_ACCESS_KEY>(就是第 4 步自己设的那个随机串,不是 OpenRouter 的 Key)
  • 模型 ID:填 OpenRouter 的模型 ID 即可,例如 deepseek/deepseek-v4-flash-0731;换模型直接改这里,网关会自动寻优,无需改配置。

运维接口#

接口方法说明
/v1/chat/completionsPOST主代理接口(OpenAI 兼容)
/v1/modelsGET模型列表(客户端启动探测用)
/statsGET价格对比 + 当前锁实时信息(支持 ?model= 过滤)
/__cronPOST手动触发寻优(同步等待结果)
# 手动触发寻优(同步,等待结果返回)
curl -X POST -H "Authorization: Bearer <你的 CUSTOM_ACCESS_KEY>" https://<你的网关地址>/__cron

# 查看价格对比统计(含当前锁、剩余时间)
curl -H "Authorization: Bearer <你的 CUSTOM_ACCESS_KEY>" https://<你的网关地址>/stats
bash

故障排查#

症状排查步骤
域名打不开① npx wrangler deployments 看部署是否成功;② CF 面板 Workers → 域名绑定是否在;③ DNS 记录是否自动创建(子域 CNAME);④ 等 1–5 分钟 DNS 生效
401 鉴权失败CUSTOM_ACCESS_KEY 是否被换过?CF 面板 Settings → Variables and Secrets 里核对(secret 不回显,重设一次即可)
/stats 某模型返回 null该模型从没寻优成功:① 手动调 /__cron 看返回;② 若返回 failed,检查 OpenRouter key 是否有效;③ 模型 ID 是否在 OpenRouter 上存在
请求返回 404检查模型 ID 是否含 %2F(OpenRouter endpoints 接口不吃 URL 编码的斜杠,代码里不能用 encodeURIComponent 编码模型路径)
锁不住(每次 provider 不同)KV 里 BEST_PROVIDER 没写入:① 手动 /__cron 一次;② 检查 KV 命名空间 id 是否与 wrangler.toml 一致;③ KV 最终一致性,写入后稍等几秒
上游报错/卡顿频繁看 /stats 的 lock 字段与账单估算;SLOW_THRESHOLD/FAIL_LIMIT/COOLDOWN_SECONDS 都在 wrangler.toml,调参后重新 deploy
想要更便宜 / 更缓存友好调 CACHE_BONUS(默认 2,越大越缓存友好)、HIT_RATE(默认 0.98);改完 deploy
想看实时日志wrangler tail 可能受本机网络限制连不上,可改用 CF 面板 Workers → Logs 看实时日志
换/加模型直接改客户端模型 ID 即可(自动寻优);要改默认模型才动 wrangler.toml 的 TARGET_MODEL

踩坑记录#

  1. wrangler kv:namespace create 在 wrangler 4.x 已改为 wrangler kv namespace create(去掉冒号)。
  2. routes 必须放在 [triggers] 之前,否则被解析进 triggers 报 warning。
  3. OpenRouter 的 /models/{id}/endpoints 不接受 %2F 编码的模型 ID(encodeURIComponent 会把 / 编码成 %2F 导致 404),必须用原始斜杠路径。这是寻优一直失败、stats 一直 404 的最常见根因。
  4. 部分官方端点输出价是第三方(如 OpenInference)的约 9 倍:默认 CACHE_BONUS=2 时官方仍会胜出;若某项目输出 token 特别多嫌贵,调低 CACHE_BONUS(如 1.2)即可让便宜 Provider 胜出。
  5. 本地调试:建 .dev.vars 填真实值(格式同 wrangler secret 的键值对),npx wrangler dev --test-scheduled,另开终端 curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*" 手动触发 cron。

结语#

这套网关本质上是把「OpenRouter 多 Provider 调度」这件事从黑盒变成白盒:价格、缓存、稳定性全在你手里。最关键的收益是 KV Cache 命中率——长会话项目一旦锁定单一 Provider,缓存红利会直接反映在账单和延迟上。代码不到 200 行核心逻辑,跑在 Cloudflare 的免费额度里基本零成本,值得一试。

自建 OpenRouter 智能网关:自动选最优 Provider、防盗刷、自动容错
https://v3.597457.xyz/blog/openrouter-smart-gateway
Author HJP
Published at 2026年8月20日