共计 3037 个字符,预计需要花费 8 分钟才能阅读完成。
背景痛点
国内开发者在直接使用 ChatGPT 或 Claude 的 API 时,通常会遇到以下问题:

- 网络延迟高:由于国际网络链路的不稳定性,API 响应时间波动较大
- 合规风险:直接连接境外 AI 服务可能违反网络安全相关规定
- API 不稳定:部分地区存在间歇性访问阻断现象
- 计费不透明:跨境 API 调用产生的隐性成本难以控制
技术方案对比
1. 反向代理方案
优点:
– 实现简单,维护成本低
– 支持负载均衡和故障转移
– 可灵活添加缓存层
缺点:
– 需要自建服务器基础设施
– 高并发场景需优化配置
2. WebSocket 隧道
优点:
– 穿透性强,规避常规流量检测
– 保持长连接降低延迟
缺点:
– 实现复杂度高
– 服务器资源消耗大
3. API 网关
优点:
– 提供完善的管理界面
– 内置限流和监控功能
缺点:
– 商业方案成本高
– 自定义能力受限
Nginx+Lua 实现方案
核心架构
flowchart TD
A[客户端] --> B[Nginx 入口]
B --> C{Lua 路由判断}
C -->| 合法请求 | D[后端 API 集群]
C -->| 非法请求 | E[拦截响应]
D --> F[响应处理]
F --> B
关键配置示例
# 主服务配置
server {
listen 443 ssl;
server_name api.yourdomain.com;
# SSL 配置
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Lua 包路径
lua_package_path '/etc/nginx/lua/?.lua;;';
location /v1/chat {
access_by_lua_file /etc/nginx/lua/auth_filter.lua;
proxy_pass https://api.openai.com;
proxy_set_header Host api.openai.com;
# 连接池配置
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Lua 脚本核心逻辑
-- auth_filter.lua
local cjson = require "cjson"
local redis = require "resty.redis"
-- 敏感词检查函数
local function check_sensitive(content)
local sensitive_words = {"政治", "暴力", "违禁词"} -- 示例词库
for _, word in ipairs(sensitive_words) do
if string.find(content, word) then
return false
end
end
return true
end
-- 主处理逻辑
local args = ngx.req.get_uri_args()
if not check_sensitive(args.prompt) then
ngx.status = 403
ngx.say(cjson.encode({error = "Content violation"}))
return ngx.exit(403)
end
-- 负载均衡选择后端
local red = redis:new()
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "Redis connect failed:", err)
-- 降级策略
ngx.var.backend = "https://api.openai.com"
else
local last_used = red:get("last_used_backend")
-- 简单的轮询策略
ngx.var.backend = last_used == "1" and "https://backup.api1.com" or "https://backup.api2.com"
red:set("last_used_backend", last_used == "1" and "2" or "1")
end
性能优化
连接池管理
-
保持与后端服务的持久连接
upstream chatgpt_backend { server api1.openai.com:443; server api2.openai.com:443 backup; keepalive 32; } -
动态调整连接数
-- 根据负载自动扩容 local current_conns = tonumber(red:get("current_connections")) or 0 if current_conns > 30 then ngx.var.backend = "https://fallback.api.com" end
响应缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=chat_cache:10m inactive=1h;
location /v1/chat {
proxy_cache chat_cache;
proxy_cache_key "$request_uri|$request_body";
proxy_cache_valid 200 5m;
proxy_cache_use_stale error timeout updating;
}
安全合规实践
敏感词过滤
- 构建 AC 自动机进行高效匹配
- 支持动态更新词库
-- 定时从数据库加载最新词库 local function load_keywords() local new_words = db.query("SELECT word FROM sensitive_words") update_trie(new_words) -- 更新 AC 自动机 end -- 每小时更新一次 local timer = ngx.timer.every(3600, load_keywords)
日志脱敏
log_format masked '$remote_addr - $remote_user [$time_local]'
'"$masked_request" $status $body_bytes_sent';
map $request_body $masked_request {default "[FILTERED]";
~^(.*) "$1"; # 实际应用中需更复杂的正则处理
}
避坑指南
常见问题
- 代理突然失效
- 检查境外 IP 是否被封锁
- 验证 SSL 证书有效性
-
监控 API 响应码变化
-
性能瓶颈
- 使用
ngx.location.capture进行子请求 -
避免在 Lua 中进行阻塞 I / O 操作
-
合规风险
- 定期审计日志
- 实现双因素认证
- 保留完整的访问记录
动手实验
本地 Docker 部署
-
准备 docker-compose.yml
version: '3' services: nginx: image: openresty/openresty:alpine ports: - "8443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf - ./lua:/etc/nginx/lua -
启动服务
docker-compose up -d curl -k https://localhost:8443/v1/chat -d '{"prompt":" 你好 "}' -
验证功能
- 检查代理请求是否成功
- 测试敏感词过滤效果
- 观察负载均衡行为
总结
本文介绍的技术方案在实际项目中已经过验证,在日请求量百万级的场景下仍能保持稳定。建议开发者根据自身业务特点调整缓存策略和负载均衡算法,特别注意要定期更新安全策略以应对不断变化的监管要求。
正文完
发表至: 未分类
近两天内
