AWS Amplify部署NextJS后流式API失效且超时30秒求助
问题描述
在AWS Amplify上部署的Next.js应用中,针对耗时较长的API调用采用了流式响应方案,本地开发环境运行正常,但部署后流式功能失效,且请求会因超过30秒而超时。前端处理流式响应的代码如下:
try { setLoading(true); setAnswer(''); const res = await fetch(`/api/test?question=${question}`); if (res.ok) { const reader = res?.body?.getReader(); const processStream = async () => { while(true) { const {done, value} = await reader?.read() || {}; if (!value) { setLoading(false); break; } if(done) { setLoading(false); break; } let chunk = new TextDecoder('utf-8').decode(value) chunk = chunk.replace(/^data: /, ''); setAnswer((prev) => prev + chunk); } } processStream().catch(err => console.log('--stream error--', err)) } else { setAnswer("Sorry, there was an error fetching your answer. Please try again later."); } } catch (error) { console.error("Error fetching answer:", error); setAnswer("Sorry, there was an error fetching your answer. Please try again later."); }
解决方案
1. 调整AWS Amplify的超时与流式支持配置
AWS Amplify默认请求超时为30秒,且CDN会缓冲响应导致流式失效,需在项目根目录的amplify.yml中修改配置:
- 延长API对应的Lambda函数超时时间(最大可设为15分钟)
- 为API路径添加分块传输响应头
- 禁用API路径的CDN缓存
示例amplify.yml配置片段:
version: 1 frontend: phases: preBuild: commands: - npm install build: commands: - npm run build artifacts: baseDirectory: .next files: - '**/*' cache: paths: - node_modules/**/* headers: - pattern: /api/* headers: - key: Transfer-Encoding value: chunked - key: Cache-Control value: no-cache, no-store, must-revalidate function: your-api-function-name: timeout: 900 # 15分钟,按需调整
2. 确保Next.js API路由正确实现流式响应
Pages Router(pages/api/test.js)
使用res.write()和res.flush()手动输出分块内容,同时设置正确响应头:
export default async function handler(req, res) { res.setHeader('Content-Type', 'text/plain; charset=utf-8'); res.setHeader('Transfer-Encoding', 'chunked'); res.setHeader('Cache-Control', 'no-cache'); // 模拟流式数据返回逻辑 const dataChunks = ['第一部分内容', '第二部分内容', '第三部分内容']; for (const chunk of dataChunks) { res.write(`data: ${chunk}\n\n`); await new Promise(resolve => setTimeout(resolve, 1000)); res.flush(); // 强制发送当前缓冲区内容 } res.end(); }
App Router(app/api/test/route.js)
使用Next.js流式API返回ReadableStream:
export async function GET(req) { const { searchParams } = new URL(req.url); const question = searchParams.get('question'); const stream = new ReadableStream({ async start(controller) { // 模拟流式数据生成逻辑 const dataChunks = ['第一部分内容', '第二部分内容', '第三部分内容']; for (const chunk of dataChunks) { controller.enqueue(new TextEncoder().encode(`data: ${chunk}\n\n`)); await new Promise(resolve => setTimeout(resolve, 1000)); } controller.close(); } }); return new Response(stream, { headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Cache-Control': 'no-cache' } }); }
3. 优化前端请求配置
确保fetch请求禁用压缩(避免CDN缓冲完整响应),添加必要配置:
const res = await fetch(`/api/test?question=${question}`, { headers: { 'Accept-Encoding': 'identity' // 禁用gzip压缩 }, keepalive: true });
4. 检查Lambda执行角色权限
如果API调用依赖其他AWS服务(如大模型服务、存储服务等),确保Lambda执行角色拥有对应权限,避免因权限问题导致响应停滞超时。
内容的提问来源于stack exchange,提问作者Dragos Micu
相关产品推荐
相关产品推荐

