共计 2308 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
直接调用 OpenAI 官方 API 存在两个主要问题:

- 高昂成本 :GPT-3.5 每 1000 tokens 约 0.002 美元,高频使用时账单增长极快
- 响应延迟 :国内直连 API 平均延迟超过 800ms,且常有超时现象
技术选型对比
针对无服务器方案,我们对比了两种主流选择:
- Cloudflare Workers
- 优势:全球网络加速、免费调用额度高(10 万次 / 天)
-
劣势:需要处理 KV 存储的异步问题
-
Vercel Edge Functions
- 优势:与 Next.js 无缝集成、自动 CDN 分发
- 劣势:免费版有执行时长限制(50ms CPU 时间)
最终选择 Cloudflare Workers 作为代理层,因其更适合高并发场景。
核心实现
Next.js 流式响应实现
/**
* 处理流式数据的 React Hook
* @param endpoint 代理 API 地址
* @param initialMessage 初始对话消息
*/
function useStreamingResponse(
endpoint: string,
initialMessage: string
) {const [response, setResponse] = useState('');
useEffect(() => {const controller = new AbortController();
const fetchData = async () => {
try {
const res = await fetch(endpoint, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({message: initialMessage}),
signal: controller.signal
});
const reader = res.body?.getReader();
if (!reader) return;
while (true) {const { done, value} = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
setResponse(prev => prev + chunk);
}
} catch (error) {console.error('Stream error:', error);
}
};
fetchData();
return () => controller.abort();
}, [endpoint, initialMessage]);
return response;
}
Nginx 反向代理配置
location /api/proxy {
proxy_pass https://api.openai.com/v1/chat/completions;
# 缓存高频问答对
proxy_cache my_cache;
proxy_cache_key "$request_uri|$request_body";
proxy_cache_valid 200 10m;
# 防止 API Key 泄露
proxy_set_header Authorization "Bearer $hidden_api_key";
proxy_hide_header Authorization;
}
性能优化实战
对话存储方案对比
| 方案 | 容量上限 | 读写速度 | 持久性 |
|---|---|---|---|
| LocalStorage | 5MB | 同步 | 标签页独立 |
| IndexedDB | 浏览器限制 | 异步 | 全站共享 |
推荐使用 IndexedDB 存储长对话历史,因其支持事务操作和更大存储空间。
TTFB 优化技巧
- 预连接 DNS:
<link rel="dns-prefetch" href="//your-proxy.domain"> - 启用 HTTP/ 2 服务端推送
- 压缩 API 响应:
gzip_min_length 1k;
常见问题处理
应对 429 限流
// 指数退避重试机制
async function retryWithBackoff(fn: () => Promise<any>,
retries = 3,
delay = 1000
) {
try {return await fn();
} catch (error) {if (retries <= 0 || error.status !== 429) throw error;
await new Promise(res => setTimeout(res, delay));
return retryWithBackoff(fn, retries - 1, delay * 2);
}
}
敏感词过滤
/** 匹配政治敏感词(示例)*/
const SENSITIVE_REGEX = /(某敏感词 1 | 某敏感词 2)/gi;
function sanitizeInput(text: string) {
return text.replace(SENSITIVE_REGEX, match =>
'*'.repeat(match.length)
);
}
安全加固方案
API Key 多层防护
- 环境变量加密:使用
wrangler secret put API_KEY - 请求频率限制:
limit_req zone=apilimit burst=5 nodelay; - IP 白名单过滤
CSP 策略示例
Content-Security-Policy:
default-src 'self';
connect-src 'self' api.openai.com;
script-src 'unsafe-inline' 'unsafe-eval';
开放性问题
在零服务器成本的前提下,可以考虑:
1. 使用浏览器 Service Worker 缓存历史对话
2. 将记忆加密后存储在 URL hash 中
3. 利用 Cloudflare D1 实现边缘数据库
哪种方案更适合长期对话场景?欢迎在评论区分享你的见解。
正文完
