共计 3773 个字符,预计需要花费 10 分钟才能阅读完成。
背景痛点分析
最近很多开发者想搭建 ChatGPT 镜像站,主要出于两个需求:

- 国内网络无法直接访问 OpenAI 官方 API
- 需要对 API 调用进行二次封装,加入自定义逻辑
但在实际搭建过程中,会遇到几个棘手问题:
- 如何选择合适的反向代理方案?不同方案的延迟和成本差异很大
- OpenAI 有严格的反爬机制,容易触发风控
- 直接代理所有流量会导致高昂的 API 调用成本
技术方案对比
反向代理方案选型
我们测试了三种常见方案:
- Cloudflare Workers
- 优点:边缘计算、延迟低
-
缺点:免费额度有限,超出后成本高
-
Vercel Edge
- 优点:部署简单
-
缺点:冷启动延迟明显
-
Nginx 反向代理
- 优点:完全可控,成本低
- 缺点:需要自己维护服务器
实测数据(测试环境:上海到 OpenAI 美国节点):
- Cloudflare Workers 平均延迟:280ms
- Vercel Edge 平均延迟:420ms(冷启动时可达 1.5s)
- Nginx 反向代理平均延迟:320ms
对于大多数场景,我们推荐使用 Nginx 方案,性价比最高。
核心实现
动态域名解析配置
使用 Python+Cloudflare API 实现动态 DNS 更新:
import requests
import time
# Cloudflare API 配置
API_KEY = 'your_api_key'
ZONE_ID = 'your_zone_id'
RECORD_ID = 'your_record_id'
DOMAIN = 'your.domain.com'
def update_dns_record(ip):
url = f'https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records/{RECORD_ID}'
headers = {'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
data = {
'type': 'A',
'name': DOMAIN,
'content': ip,
'ttl': 120,
'proxied': False
}
try:
response = requests.put(url, headers=headers, json=data)
response.raise_for_status()
print(f'Successfully updated DNS record to {ip}')
except Exception as e:
print(f'Error updating DNS record: {e}')
# 获取当前公网 IP(简化版,实际生产环境需要更健壮的实现)def get_public_ip():
try:
return requests.get('https://api.ipify.org').text
except:
return None
if __name__ == '__main__':
current_ip = get_public_ip()
if current_ip:
update_dns_record(current_ip)
Nginx Stream 模块配置
使用 Nginx 的 stream 模块实现 TCP 层代理:
# /etc/nginx/nginx.conf
stream {
upstream openai_backend {server api.openai.com:443;}
server {
listen 443;
proxy_pass openai_backend;
# SSL 配置
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# 连接超时设置
proxy_connect_timeout 5s;
# 缓冲区设置
proxy_buffer_size 16k;
}
}
SSL 证书管理建议使用 Let’s Encrypt,配合 certbot 自动续期:
sudo apt install certbot
sudo certbot certonly --standalone -d your.domain.com
基于 Redis 的频率限制
使用 Lua 脚本实现精确的请求频率控制:
-- rate_limit.lua
local key = KEYS[1] -- 限流 key,如用户 IP
local limit = tonumber(ARGV[1]) -- 限流阈值
local expire_time = tonumber(ARGV[2]) -- 过期时间(秒)local current = tonumber(redis.call('GET', key)) or 0
if current + 1 > limit then
return 0
else
redis.call('INCR', key)
if current == 0 then
redis.call('EXPIRE', key, expire_time)
end
return 1
end
Nginx 中集成限流:
http {
lua_shared_dict my_limit_req_store 100m;
server {
location / {
access_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000) -- 1 秒超时
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis:", err)
return ngx.exit(500)
end
local res, err = red:eval([[-- 上面提到的 Lua 脚本内容]], 1, ngx.var.remote_addr, "100", "60")
if res == 0 then
ngx.exit(429)
end
}
proxy_pass https://your_backend;
}
}
}
避坑指南
OpenAI 风控规避
- 避免短时间内大量相同请求
- 模拟浏览器 User-Agent
- 控制单个 IP 的请求频率
流量伪装
在 Nginx 中添加这些 HTTP 头:
proxy_set_header Host api.openai.com;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header User-Agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
proxy_set_header Accept "application/json";
proxy_set_header Accept-Language "en-US,en;q=0.9";
低成本流量分发
可以结合 Cloudflare CDN:
- 在 Cloudflare 中设置页面规则,缓存 API 响应
- 设置合适的缓存时间(如 5 分钟)
- 启用 Argo Smart Routing 优化路由
安全加固
HMAC 签名
在 API 网关层实现请求签名验证:
import hmac
import hashlib
def verify_signature(api_key, signature, timestamp, body):
# 防止重放攻击,时间戳不能相差超过 5 分钟
if abs(int(time.time()) - int(timestamp)) > 300:
return False
expected_signature = hmac.new(api_key.encode(),
f'{timestamp}{body}'.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected_signature)
IP 访问控制
使用 iptables 限制访问:
# 只允许特定 IP 访问 443 端口
sudo iptables -A INPUT -p tcp --dport 443 -s 允许的 IP -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j DROP
# 限制单个 IP 的连接数
sudo iptables -A INPUT -p tcp --dport 443 -m connlimit --connlimit-above 50 -j DROP
性能测试
使用 ab 工具进行压力测试(测试环境:4 核 8G 服务器):
ab -n 1000 -c 50 https://your.domain.com/v1/chat/completions
测试结果:
- Nginx 方案:QPS 320,平均延迟 35ms
- Cloudflare Workers:QPS 280,平均延迟 42ms
- Vercel Edge:QPS 210,平均延迟 68ms(冷启动时可达 200ms)
总结与思考
经过以上实践,我们成功搭建了一个稳定可用的 ChatGPT 镜像站。但在实际运营中,还会遇到突发流量的问题。如何设计多级缓存策略来应对这种情况?比如:
- 第一层:CDN 边缘缓存
- 第二层:Nginx 内存缓存
- 第三层:Redis 缓存
每种缓存应该设置怎样的过期策略?如何平衡缓存一致性和性能?这是值得我们进一步探讨的问题。
正文完
