为何长时间请求会导致FastAPI服务器冻结?
关于FastAPI异步请求及你的服务器问题解答
1. 为何请求第三方无响应服务时会导致服务器冻结?
你代码里的urllib.request.urlopen是同步阻塞的网络调用,哪怕proxy函数加了async关键字,这个同步操作会直接卡住Uvicorn的事件循环线程。你的EC2是1vCPU规格,Uvicorn默认单进程单线程运行时,事件循环被阻塞后,所有后续请求都得等这个阻塞的请求超时(比如系统默认的TCP超时)才能被处理,看起来就像服务器“冻结”了。
2. 能否让服务器不受请求时长限制,同时处理多个请求?
完全可以,核心是把同步的HTTP请求换成异步HTTP客户端,比如aiohttp,这样不会阻塞事件循环。同时可以给第三方请求设置合理的超时时间,避免无限制等待。
修改后的示例代码:
import aiohttp from fastapi import FastAPI, Request, Response import urllib.parse app = FastAPI() async def proxy(request, sUrl): target_url = urllib.parse.unquote(sUrl) timeout = aiohttp.ClientTimeout(total=10) # 设置10秒总超时 async with aiohttp.ClientSession(timeout=timeout) as session: async with session.get(target_url) as target_response: content = await target_response.text() return Response( status_code=target_response.status, content=content, media_type=target_response.headers.get('Content-Type', 'text/plain') ) @app.get("/") async def get_proxy(url: str = "", request: Request = {}): return await proxy(request, url)
换成异步客户端后,事件循环可以在等待第三方响应的间隙处理其他请求,不会被单个慢请求卡住。
3. 换成2个vCPU会有什么差异?
- 如果还用原来的同步代码:你可以给Uvicorn设置
--workers 2,让它启动2个工作进程,每个进程占用1个vCPU。这样当一个进程被慢请求阻塞时,另一个进程还能处理新请求,不会完全冻结,但本质还是同步阻塞,并发能力提升有限。 - 如果已经换成异步代码:2vCPU可以让你设置更多的工作进程(比如
--workers 2),或者调整Uvicorn的线程数,更好地利用多核资源,同时事件循环本身能处理更多并发请求,整体并发能力会比1vCPU时显著提升。
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

