news 2026/9/2 1:23:03

零成本搭建AI聚合网关:基于Cloudflare Workers的云上部署实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零成本搭建AI聚合网关:基于Cloudflare Workers的云上部署实践

最近在做一个多模型接入的小项目,发现每次对接不同的 AI 服务商都要写一堆适配代码,密钥管理也散落各处,临时想统一走一个入口却找不到趁手的工具。花了一周时间,我直接自己搓了一个轻量级 AI 聚合网关,并且利用 Cloudflare 的免费额度完成了云上部署,整个过程没有买服务器、没有备案,成本几乎为零。

这篇文章会把整个思路和实现过程完整记录下来,从核心概念、环境准备、网关代码实现,到一键部署、自动发布、常见排错,一次讲清楚。不管是想自己搭一个 AI 网关,还是想白嫖云资源做个人项目,这篇文章都值得收藏。

1. 背景与核心概念

1.1 什么是 AI 聚合网关

先来说说 AI 聚合网关到底是干什么的。

正常情况下,一个应用如果同时对接多个 AI 模型提供方,比如 OpenAI、Anthropic、Google Gemini,以及国内的一些大模型服务,你需要分别处理各家不同的接口地址、认证方式、请求格式、限流策略。一旦模型数量变多,代码会变得非常臃肿,维护成本也很高。

AI 聚合网关做的事情就是把这些差异都屏蔽掉,对外提供一个统一、稳定的 API 入口。客户端只需要按照一套标准格式发起请求,网关负责将请求转发到正确的模型服务商,并把响应结果返回给客户端。

用通俗的话来说,网关就像是一个前台中转站。你不用再记住每个公司的门牌号和接待方式,只需要跟前台说一句“我要找谁”,后面的事情由前台来处理。

1.2 AI 聚合网关的核心功能

一个完整的 AI 聚合网关通常包含以下能力:

功能模块说明
统一 API 入口对外提供标准接口,客户端无需关心每个上游服务的差异
模型路由根据请求中的模型名称,自动转发到对应的服务商
密钥管理多个上游服务的 API Key 统一存放在网关侧,不暴露给客户端
参数转换将统一格式的请求转换为各服务商要求的格式
错误处理与重试上游故障时返回友好提示,可选自动重试
限流与权限校验控制调用频率,防止接口被滥用
日志与统计记录请求量、延迟、失败率,便于观察和排错

这些能力如果自己从零去写,工作量不小。但如果利用 Cloudflare Workers 这样的边缘计算服务,配合第三方开源模型,网关的骨架可以在很短时间内搭出来。

1.3 为什么选择 Cloudflare 作为部署平台

Cloudflare 不是一家传统的云服务器厂商,它的核心优势在于全球边缘网络。你写的一段代码可以部署到离用户最近的节点上,用户访问时延迟更低。

对于个人开发者来说,Cloudflare 最有吸引力的其实是免费额度:

  • Workers 免费计划每天有 10 万次请求额度,个人项目完全够用。
  • 免费提供 HTTPS 证书,可以绑定自定义域名。
  • 提供 Workers KV 存储,可以存放配置数据。
  • 配合 GitHub 可以进行自动化部署。

换句话说,你不需要购买任何云服务器,也不需要为流量付费,只要代码量不大、请求量在免费额度内,这个网关可以长期“零成本”运行。

2. 整体架构与方案设计

2.1 免费云上部署的整体架构

在动手之前,先把整体架构想清楚,后面写代码时思路会顺畅很多。

本文实现的 AI 聚合网关采用如下架构:

  1. 客户端发送标准 OpenAI 兼容格式的请求到 Cloudflare Workers 网关地址。
  2. Workers 中的网关程序解析请求,提取模型名称和消息内容。
  3. 网关根据模型名称,匹配上游服务配置,替换 API Key,转换请求格式。
  4. 通过fetch转发到真实的 AI 服务商接口。
  5. 获取上游响应,转换回统一格式,返回给客户端。

整个链路中,只有网关这一个入口是暴露在外的,所有上游服务的密钥都保存在 Cloudflare Workers 的环境变量或 KV 存储中。

2.2 Cloudflare 免费额度说明

Cloudflare 的免费计划对个人项目非常友好。以 Workers 为例:

  • 每天 10 万次请求。
  • 每天 30 分钟 CPU 时间。
  • 支持 Workers KV,每天上限 10 万次读操作。
  • 免费绑定自定义域名,并启用 CDN 加速。
  • 自带基础防护能力。

需要注意的是,免费额度是每日计算的,如果某一天请求量突然暴增,可能会触发用量限制,这时请求会返回错误。对于个人学习项目和小流量应用来说,这个额度已经非常宽裕了。

2.3 项目目录结构

在写代码之前,我先列出项目的完整目录结构,让你有一个整体感知:

ai-gateway/ ├── .github/ │ └── workflows/ │ └── deploy.yml # GitHub Actions 自动部署配置 ├── src/ │ ├── gateway.js # Worker 主入口,路由分发 │ ├── config.js # 上游服务配置 │ ├── providers/ │ │ ├── openai.js # OpenAI 适配器 │ │ ├── anthropic.js # Anthropic 适配器 │ │ └── gemini.js # 自定义模型适配器 │ └── utils/ │ ├── response.js # 统一响应处理 │ └── crypto.js # 签名校验工具 ├── dashboard/ │ ├── index.html # 简单管理面板 │ └── app.js # 面板前端逻辑 ├── .dev.vars # 本地开发环境变量 └── wrangler.toml # Cloudflare Workers 配置

这个目录结构并不是死的,你可以根据自己的实际需要增删。核心是src目录下的网关逻辑,其他都可以灵活调整。

3. 环境准备与账号配置

3.1 本地开发环境

开始之前,先确保本地环境满足以下要求。版本需要根据你的实际项目情况调整,本文示例以常见环境为例,重点演示配置思路。

  • Node.js 18 或以上版本。
  • npm 或 pnpm 包管理器。
  • Git 命令行工具。
  • 一个 GitHub 账号,用来存储代码和触发自动部署。
  • 一个 Cloudflare 账号,用来部署 Workers。

如果你还没有安装 Node.js,可以去官网下载 LTS 版本,安装完成后在终端验证一下:

node -v npm -v

3.2 Cloudflare 账号准备

登录 Cloudflare 控制台后,不需要做太复杂的配置。你需要拿到两个关键信息:

  • Account ID:在控制台首页右侧可以找到。
  • API Token:在右上角头像 -> My Profile -> API Tokens 中创建。

创建 API Token 时,选择Edit Cloudflare Workers模板,权限范围只需要包含 Workers 即可。生成的 Token 只会显示一次,一定要保存好。

3.3 安装 Wrangler CLI

Wrangler 是 Cloudflare 官方提供的命令行工具,用来开发、调试、部署 Workers。安装方式很简单:

npm install -g wrangler

安装完成后,验证一下版本:

wrangler --version

然后登录 Cloudflare 账号:

wrangler login

执行后浏览器会打开授权页面,点击允许即可。登录成功后在终端会看到对应的提示。

如果不想全局安装,也可以作为项目依赖安装,这样团队协作时版本更统一:

npm install -D wrangler

4. 核心代码:AI 聚合网关 Worker 实线

4.1 创建 Worker 项目

使用 Wrangler 初始化一个项目:

mkdir ai-gateway cd ai-gateway wrangler init

在初始化过程中,Wrangler 会询问是否创建基础代码和配置文件,按需选择即可。最终项目里会生成一个wrangler.toml文件和src/目录。

接下来,我们需要安装路由处理相关的依赖。为了保证网关代码足够轻量,我只引入一个用于 URL 匹配的库:

npm install itty-router

itty-router是一个轻量级路由库,非常适合 Cloudflare Workers 环境,体积小、语法简单。

4.2 配置 wrangler.toml

wrangler.toml是 Cloudflare Workers 的核心配置文件。我的参考配置如下:

name = "ai-gateway" main = "src/gateway.js" compatibility_date = "2024-09-01" workers_dev = true [vars] GATEWAY_TOKEN = "your-gateway-token" # 以 OpenAI 为例,其他服务商的密钥也可以放在这里 OPENAI_API_KEY = "sk-your-openai-key" # 如果用到 KV 存储,开下面这行 # [[kv_namespaces]] # binding = "GATEWAY_KV" # id = "your-kv-namespace-id"

配置说明:

  • name:Worker 服务名称,会作为默认子域名的一部分。
  • main:入口文件路径。
  • compatibility_date:Cloudflare 运行时兼容性日期。
  • vars:环境变量,可以在代码中直接读取。

有一点要特别提醒:你的 API Key 如果写在这个配置文件里,那么上传到 GitHub 时一定要确保仓库是私有的。更安全的做法是使用.dev.vars存放本地密钥,生产环境的密钥通过 Cloudflare 控制台或 GitHub Actions Secrets 注入。

4.3 编写网关主入口

网关主入口是整篇文章的核心,它负责接收所有请求,并转发到对应的上游 AI 服务。

先来看一个简化版的主入口代码:

// 文件路径:src/gateway.js import { Router } from 'itty-router'; import { handleChatCompletion } from './routes/chat'; import { handleModels } from './routes/models'; import { authMiddleware } from './middleware/auth'; const router = Router(); // 所有请求都要经过鉴权中间件 router.all('*', authMiddleware); // 获取模型列表 router.get('/v1/models', handleModels); // 对话补全接口 router.post('/v1/chat/completions', handleChatCompletion); // 健康检查 router.get('/health', () => new Response('OK', { status: 200 })); export default { async fetch(request, env, ctx) { try { return await router.handle(request, env, ctx); } catch (err) { return new Response( JSON.stringify({ error: { message: err.message || 'Internal Server Error', type: 'internal_error' } }), { status: 500, headers: { 'Content-Type': 'application/json' } } ); } } };

这段代码的职责非常清晰:

  • 使用itty-router注册路由规则。
  • 对所有请求先执行鉴权中间件。
  • 对不同的路径分发到对应的处理函数。
  • 全局捕获异常,统一返回 JSON 格式错误。

4.4 实现鉴权中间件

既然是网关,就不能让所有拿到地址的人随便调用。我给网关加了一个简单的 Token 鉴权机制。

// 文件路径:src/middleware/auth.js export async function authMiddleware(request, env) { // 健康检查不需要鉴权 if (new URL(request.url).pathname === '/health') { return; } const authHeader = request.headers.get('Authorization') || ''; const token = authHeader.replace('Bearer ', ''); if (!token || token !== env.GATEWAY_TOKEN) { return new Response( JSON.stringify({ error: { message: 'Unauthorized', type: 'auth_error' } }), { status: 401, headers: { 'Content-Type': 'application/json' } } ); } }

这个中间件的逻辑很简单:请求头里必须携带Authorization: Bearer <token>,并且 token 要和环境变量GATEWAY_TOKEN一致,否则直接返回 401。

在实际项目中,这里可以升级为 JWT 校验、API Key 轮换、按用户维度限流等能力,本文先保持最简实现。

4.5 实现对话补全路由

对话补全接口是网关的核心。下面是一个能实际工作的简化版本,逻辑是:根据请求里的模型名称,把请求转发给 OpenAI 的 Chat Completions 接口。

// 文件路径:src/routes/chat.js const OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions'; export async function handleChatCompletion(request, env) { const body = await request.json(); const model = body.model; if (!model) { return new Response( JSON.stringify({ error: { message: 'Missing model parameter', type: 'invalid_request_error' } }), { status: 400, headers: { 'Content-Type': 'application/json' } } ); } // 这里可以做模型路由,根据 model 名称转发到不同服务商 // 为了演示,这里统一走 OpenAI const upstreamResponse = await fetch(OPENAI_CHAT_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${env.OPENAI_API_KEY}` }, body: JSON.stringify(body) }); const data = await upstreamResponse.json(); return new Response(JSON.stringify(data), { status: upstreamResponse.status, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } }); }

在上面的例子里,网关做的事情其实就是“透传”。客户端发什么,网关就原样转发给 OpenAI。注意,这只是一个演示版本,实际项目中还需要处理以下问题:

  • 不同服务商的接口格式不同,需要做参数转换。
  • 请求失败时需要返回更明确的错误信息。
  • 响应需要统一格式,方便客户端处理。

4.6 实现 OpenAI 兼容接口

为了让上游服务格式不统一的问题得到解决,我在网关内部设计了一个“适配器”概念。

每个上游服务商实现一个chat方法,负责将统一请求体转换为该服务商要求的格式。

以 OpenAI 适配器为例:

// 文件路径:src/providers/openai.js export async function chat(messages, options, env) { const url = options.baseUrl || 'https://api.openai.com/v1/chat/completions'; const apiKey = env.OPENAI_API_KEY; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify({ model: options.model || 'gpt-4o-mini', messages, temperature: options.temperature ?? 0.7, max_tokens: options.maxTokens || 1000 }) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`OpenAI upstream error: ${response.status} ${errorText}`); } return await response.json(); }

再看一个自定义模型的适配器示例,假设上游接口是兼容 OpenAI 格式的,但接口地址和密钥不同:

// 文件路径:src/providers/custom.js export async function chat(messages, options, env) { const url = env.CUSTOM_BASE_URL || 'https://custom-ai.example.com/v1/chat/completions'; const apiKey = env.CUSTOM_API_KEY; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify({ model: options.model, messages, temperature: options.temperature ?? 0.7 }) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Custom upstream error: ${response.status} ${errorText}`); } return await response.json(); }

有了适配器之后,路由层就变得更灵活了。在chat.js里做一个简单的模型映射即可:

// 文件路径:src/routes/chat.js(升级版) import { chat as openaiChat } from '../providers/openai'; import { chat as customChat } from '../providers/custom'; const modelProviderMap = { 'gpt-4o-mini': 'openai', 'gpt-4o': 'openai', 'custom-model-1': 'custom' }; export async function handleChatCompletion(request, env) { const body = await request.json(); const { messages, model } = body; if (!model || !messages) { return new Response( JSON.stringify({ error: { message: 'model and messages are required', type: 'invalid_request_error' } }), { status: 400, headers: { 'Content-Type': 'application/json' } } ); } const providerName = modelProviderMap[model]; if (!providerName) { return new Response( JSON.stringify({ error: { message: `Unsupported model: ${model}`, type: 'invalid_request_error' } }), { status: 400, headers: { 'Content-Type': 'application/json' } } ); } let result; if (providerName === 'openai') { result = await openaiChat(messages, { model }, env); } else if (providerName === 'custom') { result = await customChat(messages, { model }, env); } return new Response(JSON.stringify(result), { status: 200, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } }); }

这段代码采用了一张简单的映射表,将不同模型名称指向不同的处理器。当新增模型服务商时,只需要新增适配器并更新映射表,主流程代码不需要改动。

实际生产项目中,模型映射表可以放到 Workers KV 中,这样你可以在不发布新代码的情况下,动态修改模型路由规则。

4.7 添加 CORS 支持

如果你的网关会从浏览器端调用,必须处理跨域问题。可以在入口处统一添加响应头:

// 文件路径:src/utils/cors.js export const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization' }; export function handleOptions(request) { if (request.method === 'OPTIONS') { return new Response(null, { status: 204, headers: corsHeaders }); } }

在入口文件中,针对 OPTIONS 请求直接返回:

import { handleOptions, corsHeaders } from './utils/cors'; const router = Router(); router.all('*', (request) => { if (request.method === 'OPTIONS') { return handleOptions(request); } });

4.8 统一响应格式

为了让客户端处理响应时更简单,我将成功和失败两种情况统一格式。

成功响应示例:

{ "success": true, "data": { "id": "chatcmpl-123", "object": "chat.completion", "model": "gpt-4o-mini", "choices": [...] } }

失败响应示例:

{ "success": false, "error": { "message": "上游服务超时", "type": "upstream_timeout" } }

这样设计的好处是,客户端只需要检查success字段就可以判断请求是否成功,不需要去解析 HTTP 状态码。

5. 一键部署到 Cloudflare Workers

5.1 本地调试

在部署到线上之前,先在本地启动开发服务器调试:

wrangler dev

启动后,Wrangler 会在本地开启一个端口,比如http://localhost:8787。你可以用 curl 测试接口:

curl -X POST http://localhost:8787/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-gateway-token" \ -d '{ "model": "gpt-4o-mini", "messages": [ { "role": "user", "content": "你好,介绍一下你自己" } ] }'

如果一切正常,你会收到来自模型服务商的响应内容。

5.2 手动部署

本地调试通过后,直接执行部署命令:

wrangler deploy

执行完成后,终端会输出一个 Workers 域名,形如:

https://ai-gateway.your-subdomain.workers.dev

这个地址就是网关的公网入口。用浏览器打开/health路径,能看到一个简单的 OK 响应。

5.3 配置 GitHub Actions 自动部署

手动部署每次都要在本地执行命令,不够自动化。更推荐的做法是配置 GitHub Actions,在每次 push 到 main 分支时自动部署。

首先,在 GitHub 仓库的Settings -> Secrets and variables -> Actions中配置以下 Secrets:

  • CLOUDFLARE_API_TOKEN:你之前创建的 API Token。
  • CLOUDFLARE_ACCOUNT_ID:Cloudflare 控制台中的 Account ID。

然后创建文件.github/workflows/deploy.yml

name: Deploy Worker on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Install dependencies run: npm ci - name: Deploy to Cloudflare Workers run: npx wrangler deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

这个工作流的逻辑很清晰:

  • 监听 main 分支的 push 事件。
  • 签出代码。
  • 安装 Node.js 环境。
  • 安装依赖。
  • 执行wrangler deploy部署。

以后你只需要把代码 push 到 GitHub 仓库的 main 分支,GitHub Actions 会自动完成部署,真正实现“一键云上部署”。

5.4 配置自定义域名

如果你有自己的域名,并且域名托管在 Cloudflare,可以在控制台为 Worker 绑定自定义域名。

在 Cloudflare 控制台中进入你的 Worker 服务,点击Settings -> Domains & Routes -> Add,输入你想绑定的域名,比如ai-api.example.com,保存后等待 DNS 生效即可。

绑定成功后,你访问的地址就变成了你自己的域名,不再需要通过workers.dev子域名对外提供服务。

6. 前端管理面板

6.1 为什么需要管理面板

网关上线后,总不能每次看日志都去 Cloudflare 控制台。这里我顺手做了一个极简管理面板,部署在 Cloudflare Pages 上,用来展示网关的基本状态和调用统计。

6.2 面板页面示例

管理面板只包含一个简单的 HTML 页面:

<!-- 文件路径:dashboard/index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>AI Gateway Dashboard</title> <style> body { font-family: system-ui, sans-serif; max-width: 800px; margin: 0 auto; padding: 24px; } .card { border: 1px solid #e5e7eb; border-radius: 8px; padding: 16px; margin-bottom: 16px; } .status { font-weight: bold; } .online { color: #16a34a; } .offline { color: #dc2626; } </style> </head> <body> <h1>AI Gateway Dashboard</h1> <div class="card"> <h2>网关状态</h2> <p class="status" id="healthStatus">检测中...</p> </div> <div class="card"> <h2>模型配置</h2> <ul id="modelList"> <li>gpt-4o-mini -> OpenAI</li> <li>gpt-4o -> OpenAI</li> <li>custom-model-1 -> Custom</li> </ul> </div> <script src="./app.js"></script> </body> </html>

6.3 面板前端逻辑

// 文件路径:dashboard/app.js async function checkHealth() { try { const response = await fetch('/health'); const statusEl = document.getElementById('healthStatus'); if (response.ok) { statusEl.textContent = '在线'; statusEl.classList.add('online'); } else { statusEl.textContent = '异常'; statusEl.classList.add('offline'); } } catch (err) { const statusEl = document.getElementById('healthStatus'); statusEl.textContent = '离线'; statusEl.classList.add('offline'); } } checkHealth();

这个页面非常简单,实际项目中可以扩展为请求量图表、错误率统计、模型调用占比等更丰富的展示。把dashboard目录部署到 Cloudflare Pages 即可。

7. 常见问题与排查思路

7.1 常见问题速查表

问题现象常见原因解决思路
部署时提示Missing API TokenCLI 未登录或未配置 Token执行wrangler login,或在 CI 中配置 Secrets
调用返回 401 Unauthorized网关 Token 不匹配检查请求头 Authorization 是否携带正确的 Bearer Token
返回Model not found模型名称未在映射表中配置检查modelProviderMap,确认模型名与上游一致
上游请求超时第三方接口响应慢或网络不稳增加超时处理,适当重试,查看上游状态页
部署后代码未生效自动部署失败或环境变量未更新查看 GitHub Actions 日志,确认 Secrets 是否配置
浏览器跨域报错缺少 CORS 头在响应中增加Access-Control-Allow-Origin
免费额度被耗尽请求量超过每日限制进入控制台查看用量,考虑升级计划或加限流

7.2 详细排查步骤

案例一:部署后访问返回 500

出现 500 错误,首先查看 Worker 的日志。在 Cloudflare 控制台进入 Worker,点击Logs菜单,可以看到实时的请求日志和异常堆栈。

常见原因是环境变量没有读取到。检查wrangler.toml中的vars是否已经包含所有需要的变量;如果是通过 CI 部署,需要确认 GitHub Secrets 是否配置正确。

案例二:请求 OpenAI 时报 401

这种情况通常是OPENAI_API_KEY配置错误。可以在本地环境变量文件.dev.vars中确认一下:

OPENAI_API_KEY=sk-xxxxxxxx GATEWAY_TOKEN=my-gateway-token

另外注意,某些服务商的密钥需要通过不同的请求头传递。有的要求Authorization: Bearer,有的要求自定义请求头,这些细节需要查阅上游文档。

案例三:模型请求速度很慢

如果网关本身逻辑很简单,但请求延迟很高,大概率是上游服务本身的响应时间慢。可以在前端上报请求开始和结束时间,对比一下直连上游和通过网关访问的耗时差距。

也有可能是 Cloudflare Workers 节点距离上游服务商的接口较远,导致的网络延迟。这种情况可以尝试在fetch请求中指定cf参数,或者调整 Worker 的访问地区设置。

8. 最佳实践与安全建议

8.1 密钥管理:永远不要把密钥写死在代码里

这是最容易犯的错误,也是后果最严重的问题。

开发阶段可以把密钥放到.dev.vars中,这个文件不要提交到 Git;生产环境的密钥通过 Cloudflare 控制台设置,或者在 GitHub Actions 中通过 Secrets 注入。

一旦发现密钥泄露,立即到上游服务商的控制台吊销并重新生成,同时更新网关配置。

8.2 添加访问控制与限流

对外的网关上,至少要有两层保护:

  • 第一层是网关自身的 Token 鉴权,拒绝未授权的请求。
  • 第二层是按调用方维度限流,防止某个调用方消耗全部额度。

Cloudflare 提供了 Rate Limiting 规则,可以在控制台中针对/v1/chat/completions路径配置速率限制。免费计划有一定的配额,个人项目完全够用。

生产环境如果并发量大,建议将网关 Token 升级为短期 JWT,并配合签名校验机制。

8.3 日志与监控

Cloudflare Workers 自带日志功能,但只能保留最近一段时间的数据,无法做长期趋势分析。

建议在网关代码中主动记录结构化日志,例如:

{ "time": "2025-01-01T12:00:00Z", "path": "/v1/chat/completions", "model": "gpt-4o-mini", "status": 200, "latency_ms": 340 }

如果你的项目运行量不大,也可以直接把关键指标发送到免费的可观测性平台,或者用 Workers KV 做简单的计数统计。

8.4 合理使用上游模型

聚合网关最大的优势是灵活性,但这不代表可以滥用。

一些上游服务商对单账号的请求速率有限制,网关层如果只是单纯转发,多个客户端同时调用时仍然可能触发上游限流。这时可以在网关层做两件事:

  • 对同一上游做排队或节流。
  • 在多个上游 Key 之间做负载均衡。

本文的示例没有覆盖这两点,但如果你的网关流量逐步增长,这些是下一步值得研究和实现的方向。

8.5 代码可维护性

网关的代码量虽然不大,但涉及到多个上游服务商时,很容易变成一堆 if-else。建议从第一天开始就使用适配器模式,每个上游服务商一个文件,保持主流程干净。

另外,给每个适配器补充清晰的注释,标明接口地址、认证方式、返回差异,方便后续维护。

9. 总结与下一步方向

这篇文章实现了以下几件事:

  • 用一个 Worker 代码,搭建了兼容 OpenAI 格式的 AI 聚合网关。
  • 实现了模型路由、鉴权、统一错误处理、CORS 支持。
  • 支持手动部署和 GitHub Actions 自动部署。
  • 通过 Cloudflare 免费额度,实现了零成本云上部署。
  • 给出了常见问题的排查思路和工程级安全建议。

如果你的目标只是个人学习和使用,目前这个网关已经可以满足大部分需求。下一步可以考虑的方向包括:

  • 将模型映射配置搬进 Workers KV,实现动态路由。
  • 增加请求日志落库,分析调用趋势。
  • 增加缓存层,对重复请求直接返回缓存结果,节省上游调用费用。
  • 集成更多模型服务商,比如 Anthropic、Gemini 等。
  • 增加多 Key 自动轮询机制,提升上游可用性。

动手搭一个属于你自己的 AI 聚合网关,是理解 API 网关设计、边缘计算部署和服务治理的很好项目实践。如果这篇文章对你有帮助,可以先收藏备用,后续遇到部署或使用问题随时回来查阅。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 1:21:25

Windows下cuDNN 8.5.0.96与CUDA 11安装配置与排障详解

简介&#xff1a;这份资源是面向Windows平台的CUDA深度学习加速库CuDNN 8.5.0.96压缩包&#xff0c;专为CUDA 11.x环境设计&#xff0c;适用于使用TensorFlow、PyTorch等框架进行神经网络训练与推理的开发者。包内共31个文件&#xff0c;包含14个.lib库文件、9个.h头文件、7个.…

作者头像 李华
网站建设 2026/9/2 1:20:38

Python+Django旅游景点可视化系统:从数据清洗到DeepSeek问答全解析

先想一个常被问的问题&#xff1a;拿到“Python旅游景点信息可视化系统”这类题目&#xff0c;很多人的第一反应是上网找一套源码&#xff0c;改改名字、换换图片&#xff0c;然后交差。这个做法短期应付可以&#xff0c;但一旦被问到“表结构怎么设计的”“图表数据从哪来”“…

作者头像 李华
网站建设 2026/9/2 1:19:39

Obsidian+AI打造个人知识库:从双链笔记到RAG语义检索问答

不知道你有没有遇到过这样的场景&#xff1a;笔记软件里存了上百篇文档&#xff0c;标签打了无数个&#xff0c;文件夹也建了一层又一层&#xff0c;可真到用的时候&#xff0c;却连“之前整理过的那份资料”都找不出来。关键词搜索总是返回一堆标题匹配&#xff0c;真正要用的…

作者头像 李华
网站建设 2026/9/2 1:19:32

Spring Boot 3.x与Vue 3.x全栈实战:从零构建美食分享网站

最近在辅导学生做毕业设计时&#xff0c;发现很多同学对如何从零开始构建一个完整的JavaWeb项目感到迷茫&#xff0c;尤其是在整合前后端分离架构时&#xff0c;常常在环境配置、接口联调、数据库设计等环节卡住。本文将以一个“美食分享网站”为例&#xff0c;手把手带你完成一…

作者头像 李华
网站建设 2026/9/2 1:16:11

LangChain Agent实战:用Harness工程构建TextToSQL

当业务需要把自然语言问题直接转化为数据库查询结果时&#xff0c;TextToSQL 是性价比很高的一条技术路线。但真正落地时你会发现&#xff0c;单纯让大模型生成 SQL 远远不够&#xff1a;模型要理解表结构、要调用工具去执行查询、还要根据执行报错自我修正&#xff0c;整个过程…

作者头像 李华
网站建设 2026/9/2 0:11:00

32位MCU电动自行车应用参考方案

随着新国标落地&#xff0c;电动自行车向着轻量化、高安全、智能化方向迭代升级&#xff0c;市场对车辆控制系统的稳定性、精度及安全性要求持续提升。依托成熟的电机控制技术&#xff0c;中微半导推出基于32位MCU的电动自行车专用控制器解决方案&#xff0c;适配主流两轮电动车…

作者头像 李华