bigywater.tech
Flask · 136

Flask 同步请求模型

Flask 是同步框架,到底意味着什么?一个 worker 能同时处理几个请求?线程和进程哪个对等待有帮助、哪个对计算有帮助?这篇用真实的 gunicorn 与开发服务器,把等待型和计算型两种负载各跑一遍。

8 → 1 秒
8 个各等 1 秒的请求:gunicorn sync 单 worker 与 8 线程的总耗时
1.4 vs 0.4 秒
8 个纯计算请求:8 线程与 4 个进程的总耗时
0 个
8 个线程并发写读 g 时读错的个数

等待型负载

实测 · 本机执行输出
  gunicorn sync,1 个 worker               总耗时  8.05 秒 | 用到 1 个进程、1 个线程 | 全部 200: True
  gunicorn sync,4 个 worker               总耗时  2.02 秒 | 用到 4 个进程、1 个线程 | 全部 200: True
  gunicorn gthread,1 个 worker × 8 线程     总耗时  1.02 秒 | 用到 1 个进程、8 个线程 | 全部 200: True
  flask run(开发服务器,默认多线程)                 总耗时  1.01 秒 | 用到 1 个进程、8 个线程 | 全部 200: True
  flask run --without-threads            总耗时  8.09 秒 | 用到 1 个进程、1 个线程 | 全部 200: True

上一篇:信任代理头配置;下一篇:Flask Async View。

计算型负载

实测 · 本机执行输出
  gunicorn sync,1 个 worker               总耗时  1.43 秒 | 用到 1 个进程
  gunicorn sync,4 个 worker               总耗时  0.40 秒 | 用到 4 个进程
  gunicorn gthread,1 个 worker × 8 线程     总耗时  1.43 秒 | 用到 1 个进程
  flask run(开发服务器,默认多线程)                 总耗时  1.44 秒 | 用到 1 个进程
  (本机 CPU 核数: 10 )

队头阻塞

实测 · 本机执行输出
  gunicorn sync,1 个 worker               慢请求(2 秒)进行中,一个只要 0 秒的请求用了 1706 ms
  gunicorn gthread,1 个 worker × 8 线程     慢请求(2 秒)进行中,一个只要 0 秒的请求用了 5 ms

上下文互相独立

实测 · 本机执行输出
  8 个并发请求在同一个进程的 8 个线程里,各自读回自己写进 g 的值,读错的有 0 个

分步演示

Flask 同步请求模型
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动。gunicorn sync 与 gthread worker、flask run(Werkzeug 开发服务器),本机 10 核
    • 没有验证:gevent 与 eventlet 的协作式并发(见第 142 篇)、真实数据库等待下的数字、内存占用随 worker 与线程数的变化、Python 3.13 之后的自由线程(无 GIL)构建
    京ICP备2026067502号-1京公网安备11010502063487号