知其然,知其所以然
Flask 内部机制 2026-10-02

开发模式 Debugger 风险

防御向地验证 Flask 调试器的暴露面:flask run --debug 时错误页面带出源码、路径、异常类型和交互式控制台;不开 debug 只有通用 500;gunicorn 下没有 Werkzeug 调试器、堆栈留在服务端日志;调试服务器默认只监听 127.0.0.1;--debug 参数压过 FLASK_DEBUG=0。

Flask Debugger 开发模式 信息泄漏 真实验证 动画演示
Flask 内部机制 2026-10-02

安全响应头

在真实的 Chrome 里验证安全响应头:没有头时内联脚本与 MIME 不符的脚本都执行、能被别的站点 iframe 嵌入、Referer 带来源;加 CSP(nonce)、nosniff、X-Frame-Options、Referrer-Policy 后分别被拦下;HSTS 只能在 HTTPS 响应里发,代理后面要靠 ProxyFix(x_proto=1) 才能判断。

Flask 安全响应头 CSP nosniff HSTS Chrome 真实验证 动画演示
Flask 内部机制 2026-10-02

HTTPS 与反向代理

用真实的 nginx(自签证书终止 TLS)加 gunicorn 实测 HTTPS 与反向代理:Flask 看不到 https 时外部链接与重定向变成 http;gunicorn 默认只翻译 X-Forwarded-Proto;ProxyFix 与 nginx 的 X-Forwarded-* 配套;Host 要用 $http_host;nginx 的 client_max_body_size 先于 Flask 返回 413;proxy_buffering 让流式响应一次性到达。

Flask HTTPS nginx 反向代理 ProxyFix 真实验证 动画演示
Flask 内部机制 2026-10-02

信任代理头配置

用真实的 nginx 与 gunicorn 实测信任代理头的配置:nginx 覆盖或追加 X-Forwarded-For、ProxyFix 的 x_for 层数、多信任一层会取到客户端伪造的地址、取 XFF 第一个元素的常见写法不可信、没有可信代理却配 ProxyFix 时客户端能决定自己的 IP。

Flask ProxyFix X-Forwarded-For nginx 真实验证 动画演示
Flask 内部机制 2026-10-02

Flask 同步请求模型

实测 Flask 的同步请求模型:8 个各等 1 秒的请求在 sync 单 worker 下 8.0 秒、4 个 worker 下 2.0 秒、8 线程下 1.0 秒;纯计算请求线程不加速而多进程加速;一个慢请求挡住 sync worker 里的快请求 1706 ms;线程里的 request 与 g 不会串。

Flask 同步模型 gunicorn 线程 GIL 真实验证 动画演示
Flask 内部机制 2026-10-02

Flask Async View

实测 Flask 的 async 视图:每个请求新建事件循环、请求内 asyncio.gather 把 3 个 0.5 秒的等待压到 0.5 秒、每个请求多约 251 µs 的开销、在 gunicorn 下 8 个并发的 async 视图在 sync worker 上仍需 8071.5 秒而不会突破 worker 并发数。

Flask async asyncio asgiref 真实验证 动画演示
Flask 内部机制 2026-10-02

Async View 的执行边界

实测 Flask async 视图的执行边界:协程在工作线程的新事件循环里运行、request 与 g 与 session 与 contextvars 都可用、响应返回后 create_task 的任务被取消、模块级的 asyncio.Event 与 Lock 第二个请求报 bound to a different event loop、asyncio.to_thread 带上下文而普通线程没有。

Flask async 事件循环 上下文 asyncio 真实验证 动画演示
Flask 内部机制 2026-10-02

同步代码阻塞异步请求

实测同步代码阻塞异步请求:uvicorn 上的纯 ASGI 应用里 time.sleep 让另一个请求等 1620 ms 而 await 与 to_thread 只要几 ms;gunicorn gthread 下互不影响;同一个 Flask 应用经 asgiref 的 WsgiToAsgi 放到 uvicorn 上全部串行(1609 ms),换 a2wsgi 就不串行;asyncio debug 模式能暴露阻塞调用。

Flask asyncio 阻塞 ASGI uvicorn 真实验证 动画演示
Flask 内部机制 2026-10-02

Flask 与 ASGI

实测 Flask 与 ASGI:同一个 Flask 应用用 gunicorn sync、gunicorn gthread、uvicorn 加 a2wsgi、uvicorn 加 WsgiToAsgi 四种方式,用 ApacheBench 压测轻量与计算型两种接口(单次测量);WSGI 适配器下 WebSocket 握手返回 403。

Flask ASGI uvicorn a2wsgi WebSocket 真实验证 动画演示
Flask 内部机制 2026-10-02

WSGI 到 ASGI 的适配

实测 WSGI 到 ASGI 的适配:对比 gunicorn、a2wsgi、asgiref 与自己写的 25 行适配器交给 Flask 的 environ 差别(asgi.scope、缺失的服务器特有键、wsgi.input 的类型),2 MB 请求体读取,以及流式响应是否边生成边发出——收集完再发的适配器让 4 块同时到达。

Flask WSGI ASGI 适配器 a2wsgi asgiref 真实验证 动画演示
Flask 内部机制 2026-10-02

Greenlet 与 Flask Context

实测 Greenlet 与 Flask 上下文:gunicorn 的 gevent worker 用 1 个进程处理 100 个各睡 1 秒的请求只要 1.05 秒且 g 没有串(gthread 8 线程要 13.1 秒);协作式调度下纯计算请求会卡住其它请求;未 patch 的 threading.local 在 greenlet 之间共享而 contextvars 不会。

Flask gevent greenlet 上下文 真实验证 动画演示
Flask 内部机制 2026-10-02

Thread Local 与请求隔离

实测 Flask 的请求隔离:request、g、current_app 是 LocalProxy,Werkzeug 的 Local 基于 ContextVar;三个线程各自的请求上下文互不影响;新线程要用 copy_current_request_context;g 属于应用上下文;模块级全局变量被线程共享,100 次并发读算写不加锁只计到 29。

Flask Thread Local ContextVar 请求隔离 LocalProxy 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号