
博客目录
-
-
- [🔍 场景还原](#🔍 场景还原)
- [✅ 根本原因分析](#✅ 根本原因分析)
-
- [✅ 1. 单 worker 模型导致**请求排队**](#✅ 1. 单 worker 模型导致请求排队)
- [✅ 2. **循环依赖 + 同步阻塞** 导致**死锁**](#✅ 2. 循环依赖 + 同步阻塞 导致死锁)
- [✅ 3. **超时打破死锁**](#✅ 3. 超时打破死锁)
- [🧠 总结一句话](#🧠 总结一句话)
- [✅ 解决方案建议](#✅ 解决方案建议)
- [📌 小贴士](#📌 小贴士)
-
fastapi 使用的是 uvicorn 一个 worker
请求 flask 的一个接口,flask 使用的是 gunicorn 也是一个 worker
从 fastapi 发送了一个请求到 flask 的接口,在 flask 的这个接口中,又请求和 fastapi 服务的一个异步方法,2 个系统都会阻塞,
但是将请求 fastapi 的接口设置一个超时时间,则超时后,2 个系统可以正常使用
这个场景,本质上是一个同步阻塞 + 循环依赖 + 单工作进程 导致的死锁 问题。

🔍 场景还原
-
FastAPI 服务:
- 使用
uvicorn单 worker(--workers 1)。 - 同步接口(或异步接口中用了阻塞调用)调用了 Flask 的接口。
- 使用
-
Flask 服务:
- 使用
gunicorn单 worker(--workers 1)。 - 接口内部又调用了 FastAPI 的一个异步接口(或同步接口,但阻塞等待)。
- 使用
-
结果:
- 两个服务都阻塞,无法响应后续请求。
- 一旦给其中一方的请求设置超时 ,超时后,两个系统恢复。
✅ 根本原因分析
✅ 1. 单 worker 模型导致请求排队
uvicorn和gunicorn在单 worker 模式下,只有一个进程处理请求。- 如果当前请求没有处理完 ,新请求会被排队 ,不会被处理。
✅ 2. 循环依赖 + 同步阻塞 导致死锁
- FastAPI 请求 Flask → Flask 请求 FastAPI。
- 此时:
- FastAPI 的 worker 正在等待 Flask 的响应(阻塞)。
- Flask 的 worker 正在等待 FastAPI 的响应(也阻塞)。
- 两个服务的唯一 worker 都在等待对方 ,没有空闲 worker 处理新请求。
- 形成死锁。
✅ 3. 超时打破死锁
- 一旦其中一方(如 FastAPI 请求 Flask)设置了超时时间 :
- 超时后,FastAPI 放弃等待,释放了自己的 worker。
- FastAPI 的 worker 恢复后,可以处理 Flask 发来的请求。
- Flask 收到响应后,也释放了自己的 worker。
- 死锁被打破,系统恢复。
🧠 总结一句话
单 worker + 同步阻塞 + 循环调用 = 死锁;超时打破等待,释放 worker,死锁解除。
✅ 解决方案建议
| 方案 | 说明 |
|---|---|
| ✅ 增加 worker 数量 | 至少 2 个 worker,避免单点阻塞。 |
| ✅ 避免同步循环调用 | 用消息队列(如 Redis + Celery)解耦。 |
| ✅ 使用异步非阻塞调用 | FastAPI 端用 httpx.AsyncClient,Flask 端用 aiohttp 或 httpx,但注意 Flask 本身不支持异步视图(除非用 quart 或 flask 2.x + asgiref)。 |
| ✅ 设置超时 | 作为兜底机制,防止死锁永久挂起。 |
📌 小贴士
- 单 worker 模式只适合开发调试,生产环境务必多 worker。
- 如果你用的是
sync视图 +requests库,一定是阻塞的,即使 FastAPI 是异步框架。
觉得有用的话点个赞
👍🏻呗。❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
