Vercel Python无服务器函数返回流时触发FUNCTION_INVOCATION_TIMEOUT问题
解决Vercel上Python FastAPI流式转发超时问题
问题分析
在Vercel环境中,使用Python FastAPI的StreamingResponse转发第三方流时,若流持续超过10秒会触发FUNCTION_INVOCATION_TIMEOUT错误,但Node.js通过fetch直接返回流却能正常运行。核心原因是Vercel对Python函数默认设置了10秒超时,且Python的流式响应处理会让函数进程持续运行至流结束;而Node.js的fetch响应透传机制被Vercel优化,不会轻易触发超时。
解决方案
方案1:调整Vercel函数超时配置
在vercel.json中为Python函数设置更长的超时时间(Vercel允许最大900秒),给流转发预留足够时长:
{ "builds": [ { "src": "main.py", "use": "@vercel/python" }, { "src": "stream.js", "use": "@vercel/node"} ], "routes": [ {"src": "/api/(.*)", "dest": "main.py"}, {"src": "/stream/(.*)", "dest": "stream.js"} ], "functions": { "main.py": { "maxDuration": 60 } } }
方案2:优化Python流式转发代码
确保第三方响应的头信息完整透传,让StreamingResponse以更高效的方式传输数据,减少函数进程阻塞:
from fastapi import FastAPI from fastapi.responses import StreamingResponse import httpx app = FastAPI() @app.get("/api/stream/{url:path}") async def forward_stream(url: str): async with httpx.AsyncClient(http2=True) as client: request = client.build_request("GET", f"https://{url}") async with client.send(request, follow_redirects=True, stream=True) as response: # 透传第三方响应的状态码和头信息 headers = dict(response.headers) # 移除流式响应不需要的固定长度头 headers.pop("Content-Length", None) return StreamingResponse( response.aiter_raw(), status_code=response.status_code, headers=headers, media_type=response.headers.get("Content-Type") )
关键优化点
- 透传
Transfer-Encoding: chunked等流式相关头,让Vercel明确识别这是流式响应 - 使用
async with管理客户端连接,避免资源泄漏 - 移除
Content-Length头,防止Vercel等待完整响应内容
方案3:使用Starlette底层响应类
若FastAPI的StreamingResponse仍有问题,可尝试直接用Starlette的底层响应类,贴近Node.js的fetch透传逻辑:
from starlette.responses import Response # 替换接口中的返回逻辑 return Response( content=response.aiter_raw(), status_code=response.status_code, headers=headers, media_type=response.headers.get("Content-Type") )
内容的提问来源于stack exchange,提问作者gdlk
相关产品推荐
相关产品推荐

