Sub2API 源码技术分析与搭建教程:把 AI 订阅变成可管理的 API 网关
面向读者刚接触后端、网关、AI API 中转的新手。 阅读目标看完你应该知道 Sub2API 是什么、怎么跑起来、源码怎么分层、一次请求在系统里经历了什么以及它为什么能做账号调度、鉴权、计费和限流。1. 一句话理解这个项目Sub2API 不是一个普通的“转发接口”。它更像一个面向 AI 服务的 SaaS 网关管理员把上游 AI 账号或 API Key 接入系统用户拿到平台生成的 API Key 后调用统一入口系统在中间完成鉴权、选择账号、转发请求、记录用量、扣费、限流、监控和后台管理。如果用生活化比喻上游账号像“批发来的 AI 调用额度”。平台 API Key 像“发给用户的门票”。网关像“检票员 调度员 记账员”。管理后台像“老板看的控制台”。官方 README 对它的定位是AI API Gateway Platform for Subscription Quota Distribution也就是“用于订阅配额分发管理的 AI API 网关平台”。2. 技术栈速览从仓库可以看出这是一个前后端分离但可打包成单体镜像的项目。层级技术作用后端Go、Gin、Ent、WireHTTP 服务、业务逻辑、数据库 ORM、依赖注入前端Vue 3、Vite、Pinia、Vue Router、TailwindCSS管理后台、用户中心、设置向导数据库PostgreSQL保存用户、账号、API Key、订阅、计费、日志等核心数据缓存/队列Redis限流、缓存、会话、异步用量记录等部署Docker Compose、systemd 安装脚本、多阶段 Dockerfile快速部署、打包前端和后端关键文件README.md/README_CN.md项目介绍与部署说明。backend/cmd/server/main.go后端启动入口。backend/internal/server/router.go统一注册中间件和路由。backend/internal/server/routes/gateway.goAI 网关相关路由。backend/internal/handler/openai_gateway_handler.goOpenAI 网关 HTTP Handler。backend/internal/service/openai_gateway_service.goOpenAI 请求转发、兼容、重试、流式处理等核心逻辑。backend/internal/service/openai_account_scheduler.goOpenAI 上游账号调度器。backend/internal/service/api_key_service.go平台 API Key 管理与校验逻辑。backend/internal/service/billing_service.go计费缓存、模型价格、余额/订阅用量逻辑。frontend/package.json前端脚本和依赖。deploy/docker-compose.yml、deploy/.env.exampleDocker 部署配置。Dockerfile前端构建、后端构建、最终镜像三阶段打包。3. 新手最快搭建方式Docker Compose如果你只是想先跑起来推荐 Docker Compose。它会同时拉起 Sub2API、PostgreSQL 和 Redis。3.1 环境要求Linux 服务器或本地 Docker 环境Docker 20.10Docker Compose v2推荐开放端口80803.2 一键准备部署目录官方 README 提供的快速方式mkdir -p sub2api-deploy cd sub2api-deploy curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash docker compose up -d docker compose logs -f sub2api这个脚本会做几件对新手很友好的事下载 Docker Compose 配置和.env.example。自动生成JWT_SECRET、TOTP_ENCRYPTION_KEY、POSTGRES_PASSWORD等密钥。创建数据目录方便以后备份和迁移。启动后访问http://服务器IP:8080。3.3 手动部署方式如果你想理解每一步可以手动来git clone https://github.com/Wei-Shaw/sub2api.git cd sub2api/deploy cp .env.example .env nano .env.env里最关键的是POSTGRES_PASSWORDyour_secure_password_here JWT_SECRETyour_jwt_secret_here TOTP_ENCRYPTION_KEYyour_totp_key_here ADMIN_EMAILadminexample.com ADMIN_PASSWORDyour_admin_password SERVER_PORT8080生成密钥可以用openssl rand -hex 32然后启动docker compose up -d docker compose logs -f sub2api如果使用本地目录版配置docker compose -f docker-compose.local.yml up -d docker compose -f docker-compose.local.yml logs -f sub2api3.4 首次启动发生了什么backend/cmd/server/main.go里可以看到启动逻辑解析-setup和-version参数。检查是否需要初始化配置。如果设置了AUTO_SETUPtrue就从环境变量自动初始化。如果没有自动初始化就启动 Web Setup Wizard。初始化完成后进入正常服务模式。Docker Compose 中的deploy/docker-compose.yml明确设置了AUTO_SETUPtrue SERVER_HOST0.0.0.0 SERVER_PORT8080 DATABASE_HOSTpostgres REDIS_HOSTredis所以容器部署时不需要你手动创建配置文件系统会根据环境变量完成第一次初始化。4. 本地开发搭建如果你想读源码、改代码、参与开发可以按开发模式来。4.1 后端后端位于backend/使用 Go modules。cd backend go mod download go build -o bin/server ./cmd/server项目自己的后端 Makefile 提供了make build make test make test-unit make test-integration根目录 Makefile 也封装了make build-backend make test-backend注意backend/go.mod当前声明的是go 1.26.3README 徽章和开发文档中也出现过 Go 1.25.x 的描述。实际开发时建议以当前源码go.mod和 CI 配置为准。4.2 前端前端位于frontend/包管理器是 pnpm不建议混用 npm。cd frontend pnpm install pnpm run dev常用脚本来自frontend/package.jsonpnpm run dev # Vite 开发服务器 pnpm run build # vue-tsc 类型检查 Vite 构建 pnpm run typecheck # 类型检查 pnpm run lint:check # ESLint 检查 pnpm run test:run # Vitest 测试开发文档DEV_GUIDE.md特别提醒前端必须使用 pnpmpnpm-lock.yaml要同步提交否则 CI 的 frozen lockfile 会失败。5. 源码分层这个项目怎么组织从目录上看Sub2API 后端采用比较典型的 Go 分层架构。backend/ cmd/server/ # 程序入口 ent/ # Ent ORM 生成代码和 schema internal/config/ # 配置加载、默认值、校验 internal/server/ # HTTP server、router、routes、中间件组装 internal/handler/ # HTTP Handler负责解析请求和返回响应 internal/service/ # 业务逻辑账号、调度、计费、网关转发 internal/repository/ # 数据访问、缓存、迁移、上游 HTTP 辅助 migrations/ # 数据库迁移 resources/ # 模型价格等资源前端则是 Vue 项目常见结构frontend/src/ api/ # 调后端接口的封装 stores/ # Pinia 状态管理 router/ # Vue Router 路由与导航守卫 views/ # 页面级组件 components/ # 可复用组件frontend/src/router/index.ts里可以看到路由按页面懒加载包含/setup、/login、/register、用户页面和管理后台页面并通过 meta 字段控制是否需要登录。6. 请求从用户到上游一次 AI 调用的完整链路最值得分析的是网关链路。以用户调用 OpenAI/Claude/Gemini 兼容接口为例可以拆成 7 步。第 1 步请求进入 Gin 路由backend/internal/server/router.go中的SetupRouter会挂载通用中间件请求日志CORSSecurity Headers / CSP嵌入式前端资源服务API v1 路由网关路由核心注册点routes.RegisterGatewayRoutes(r, h, apiKeyAuth, apiKeyService, subscriptionService, opsService, settingService, cfg)第 2 步网关路由判断协议backend/internal/server/routes/gateway.go定义了 AI 网关入口/v1/messagesClaude Messages 兼容入口也会根据分组平台转到 OpenAI 逻辑。/v1/responsesResponses API。/v1/chat/completionsOpenAI Chat Completions。/v1/images/generations、/v1/images/editsOpenAI 图片接口。/v1beta/models/...Gemini 原生 API 兼容层。/backend-api/codex/responsesCodex 相关直连路径。这说明 Sub2API 的目标不是只支持一种 API而是把多个 AI 生态的入口统一到一个平台里。第 3 步API Key 鉴权网关路由会使用 API Key 中间件。平台发给用户的 API Key 不是上游官方 Key而是 Sub2API 自己生成和管理的 Key。backend/internal/service/api_key_service.go负责 API Key 的创建、查询、删除、额度检查、过期检查、失败限速等。源码里能看到这些错误类型API_KEY_NOT_FOUNDAPI_KEY_EXPIREDAPI_KEY_QUOTA_EXHAUSTEDAPI_KEY_RATE_5H_EXCEEDEDAPI_KEY_RATE_1D_EXCEEDEDAPI_KEY_RATE_7D_EXCEEDED这就是“平台 Key”和“上游 Key”解耦的关键用户只接触平台 Key系统内部再决定用哪个上游账号。第 4 步检查分组、订阅和余额网关中还有 RequireGroupAssignment、订阅校验、计费缓存等逻辑。billing_service.go中定义了余额、订阅、API Key 时间窗口用量缓存接口。它关心三类数据用户余额。用户某个分组下的订阅。某个 API Key 在 5 小时、1 天、7 天窗口内的用量。因此系统可以支持更细的商业规则某个用户能用哪些模型、多少额度、是否超限、是否需要扣余额。第 5 步选择上游账号这是 Sub2API 比普通反代更有技术含量的部分。backend/internal/service/openai_account_scheduler.go定义了 OpenAI 账号调度接口Select(ctx, req) (*AccountSelectionResult, OpenAIAccountScheduleDecision, error) ReportResult(accountID, success, firstTokenMs) ReportSwitch() SnapshotMetrics()调度器会综合考虑分组 ID会话 Hash粘性账号 IDprevious_response_id请求模型上游传输方式图片能力是否需要 compact 模式排除账号列表源码里的调度层名称很直观previous_response_id优先保持同一个上下文响应链。session_hash同一个会话尽量打到同一个账号。load_balance无法命中粘性时再负载均衡。它还维护运行时统计例如错误率 EWMA、首 Token 延迟 TTFT EWMA用来辅助选择更健康的账号。新手可以这样理解普通轮询是“排队轮流上”Sub2API 的调度更像“先看你是不是老客户再看哪个窗口空、哪个服务员状态好”。第 6 步构造并转发上游请求backend/internal/service/openai_gateway_service.go是 OpenAI 网关的核心大文件。它处理的事情很多OpenAI Responses / Chat Completions / Images 等接口兼容。OAuth 账号与 API Key 账号的不同上游地址。Codex CLI 相关请求头、会话和 WebSocket 行为。请求头白名单避免把不安全或无意义的客户端头透传给上游。流式响应、重试、错误恢复。上游响应头和用量信息解析。源码中可以看到一些关键常量chatgptCodexURL https://chatgpt.com/backend-api/codex/responses openaiPlatformAPIURL https://api.openai.com/v1/responses openaiStickySessionTTL time.Hour这说明它不是简单把 URL 换一下而是根据账号类型、客户端类型、模型能力和接口形态走不同路径。第 7 步记录用量、扣费、返回结果请求成功后系统需要把调用量转成成本写入用量记录再更新余额或订阅额度。billing_service.go里有模型价格结构ModelPricing包含输入 token、输出 token、缓存 token、长上下文倍率、图片输出 token 等字段。这解释了为什么它可以做到“Token 级别的用量追踪和成本计算”。对平台运营者来说这比只统计请求次数精细得多。7. 几个值得学习的技术点7.1 Setup Wizard 与 Auto Setupmain.go的启动逻辑把首次运行分成两种没有配置且没开自动初始化启动 Setup Wizard。Docker 环境设置AUTO_SETUPtrue直接从环境变量生成配置。这对开源项目很友好小白可以走网页向导生产部署可以走环境变量自动化。7.2 前端嵌入后端二进制Dockerfile 是三阶段构建Node 镜像构建前端。Go 镜像编译后端并带上前端 dist。Alpine 运行最终二进制。后端启动时web.HasEmbeddedFrontend()会判断是否有嵌入前端资源。如果有就由后端同时服务 API 和前端页面。这样部署时只需要一个应用容器不必单独部署 Nginx 前端静态站点。7.3 Redis Lua 原子限流backend/internal/middleware/rate_limiter.go使用 Redis Lua 脚本做限流local current redis.call(INCR, KEYS[1]) local ttl redis.call(PTTL, KEYS[1]) if current 1 then redis.call(PEXPIRE, KEYS[1], ARGV[1]) elseif ttl -1 then redis.call(PEXPIRE, KEYS[1], ARGV[1]) end return {current, repaired}好处是计数和设置过期时间在 Redis 内部原子完成避免高并发下出现计数错乱。7.4 粘性会话AI 对话不是一次性请求。很多客户端会带session_id、conversation_id或previous_response_id。如果同一个上下文被分配到不同上游账号可能出现上下文丢失或响应异常。所以调度器先尝试 previous response 和 session hash再进入负载均衡。这是 AI 网关区别于普通 HTTP 网关的重要点。7.5 网关不是“裸透传”OpenAI 网关里有 allowed headers 白名单。这样做可以减少两个风险客户端乱七八糟的头传到上游触发风控或兼容问题。敏感头、代理头、环境头被意外泄露。这也是成熟网关常见设计该透传的透传不该透传的坚决过滤。7.6 h2c 与 Nginx 注意事项项目支持 HTTP/2 Cleartext即 h2c。README 还特别提醒如果前面接 Nginx并且 Codex CLI 依赖带下划线的请求头需要在 Nginxhttp块里开启underscores_in_headers on;否则像session_id这样的头可能被 Nginx 丢掉进而破坏粘性会话。8. 管理后台能做什么从 Handler 聚合结构backend/internal/handler/handler.go可以看到后台能力很丰富用户管理分组管理上游账号管理公告管理数据管理与备份OAuth 管理代理管理兑换码/促销码系统设置运维监控订阅管理用量统计API Key 管理渠道监控内容审核支付与分销这说明 Sub2API 不只是一个给开发者自用的小工具而是带有 SaaS 运营后台的完整平台。9. 新手读源码路线如果你刚开始读不建议直接打开openai_gateway_service.go从头硬啃。推荐路线第一阶段先看启动和路由backend/cmd/server/main.gobackend/internal/server/http.gobackend/internal/server/router.gobackend/internal/server/routes/gateway.go目标知道服务如何启动请求如何进来。第二阶段看用户与 API Keybackend/internal/handler/api_key_handler.gobackend/internal/service/api_key_service.gobackend/internal/service/api_key_auth_cache.go目标理解平台 API Key 如何生成、校验和缓存。第三阶段看网关主链路backend/internal/handler/openai_gateway_handler.gobackend/internal/service/openai_gateway_service.gobackend/internal/service/openai_account_scheduler.go目标理解请求如何被选择账号、转发上游、处理响应。第四阶段看计费和用量backend/internal/service/billing_service.gobackend/internal/service/account_usage_service.gobackend/internal/handler/usage_handler.gobackend/internal/repository/ops_repo*.go目标理解 Token、成本、余额、订阅额度如何串起来。第五阶段看前端后台frontend/src/router/index.tsfrontend/src/api/frontend/src/stores/frontend/src/views/admin/目标理解后端能力如何被管理后台组织成页面。10. 常见问题Q1我没有上游账号可以跑起来吗可以。项目本身可以部署和进入后台但真正转发 AI 请求需要配置上游账号、API Key 或 OAuth 账号。Q2用户调用的是谁的 Key用户调用的是 Sub2API 生成的平台 Key。上游官方 Key 或 OAuth 凭据保存在平台侧由调度器选择使用哪个上游账号。Q3为什么需要 PostgreSQL 和 RedisPostgreSQL 保存长期数据比如用户、账号、配置、订阅、用量记录。Redis 处理高频、短期、并发相关数据比如限流计数、缓存、会话粘性和队列状态。Q4为什么不直接 Nginx 反代Nginx 只能做比较基础的转发和负载均衡。Sub2API 还要做 API Key 鉴权、账号调度、Token 计费、订阅额度、用户后台、支付、监控、粘性会话和模型兼容这些已经是应用层网关能力。Q5simple 和 standard 模式有什么区别配置示例中说明standard是完整 SaaS 模式包含计费和余额检查simple会隐藏 SaaS 功能并跳过计费/余额检查更适合内部使用。11. 总结这个项目最值得学什么Sub2API 的价值不在于“把请求转发到 OpenAI/Claude/Gemini”这么简单而在于它把一个 AI API 平台需要的核心能力组合起来用 Gin 承接多协议 API。用平台 API Key 解耦用户和上游账号。用调度器管理多账号、多模型、多会话。用 Redis 做高并发缓存、限流和粘性会话。用 PostgreSQL 保存长期业务数据。用计费系统把 Token 用量变成余额和订阅额度。用 Vue 管理后台把复杂运营能力可视化。用 Docker 和 Setup Wizard 降低部署门槛。对小白来说这个项目是学习“真实世界后端系统”的好样本它既有 Web 后台也有网关高并发既有业务系统也有工程化部署既要考虑用户体验也要考虑上游 API 的兼容和风控。如果你想练手可以从三个小目标开始先用 Docker Compose 跑起来。在后台创建一个用户和 API Key。顺着/v1/chat/completions或/v1/responses的路由把一次请求从 route、handler、service、scheduler 到 billing 画成流程图。当你能画出这张图你就已经从“会部署”进阶到了“读懂一个真实 AI 网关系统”。