共计 2073 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
最近在项目中使用 ChatGPT API 时遇到了几个棘手问题,这里总结下开发者直连 API 的典型痛点:

- 地域限制 :某些地区直接访问 api.openai.com 不稳定,经常出现连接超时
- QPS 瓶颈 :免费账户每分钟只有 3 次请求限额,付费账户默认也就 3500 次 / 分钟
- 密钥泄露 :前端直接调用必须暴露 API Key,存在被恶意刷量的风险
技术选型
对比了三种主流的解决方案:
- 云厂商 API 网关 (如 AWS API Gateway)
- 优点:开箱即用的限流和监控
-
缺点:无法自定义请求头处理规则,且存在厂商锁定风险
-
OpenResty
- 优点:可以通过 Lua 脚本实现复杂逻辑
-
缺点:学习曲线陡峭,性能调优复杂
-
Nginx 反向代理
- 优点:配置简单,资源占用低
- 缺点:需要自行实现 JWT 等高级功能
最终选择 Nginx 方案,因为:
1. 团队已有 Nginx 运维经验
2. 需要精细控制 HTTP 头部的修改
3. 未来可以平滑升级到 OpenResty
核心实现
基础转发配置
server {
listen 443 ssl;
server_name chat.yourdomain.com;
location /v1/chat/completions {
proxy_pass https://api.openai.com;
proxy_set_header Authorization "Bearer $OPENAI_KEY";
proxy_ssl_server_name on;
}
}
关键点说明:
– proxy_ssl_server_name 必须开启 SNI
– 建议启用 HTTP/ 2 提升并发性能
速率限制方案
limit_req_zone $binary_remote_addr zone=openai:10m rate=1r/s;
location /v1/chat/completions {
limit_req zone=openai burst=5 nodelay;
# ... 其他配置
}
参数解释:
– 10m:共享内存区大小(可存储 16 万 IP 状态)
– burst=5:允许突发 5 个请求
– nodelay:立即处理突发请求而不延迟
JWT 鉴权实现
Go 语言中间件示例:
func AuthMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {tokenString := r.Header.Get("Authorization")
if tokenString == "" {w.WriteHeader(401)
return
}
// 解析 JWT
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {return []byte(os.Getenv("JWT_SECRET")), nil
})
if err != nil || !token.Valid {w.WriteHeader(403)
return
}
// 将用户 ID 注入上下文
ctx := context.WithValue(r.Context(), "userID", token.Claims.(jwt.MapClaims)["sub"])
next.ServeHTTP(w, r.WithContext(ctx))
})
}
生产级优化
速率限制调参
建议根据业务场景调整:
– 问答场景 :rate=1r/s + burst=3
– 批处理场景 :rate=10r/m + burst=0
审计日志设计
log_format openai_log '$time_iso8601 $jwt_sub $request_id'
'$http_x_forwarded_for $request_length'
'$upstream_response_time $status';
关键字段:
– $jwt_sub:通过 map 从 JWT 提取用户 ID
– $request_id:用于链路追踪
– prompt_hash:建议用 SHA256 处理敏感内容
避坑指南
OpenAI 风控规避
-
请求头伪装 :
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header User-Agent "Mozilla/5.0"; -
超时设置 :
proxy_connect_timeout 10s; proxy_read_timeout 30s; -
内容过滤 :
- 用 Lua 脚本检测违规关键词
- 对政治、暴力类 prompt 返回 400
监控方案
Prometheus 监控关键指标:
- name: nginx_errors
rules:
- alert: HighErrorRate
expr: rate(nginx_http_requests_total{status=~"5.."}[1m]) > 0.1
for: 5m
开放问题
目前我们的方案是轮询多个 API Key,更优的方案可能是:
– 根据用户 ID 哈希分配 Key
– 实时监控各 Key 的剩余额度
– 故障时自动切换
不知道大家有没有更好的动态路由方案?欢迎在评论区讨论。
正文完
