python
runtime_error
ai_generated
true
INFO: 127.0.0.1:54321 - 'GET /sync-endpoint HTTP/1.1' 200 OK(耗时 5.02 秒,检测到阻塞事件循环)
INFO: 127.0.0.1:54321 - 'GET /sync-endpoint HTTP/1.1' 200 OK (took 5.02s, blocking loop detected)
ID: python/fastapi-event-loop-blocked
80%修复率
88%置信度
0证据数
2024-04-14首次发现
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| 3.8 | active | — | — | — |
| 3.9 | active | — | — | — |
| 3.10 | active | — | — | — |
| 3.11 | active | — | — | — |
| 3.12 | active | — | — | — |
根因分析
在 async def 端点中直接执行了同步阻塞调用(如 time.sleep、requests、重 CPU 计算),阻塞了事件循环,导致所有并发请求停滞。
English
A synchronous blocking call (e.g. time.sleep, requests, heavy CPU) was executed directly inside an async def endpoint, blocking the event loop and stalling all concurrent requests.
解决方案
-
95% 成功率
Offload blocking work to a thread: import anyio @app.get('/sync-endpoint') async def handler(): result = await anyio.to_thread.run_sync(blocking_fn) -
92% 成功率
Define the route as def (not async def) so FastAPI runs it in a threadpool: @app.get('/sync-endpoint') def handler(): return blocking_fn() -
90% 成功率
Replace requests with httpx.AsyncClient and time.sleep with asyncio.sleep.
无效尝试
常见但无效的做法:
-
70% 失败
Each worker is still blocked; throughput per worker stays at one request.
-
90% 失败
Does not fix the blocking call inside the existing one.
-
95% 失败
Unrelated to loop blocking.