Flask无原生异步支持?我的测试为何符合异步预期?
Flask异步能力的争议与实际场景适配疑问
测试背景与验证过程
看到不少博客及StackOverflow评论称Flask并非真正支持异步,于是编写测试脚本验证,已安装Flask[async]。
测试代码
import time from flask import Flask, jsonify import asyncio app = Flask(__name__) async def simulate_long_task(): await asyncio.sleep(5) print("Task completed!") return "Task completed!" async def simulate_long_task2(): await asyncio.sleep(10) print("Task2 completed!") return "Task2 completed!" @app.route('/test1') async def test1(): tasks = [simulate_long_task() for _ in range(2)] results = await asyncio.gather(*tasks) return jsonify({"message": results}) @app.route('/test2') async def test2(): s = time.time() tasks = [simulate_long_task2() for _ in range(2)] results = await asyncio.gather(*tasks) e =time.time() print(e-s) return jsonify({"message": results}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
并发请求命令
curl 'http://127.0.0.1:5000/test1' & curl --location 'http://127.0.0.1:5000/test1' & curl --location 'http://127.0.0.1:5000/test1' & curl 'http://127.0.0.1:5000/test2' & curl --location 'http://127.0.0.1:5000/test2' & curl --location 'http://127.0.0.1:5000/test2'
日志结果
Dload Upload Total Spent Left Speed 100 50 100 50 0 0 9 0 0:00:05 0:00:05 --:--:-- 13{"message":["Task completed!","Task completed!"]} 100 50 100 50 0 0 9 0 0:00:05 0:00:05 --:--:-- 13{"message":["Task completed!","Task completed!"]} 100 50 100 50 0 0 9 0 0:00:05 0:00:05 --:--:-- 13{"message":["Task completed!","Task completed!"]} 100 52 100 52 0 0 5 0 0:00:10 0:00:10 --:--:-- 13{"message":["Task2 completed!","Task2 completed!"]} 100 52 100 52 0 0 5 0 0:00:10 0:00:10 --:--:-- 13{"message":["Task2 completed!","Task2 completed!"]} 100 52 100 52 0 0 5 0 0:00:10 0:00:10 --:--:-- 13{"message":["Task2 completed!","Task2 completed!"]}
结果与疑问
原本预期所有6个请求会在t=10时同时返回,但实际/test1的3个请求在t=5返回,/test2的在t=10返回,符合异步表现。但仍困惑Flask异步能力的争议点,想了解:
- 测试中忽略的核心问题
- Flask异步不适配的场景
- 何时需要改用FastAPI
- 针对部署机器学习模型多用户请求端点的需求,该如何选择
解答与分析
1. Flask异步的本质局限
Flask的异步支持是基于WSGI协议的兼容层实现,并非原生异步框架(如FastAPI基于ASGI协议)。WSGI本身是同步协议,Flask通过在WSGI服务器中嵌入asyncio事件循环来支持异步视图,但核心的请求处理模型仍受限于WSGI的同步特性:
- 默认的Werkzeug服务器是单线程(调试模式为多线程),单个请求内的协程能被事件循环调度,但遇到CPU密集型任务(如机器学习推理)时,协程会阻塞整个事件循环,导致其他请求等待。
- 生产级WSGI服务器(如Gunicorn)即使开启多进程/多线程,每个进程/线程的事件循环独立,无法实现跨请求的协程调度,和传统同步Flask的并发模型无本质区别。
2. 测试中忽略的核心问题:跨请求并发能力
你的测试仅验证了单个请求内的协程并发,但Flask的异步无法解决跨请求的阻塞问题。例如,若有一个请求在执行CPU密集型的模型推理,在WSGI模型下,该请求会占用当前进程/线程,其他请求必须等待资源释放。而原生ASGI框架(如FastAPI)可在单进程单线程下通过协程调度处理数千个并发请求,只要任务是IO密集型或能正确释放GIL。
3. Flask异步不适配的场景
- 高并发IO密集型场景:如大量需要等待外部API、数据库查询的请求,Flask的异步无法充分利用协程优势,WSGI的线程/进程池会成为瓶颈。
- CPU密集型异步任务:机器学习推理多为CPU/GPU密集型,即使写成async函数,也无法在Flask的异步模型中实现真正并发,GIL会阻塞事件循环,导致其他请求等待。
- 长连接场景:如WebSocket、Server-Sent Events等,Flask异步对这类场景支持有限,而FastAPI原生支持ASGI的长连接特性。
4. 何时改用FastAPI
当遇到以下情况时,建议切换到FastAPI:
- 需要处理高并发多用户请求:机器学习端点若需同时处理数十上百个请求,FastAPI的ASGI模型能用更少资源处理更多并发。
- 涉及长连接或实时交互:如需要推送模型推理进度的WebSocket场景。
- 需利用原生异步生态:如使用异步数据库驱动、异步HTTP客户端等,FastAPI能更好整合这些工具。
- 追求便捷的生产特性:FastAPI自带OpenAPI文档、类型提示、依赖注入等特性,对机器学习端点的调试和维护更友好。
针对机器学习部署需求的建议
- 若模型推理为GPU加速(如TensorFlow/PyTorch的GPU推理),GIL影响较小,Flask+多进程服务器(如Gunicorn+Uvicorn作为WSGI worker)也能处理一定并发,但FastAPI的异步模型仍能更高效管理请求队列。
- 若为CPU密集型推理且并发量较高,FastAPI配合Uvicorn(ASGI服务器)能通过协程调度,在单个进程中处理更多请求,减少资源占用。
- 此外,FastAPI的请求验证、权限控制等特性,能更方便地处理多用户请求的参数校验、身份认证等,适合生产环境部署。
内容的提问来源于stack exchange,提问作者Moein Hasani
相关产品推荐
相关产品推荐

