单个Flask进程扛不住并发,因其内置服务器是单线程单进程、无连接池、无请求队列,且默认禁用多线程/多进程,无法应对I/O阻塞和高并发。

为什么单个 Flask 进程扛不住并发?
Flask 自带的 app.run() 是开发服务器,用的是单线程单进程 WSGI 服务器(Werkzeug),不支持多 worker、无连接池、无请求队列缓冲。压测时一过 50 QPS 就开始超时或 500,不是代码慢,是它根本没设计用来跑线上。
- 它默认禁用多线程/多进程(threaded=False, processes=1),连基础并发都靠不住
- 没有优雅重启、健康检查、请求超时控制等生产必需能力
- 一旦某个请求卡住(比如数据库慢查询、外部 API 延迟),整个进程就阻塞,后续所有请求排队
Gunicorn 启动参数怎么配才不翻车?
Gunicorn 是 Python 生产部署最常用 WSGI 服务器,但参数乱设反而会让并发更差。
- workers 别盲目设成 CPU 核数 × 2:CPU 密集型服务可以这么干,但 Flask 多数是 I/O 密集(DB、HTTP 调用),建议从 4 开始调,配合 worker-class=gevent 或 eventlet 更合适
- 必须设 timeout=30 和 keepalive=5:前者防长连接拖死 worker,后者减少 TCP 握手开销
- preload=True 要打开:避免每个 worker 单独 import 应用导致内存重复加载和启动延迟
- 日志别只看 access log:error-logfile 和 capture-output 打开才能捕获未处理异常和 print 输出
Nginx 到底转发什么?哪些头必须透传?
Nginx 不只是反向代理,它承担了 SSL 终止、静态文件服务、连接复用等关键角色。如果配置漏掉几个头,Flask 里 request.remote_addr 会变成 127.0.0.1,url_for(..., _external=True) 生成的链接全是 http,HTTPS 下跳转 302 就崩了。
- 必须加这三行:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
- proxy_buffering off; 对流式响应(如 SSE、大文件下载)很关键,否则 Nginx 会缓存整块响应再吐给客户端
- upstream 块里别只写一个 Gunicorn 地址:哪怕单机部署,也用 upstream flask_app { server 127.0.0.1:8000; } 包一层,方便后续横向扩到多台机器
并发上不去?先查这三个地方
压测结果不如预期,90% 不是框架问题,而是链路中某处成了瓶颈。
- 查 Gunicorn 的 accesslog 和 errorlog:有没有大量 Worker timeout 或 Connection reset by peer,说明 worker 不够或 timeout 太短
- 查 Nginx 的 error.log:出现 upstream timed out 是 Nginx 等不到后端响应,得同步调大 proxy_read_timeout 和 Gunicorn 的 timeout
- 查数据库连接池:Flask-SQLAlchemy 默认 pool_size=5,Gunicorn 启 4 个 worker 就可能抢光连接,pool_size 至少设为 workers × 2,并确认 pool_pre_ping=True
workers 别盲目设成 CPU 核数 × 2:CPU 密集型服务可以这么干,但 Flask 多数是 I/O 密集(DB、HTTP 调用),建议从 4 开始调,配合 worker-class=gevent 或 eventlet 更合适
- 必须设 timeout=30 和 keepalive=5:前者防长连接拖死 worker,后者减少 TCP 握手开销
- preload=True 要打开:避免每个 worker 单独 import 应用导致内存重复加载和启动延迟
- 日志别只看 access log:error-logfile 和 capture-output 打开才能捕获未处理异常和 print 输出
Nginx 到底转发什么?哪些头必须透传?
Nginx 不只是反向代理,它承担了 SSL 终止、静态文件服务、连接复用等关键角色。如果配置漏掉几个头,Flask 里 request.remote_addr 会变成 127.0.0.1,url_for(..., _external=True) 生成的链接全是 http,HTTPS 下跳转 302 就崩了。
- 必须加这三行:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
- proxy_buffering off; 对流式响应(如 SSE、大文件下载)很关键,否则 Nginx 会缓存整块响应再吐给客户端
- upstream 块里别只写一个 Gunicorn 地址:哪怕单机部署,也用 upstream flask_app { server 127.0.0.1:8000; } 包一层,方便后续横向扩到多台机器
并发上不去?先查这三个地方
压测结果不如预期,90% 不是框架问题,而是链路中某处成了瓶颈。
- 查 Gunicorn 的 accesslog 和 errorlog:有没有大量 Worker timeout 或 Connection reset by peer,说明 worker 不够或 timeout 太短
- 查 Nginx 的 error.log:出现 upstream timed out 是 Nginx 等不到后端响应,得同步调大 proxy_read_timeout 和 Gunicorn 的 timeout
- 查数据库连接池:Flask-SQLAlchemy 默认 pool_size=5,Gunicorn 启 4 个 worker 就可能抢光连接,pool_size 至少设为 workers × 2,并确认 pool_pre_ping=True
accesslog 和 errorlog:有没有大量 Worker timeout 或 Connection reset by peer,说明 worker 不够或 timeout 太短
- 查 Nginx 的 error.log:出现 upstream timed out 是 Nginx 等不到后端响应,得同步调大 proxy_read_timeout 和 Gunicorn 的 timeout
- 查数据库连接池:Flask-SQLAlchemy 默认 pool_size=5,Gunicorn 启 4 个 worker 就可能抢光连接,pool_size 至少设为 workers × 2,并确认 pool_pre_ping=True
真实场景里,最常被忽略的是 Gunicorn worker 类型和数据库连接池的匹配——用 sync worker 却没调大 pool_size,或者用了 gevent 却忘了给数据库驱动打 monkey patch,结果并发一上来就卡在 DB 层,还以为是网络问题。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。

















