Sub2API+Codex中转站实战:构建高可用大模型API网关
1. 项目概述这不是一个“装完就跑”的 Docker 演示而是一次对服务可用性边界的实战测绘“我如何用 Codex 部署了一个 Sub2API 中转站真正难的不是 Docker而是证明它真的能用”——这个标题里藏着三个关键信号第一“Codex”不是泛指任何代码助手而是特指那个以本地化、低延迟、强可控性为设计哲学的开源 LLM 接口代理层第二“Sub2API”在这里绝非简单的订阅链接转 API 的格式转换器它承担着协议解析、上游路由、流量整形、状态透传等核心网关职责第三最重的落点在“证明它真的能用”——这直接跳过了所有“Hello World”式部署教程的舒适区直指生产环境最本质的拷问服务是否稳定响应是否可预期故障是否可感知扩容是否可操作我做这个中转站的原始动机非常朴素手头有多个私有化部署的 Codex 实例分别跑在不同物理机、不同云区域、甚至一台老旧笔记本上它们各自独立运行但业务侧需要统一入口、统一鉴权、统一日志、统一熔断。Sub2API 就是那个“粘合剂”它把零散的 Codex 节点抽象成一个逻辑上的“Codex 集群”。而 Docker 不是目的只是让这个粘合剂具备环境一致性、快速启停、资源隔离能力的最合理载体。至于 Cloudflare 和 Nginx则是这个中转站面向公网的“门面”与“守门人”Cloudflare 提供全球 CDN 加速、DDoS 缓冲、TLS 终结和基础 WAFNginx 则在服务器本地完成更精细的路由分发、请求重写、健康检查和连接管理。所以这个项目的核心价值不在于教你“怎么敲 docker run”而在于帮你建立一套完整的“服务可用性验证体系”。它适合三类人一是正在评估 Sub2API 是否适配自己 Codex 架构的技术决策者二是已经部署但总在凌晨被告警吵醒、却找不到根因的运维同学三是想把本地大模型服务真正接入业务流水线、而非仅作 Demo 展示的工程实践者。你不需要是 Docker 专家但必须愿意花 15 分钟配置一个 curl 命令你不需要精通 Nginx 源码但得理解 location /v1/chat/completions 这个路径背后意味着什么。接下来的所有内容都围绕“如何让一个看似简单的中转链路在真实流量下持续呼吸”展开。2. 整体架构设计与选型逻辑为什么是 Sub2API Codex Cloudflare Nginx 这个组合2.1 四层结构拆解从用户请求到模型响应的完整路径整个中转链路并非线性串联而是一个具有明确职责边界、可独立演进的四层结构第 0 层用户端Client这是发起请求的源头可以是前端 Web 应用、后端微服务、或是直接调用 OpenAI 兼容 API 的 CLI 工具如 openai-cli。它的唯一认知是“我向 https://api.mycompany.com/v1/chat/completions 发起 POST 请求传入标准 OpenAI 格式的 JSON就能得到标准响应。” 它完全不知道背后是 Sub2API、Codex 还是 Azure OpenAI。这一层的“无知”恰恰是架构成功的标志。第 1 层边缘网关Cloudflare用户请求首先抵达 Cloudflare 的任一 PoP 节点。这里发生三件关键事第一TLS 1.3 握手终结将加密流量解密为明文 HTTP第二基于预设规则如 IP 白名单、User-Agent 过滤、速率限制进行初步清洗第三通过 DNS CNAME 或 Page Rule将请求无感地转发至你的服务器公网 IP。Cloudflare 的价值不在于“它多快”而在于“它替你挡了多少不该到达你服务器的流量”。实测中一次针对 /healthz 端点的恶意扫描风暴98% 的请求在 Cloudflare 边缘就被拦截你的 Nginx 日志里几乎看不到痕迹。第 2 层反向代理与负载均衡Nginx请求抵达你的服务器后由 Nginx 接手。它在此层完成四项不可替代的任务路径路由将 /v1/chat/completions、/v1/models 等不同路径精准映射到 Sub2API 容器的对应端口如 8080或内部服务名如 http://sub2api:8080健康检查通过定期向 Sub2API 的 /healthz 接口发送 HEAD 请求实时感知其存活状态。一旦失败Nginx 会自动将该 upstream 从轮询池中剔除避免请求打到“假死”进程连接管理设置proxy_http_version 1.1和proxy_set_header Connection 确保长连接复用极大降低 TCP 握手开销请求增强注入X-Real-IP、X-Forwarded-For等头信息让 Sub2API 能获取真实客户端 IP用于后续的限流或审计。提示很多人忽略 Nginx 的upstream块中max_fails3 fail_timeout30s这两个参数。它们定义了“健康检查失败多少次、持续多久才判定节点宕机”。3 次失败、30 秒内恢复是经过大量线上压测得出的平衡点——太敏感会导致误判太迟钝则影响用户体验。第 3 层协议转换与上游调度Sub2API Codex这是整个链路的“大脑”。Sub2API 容器接收来自 Nginx 的标准化 OpenAI 请求执行以下动作解析请求体提取 model 名称如codex-local-gpu、messages 内容、temperature 等参数根据内置的路由规则可配置为 YAML 文件或数据库将codex-local-gpu映射到http://192.168.1.10:3000/v1/chat/completions一台 GPU 服务器将codex-legacy-cpu映射到http://192.168.1.20:8000/v1/chat/completions一台 CPU 服务器对上游 Codex 实例发起请求并透传所有原始头信息如 Authorization Bearer token接收上游响应后将其标准化为 OpenAI 兼容的 JSON 格式包括id,object,created,choices等字段并添加X-Sub2API-Upstream头标识本次请求实际打到了哪个 Codex 节点。Codex 实例本身就是纯粹的、轻量级的 LLM 推理服务它只关心如何高效地执行chat/completions不处理任何路由、鉴权或协议转换逻辑。这种“各司其职”的解耦是系统长期可维护性的基石。2.2 为什么不是其他方案一次对主流替代品的冷静审视当决定采用 Sub2API 时我系统性地对比了五种常见替代方案最终排除它们的理由如下直接用 Nginx 反向代理 Codex表面看最简单但 Nginx 无法动态解析 OpenAI 请求体中的model字段。你只能做静态路径映射如/v1/codex-gpu/→http://gpu:3000/这意味着前端必须硬编码不同 model 的 URL彻底丧失 OpenAI 兼容性。一旦业务方要求“所有模型走同一个 endpoint”此方案即告破产。用 Kong 或 APISIX 等 API 网关功能强大支持插件化鉴权、限流、日志。但它们的复杂度是双刃剑一个简单的 model 路由规则可能需要编写 Lua 脚本、配置 Service/Route/Plugin 三张表、再调试半天。而 Sub2API 的 YAML 配置一行codex-gpu: http://gpu:3000就能搞定。对于中小团队工具的“心智负担”成本远高于其带来的功能收益。用自研 Node.js/Python 服务灵活性最高但“重复造轮子”的代价巨大。你需要自己实现OpenAI 请求/响应的完整序列化与反序列化、HTTP 连接池管理、上游健康检查、超时与重试策略、错误码映射如 Codex 的 503 要转为 OpenAI 的 429。Sub2API 已将这些通用能力封装为开箱即用的模块且经过数千个生产环境验证。我的原则是绝不为通用能力写一行新代码。用 Cloudflare Workers 直接调用 Codex看似“无服务器”很酷但 Workers 的 CPU 时间限制50ms和内存限制128MB对 LLM 推理是致命的。一次chat/completions请求光是网络传输和 JSON 解析就可能耗尽配额。它只适合做轻量级的请求预处理如 token 验证而非真正的协议桥接。用 Traefik 代替 NginxTraefik 的自动服务发现确实优雅但它的健康检查默认只检测容器端口是否可达无法深入到 Sub2API 的/healthz接口。这意味着 Sub2API 进程已卡死、但端口仍监听Traefik 依然会把流量导过去。而 Nginx 的health_check指令可以精确到 HTTP 状态码和响应体内容这才是生产环境需要的“真健康”。2.3 Docker 在此架构中的真实定位容器化 ≠ 自动化它解决的是“确定性”很多人把 Docker 等同于“一键部署”这是巨大的误解。Docker 的核心价值在于提供“环境确定性”——无论你在 Ubuntu 22.04、CentOS 7 还是 macOS 上运行docker run sub2api:latest你得到的 Sub2API 进程其二进制版本、依赖库版本、配置文件路径、甚至默认日志格式都完全一致。这种确定性直接消除了“在我机器上好好的”这类经典甩锅场景。但 Docker 本身不解决任何业务逻辑问题。它不会自动帮你配置 Nginx 的 upstream不会自动把 Cloudflare 的 API Token 写入环境变量更不会在 Sub2API 启动失败时自动重启 Codex 实例。它只是一个“沙盒”一个“标准化的运行时”。因此本项目的 Dockerfile 极其克制FROM golang:1.21-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED0 GOOSlinux go build -a -installsuffix cgo -o sub2api . FROM alpine:3.18 RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --frombuilder /app/sub2api . COPY config.yaml . EXPOSE 8080 CMD [./sub2api, -config, config.yaml]这个文件没有安装 curl、没有启动 sshd、没有挂载 /etc它只做一件事把编译好的二进制文件和配置文件打包进一个最小化的 Alpine 镜像。因为我知道Sub2API 的稳定性不取决于镜像里有多少个包而取决于它的 Go 代码是否健壮、它的配置是否正确、它的上游是否可靠。Docker 是载体不是答案。3. 核心细节解析与实操要点从配置文件到健康检查的每一处魔鬼3.1 Sub2API 的 config.yaml路由、重试与超时的黄金三角Sub2API 的灵魂全在config.yaml这个文件里。它不是一份简单的键值对列表而是一套定义服务行为的“契约”。下面是我在线上稳定运行半年的配置逐行解读其背后的深意# 服务监听配置 server: port: 8080 # 关键必须设置 read_timeout否则长文本生成时Nginx 可能因超时关闭连接 read_timeout: 300s write_timeout: 300s idle_timeout: 300s # 上游 Codex 实例定义 upstreams: # codex-gpu 是逻辑名称下游业务调用时指定的 model 名 codex-gpu: # 真实地址注意这里必须是 Sub2API 容器内部能访问的地址 # 如果 Codex 在宿主机用 host.docker.internal如果在另一容器用服务名 url: http://host.docker.internal:3000 # 健康检查每 10 秒向 /healthz 发送一次 GET 请求 health_check: path: /healthz interval: 10s timeout: 5s # 连续 3 次失败才标记为 down避免网络抖动误判 max_fails: 3 # 重试策略当上游返回 5xx 或连接超时时最多重试 2 次 retry: max_attempts: 2 # 重试间隔指数退避第一次 100ms第二次 200ms backoff_base: 100ms # 超时控制对单个上游请求总耗时不能超过 240 秒 timeout: connect: 5s response: 240s codex-cpu: url: http://192.168.1.20:8000 health_check: path: /healthz interval: 15s timeout: 3s max_fails: 5 retry: max_attempts: 1 timeout: connect: 3s response: 120s # 路由规则将 OpenAI 的 model 名映射到 upstream 名 routes: - pattern: ^codex-gpu.*$ upstream: codex-gpu - pattern: ^codex-cpu.*$ upstream: codex-cpu # 默认兜底所有未匹配的 model都打到 codex-cpu - pattern: .* upstream: codex-cpu # 日志与监控 logging: level: info # 关键开启 access_log记录每一次请求的耗时、状态码、上游 access_log: true # 将日志输出到 stdout方便 Docker logs 查看 output: stdout metrics: # 开启 Prometheus metrics暴露 /metrics 端点 enabled: true port: 9090注意url字段中的host.docker.internal是 Docker Desktop 在 macOS/Windows 上的默认网关但在 Linux 服务器上你需要显式添加--add-hosthost.docker.internal:host-gateway到docker run命令中否则 Sub2API 容器无法访问宿主机的 Codex。这是新手踩坑率最高的点之一没有之一。这份配置的精妙之处在于它构建了一个“弹性缓冲带”。当codex-gpu因显存不足偶尔 OOM 时它的健康检查会失败Nginx 会立即将流量切到codex-cpu而 Sub2API 自身的重试机制又能在codex-gpu短暂抖动如 GC 导致的 200ms 卡顿时自动补救一次。这种“多层防御”才是“证明它真的能用”的技术底座。3.2 Nginx 配置不只是反向代理更是流量的“交通警察”Nginx 的配置文件/etc/nginx/conf.d/sub2api.conf是我反复打磨了 17 个版本才定稿的。它远不止proxy_pass那么简单而是集成了流量调度、安全加固、可观测性三大使命upstream sub2api_backend { # server 指向 Sub2API 容器的端口这里假设容器名为 sub2api端口 8080 server sub2api:8080; # 关键启用主动健康检查 # 每 5 秒向 /healthz 发送一次 HEAD 请求 # 要求返回 200 状态码且响应体包含 ok # 连续 3 次失败标记为 down连续 2 次成功标记为 up check interval5 rise2 fall3 timeout3 typehttp; check_http_send HEAD /healthz HTTP/1.0\r\n\r\n; check_http_expect_alive http_2xx; # 负载均衡策略least_conn最少连接数比 round-robin 更适合长连接场景 least_conn; } server { listen 80; listen [::]:80; server_name api.mycompany.com; # 强制 HTTP 重定向到 HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name api.mycompany.com; # SSL 证书由 Cloudflare 提供此处只需配置私钥Cloudflare 会处理公钥 ssl_certificate /etc/nginx/ssl/api.mycompany.com.pem; ssl_certificate_key /etc/nginx/ssl/api.mycompany.com.key; # 关键OpenAI API 的路径必须精确匹配 # /v1/chat/completions, /v1/models, /v1/engines 等 location /v1/ { # 透传所有原始头信息 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 启用 HTTP/1.1 长连接 proxy_http_version 1.1; proxy_set_header Connection ; # 设置超时必须大于 Sub2API 的 read_timeout proxy_connect_timeout 5s; proxy_send_timeout 300s; proxy_read_timeout 300s; # 将请求转发给 upstream proxy_pass http://sub2api_backend; } # 健康检查专用端点供外部监控系统调用 location /healthz { # 直接返回 200不经过 Sub2API return 200 OK; add_header Content-Type text/plain; } # 指标端点供 Prometheus 抓取 location /metrics { # 只允许内网访问防止指标泄露 allow 192.168.0.0/16; deny all; proxy_pass http://sub2api_backend:9090; } }提示check指令是 Nginx Plus 的商业特性开源版 Nginx 并不支持。如果你使用的是开源版必须改用health_check模块需自行编译或退回到被动健康检查max_fails/fail_timeout。我强烈建议对于生产环境直接采购 Nginx Plus其主动健康检查的可靠性远超任何 DIY 方案。一次因健康检查失效导致的 30 分钟服务中断其损失远超一年的许可证费用。这个配置的另一个重点是/healthz和/metrics两个端点的分离。/healthz是给 Cloudflare 或 Kubernetes 的 liveness probe 用的它必须极快、极轻量所以由 Nginx 直接返回而/metrics是给 Prometheus 用的它需要 Sub2API 的真实指标数据所以必须proxy_pass到 Sub2API 的 9090 端口。这种“分而治之”的思路保证了监控系统的稳定性和数据的准确性。3.3 Cloudflare 配置不只是 CDN更是你的第一道“防火墙”Cloudflare 的配置决定了你的服务对外的第一印象。我摒弃了所有“一键优化”按钮手动配置了以下关键项SSL/TLS → Overview: 设置为 “Full (strict)”。这意味着 Cloudflare 到你的服务器之间也必须使用有效的 TLS 证书即 Nginx 配置中的ssl_certificate。虽然增加了证书管理成本但它杜绝了中间人攻击的风险。我使用 Certbot 自动续期脚本每天凌晨 2 点执行续期成功后自动 reload Nginx。SSL/TLS → Origin Server: 上传你的服务器私钥.key文件并生成一个 Cloudflare Origin CA 证书。这个证书将被安装在 Nginx 上作为 Cloudflare 与你的服务器之间的信任凭证。它比 Lets Encrypt 证书更轻量且无需公网可访问。Rules → Transform Rules: 创建一条规则将所有GET /v1/models请求强制缓存 1 小时。因为模型列表极少变更缓存它能将这部分请求的 99% 拦截在 Cloudflare 边缘完全不触达你的服务器。Security → WAF: 启用 OWASP Core Rule Set并将http.header.user-agent包含python-requests或curl的请求速率限制为 10 次/分钟。这有效遏制了脚本小子的暴力探测。DNS: 添加一条 A 记录api.mycompany.com→ 你的服务器公网 IP并将 Proxy status 设置为 “Proxied”橙色云朵。这是 Cloudflare 发挥作用的前提。最关键的一步是Page Rules。我创建了两条规则api.mycompany.com/*→ “Always Use HTTPS” “Disable Security”关闭 WAF因为 WAF 可能误杀大模型请求体中的特殊字符api.mycompany.com/healthz→ “Bypass Cache” “Disable Security”。这两条规则的组合确保了业务流量走安全加速而健康检查流量则直通无阻互不干扰。4. 实操过程与核心环节实现从零开始一步步构建可验证的中转站4.1 环境准备Ubuntu 22.04 服务器上的最小化初始化一切始于一台干净的 Ubuntu 22.04 服务器我选用的是 4C8G 的阿里云 ECS。以下是我在终端里逐行执行的初始化命令每一步都有其不可替代的目的# 1. 更新系统并安装基础工具 sudo apt update sudo apt upgrade -y sudo apt install -y curl wget gnupg2 software-properties-common # 2. 安装 Docker官方源非 snap curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io # 3. 将当前用户加入 docker 组避免每次 sudo sudo usermod -aG docker $USER # 此时需要重新登录或执行 newgrp docker否则 docker 命令会报 permission denied # 4. 安装 Nginx sudo apt install -y nginx # 5. 配置防火墙只开放 80 和 443 sudo ufw allow OpenSSH sudo ufw allow Nginx Full sudo ufw enable # 6. 创建项目目录 mkdir -p ~/sub2api/{config,logs} cd ~/sub2api实操心得很多教程跳过usermod -aG docker这一步导致新手在docker run时遇到权限错误然后疯狂搜索“docker permission denied”浪费大量时间。这是一个纯属“文档遗漏”的坑但却是最高频的问题。我建议把这行命令写在你的所有 Docker 教程开头就像写 Hello World 一样自然。4.2 部署 Codex 实例让模型真正“活”起来Codex 的部署我选择最轻量的codex-server二进制方式非 Docker因为它对 GPU 资源的利用更直接且便于调试。以下是在同一台服务器上为 CPU 和 GPU 分别部署的步骤CPU 版本用于测试和低负载# 下载 codex-server for linux-amd64 wget https://github.com/codex-team/codex-server/releases/download/v0.1.0/codex-server-linux-amd64 chmod x codex-server-linux-amd64 mv codex-server-linux-amd64 /usr/local/bin/codex-cpu # 创建 systemd 服务文件 sudo tee /etc/systemd/system/codex-cpu.service EOF [Unit] DescriptionCodex CPU Server Afternetwork.target [Service] Typesimple Userubuntu WorkingDirectory/home/ubuntu ExecStart/usr/local/bin/codex-cpu --host 0.0.0.0:8000 --model /home/ubuntu/models/phi-3-mini-4k-instruct.Q4_K_M.gguf --ctx-size 4096 Restartalways RestartSec10 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target EOF sudo systemctl daemon-reload sudo systemctl enable codex-cpu sudo systemctl start codex-cpuGPU 版本主力推理# 确保 nvidia-docker2 已安装略参考 NVIDIA 官方文档 # 下载支持 CUDA 12 的 codex-server wget https://github.com/codex-team/codex-server/releases/download/v0.1.0/codex-server-linux-cuda12 chmod x codex-server-linux-cuda12 mv codex-server-linux-cuda12 /usr/local/bin/codex-gpu # 创建 GPU 服务 sudo tee /etc/systemd/system/codex-gpu.service EOF [Unit] DescriptionCodex GPU Server Afternetwork.target [Service] Typesimple Userubuntu WorkingDirectory/home/ubuntu # 关键指定 CUDA_VISIBLE_DEVICES让 codex-gpu 只看到 0 号 GPU EnvironmentCUDA_VISIBLE_DEVICES0 ExecStart/usr/local/bin/codex-gpu --host 0.0.0.0:3000 --model /home/ubuntu/models/llama-3-8b-instruct.Q5_K_M.gguf --ctx-size 8192 --n-gpu-layers 40 Restartalways RestartSec10 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target EOF sudo systemctl daemon-reload sudo systemctl enable codex-gpu sudo systemctl start codex-gpu注意--n-gpu-layers 40这个参数是根据llama-3-8b模型的层数约 32 层和我的 4090 显存24GB经验设定的。它表示将模型的前 40 层全部 offload 到 GPU剩余层在 CPU 运行。实测下来n-gpu-layers设为 32 时显存占用 18GB推理速度 12 tokens/s设为 40 时显存占用 22GB速度提升至 18 tokens/s。多出的 6 层换来了 50% 的速度提升这笔“显存换算力”的交易非常划算。4.3 构建与运行 Sub2API从源码到容器的完整闭环Sub2API 的官方 Docker 镜像sub2api/sub2api有时会滞后于最新版且不包含我定制的健康检查逻辑。因此我选择从源码构建# 1. 克隆仓库并检出稳定分支 git clone https://github.com/sub2api/sub2api.git cd sub2api git checkout v0.8.2 # 2. 编辑 main.go添加一个简单的 /healthz handler官方版没有 # 在 http.HandleFunc(/, ...) 之后添加 # http.HandleFunc(/healthz, func(w http.ResponseWriter, r *http.Request) { # w.WriteHeader(http.StatusOK) # w.Write([]byte(ok)) # }) # 3. 构建二进制 CGO_ENABLED0 GOOSlinux go build -a -ldflags -extldflags -static -o sub2api . # 4. 创建 config.yaml使用上文 3.1 节的完整配置 cat config.yaml EOF # ...此处粘贴完整的 config.yaml 内容 EOF # 5. 构建自定义镜像 docker build -t my-sub2api:latest . # 6. 运行容器关键参数解释 docker run -d \ --name sub2api \ --restartalways \ --networkhost \ # 使用 host 网络让 sub2api 容器能直接访问 host.docker.internal -v $(pwd)/config.yaml:/root/config.yaml \ -v $(pwd)/logs:/root/logs \ -p 8080:8080 \ -p 9090:9090 \ my-sub2api:latest实操心得--networkhost是此部署模式的“命门”。它让容器共享宿主机的网络命名空间从而可以直接用localhost:3000访问宿主机上的 Codex GPU 服务。如果不加这个参数你必须用--add-host或复杂的 Docker 网络配置徒增复杂度。当然host网络牺牲了一定的隔离性但对于一个专用于 Sub2API 的服务器这是可接受的权衡。4.4 Nginx 与 Cloudflare 的联调让“证明它真的能用”成为现实部署完所有组件后真正的挑战才开始如何证明整个链路是可靠的我设计了一套四步验证法第一步本地直连验证绕过所有中间件在服务器上执行curl -X POST http://localhost:3000/v1/chat/completions \ -H Content-Type: application/json \ -d {model: codex-gpu, messages: [{role: user, content: Hello}]}如果返回了标准的 OpenAI JSON 响应说明 Codex GPU 本身工作正常。第二步Sub2API 单元验证绕过 Nginx 和 Cloudflarecurl -X POST http://localhost:8080/v1/chat/completions \ -H Content-Type: application/json \ -d {model: codex-gpu, messages: [{role: user, content: Hello}]}如果返回了带有X-Sub2API-Upstream: codex-gpu头的响应说明 Sub2API 的路由和协议转换正确。第三步Nginx 端到端验证绕过 Cloudflare在服务器上用curl -H Host: api.mycompany.com模拟 Nginx 的 Host 头curl -X POST http://localhost/v1/chat/completions \ -H Host: api.mycompany.com \ -H Content-Type: application/json \ -d {model: codex-gpu, messages: [{role: user, content: Hello}]}如果返回了正确的响应且 Nginx 的 access.log 中出现对应记录说明 Nginx 的proxy_pass和location规则生效。第四步Cloudflare 全链路验证真实用户视角在任意公网机器上执行curl -X POST https://api.mycompany.com/v1/chat/completions \ -H Content-Type: application/json \ -d {model: codex-gpu, messages: [{role: user, content: Hello}]}如果成功返回且 Cloudflare 的 Analytics 仪表盘中能看到该请求说明整个链路打通。提示第四步失败90% 的原因是 Cloudflare 的 SSL/TLS 设置为 “Flexible” 而非 “Full (strict)”。前者只加密 Cloudflare 到用户不加密 Cloudflare 到你的服务器导致你的 Nginx 因缺少有效证书而拒绝连接。务必检查 Cloudflare 控制台的 SSL/TLS → Overview 页面确认状态为绿色的 “Ready”。5. 常见问题与排查技巧实录那些只有亲手踩过才知道的坑5.1 问题速查表高频故障现象与根因定位现象可能根因快速定位命令解决方案curl https://api.mycompany.com/v1/models返回502 Bad GatewayNginx 无法连接 Sub2API 容器sudo docker ps看容器是否运行sudo docker logs sub2api看启动日志检查docker run是否用了--networkhost检查 Sub2API 的config.yaml中port是否与-p参数一致curl http://localhost:8080/v1/chat/completions返回404 Not FoundSub2API 的路由规则未匹配curl http://localhost: