先确认开发环境不支持持久连接
Flask 自带的开发服务器(Werkzeug)严格来说不支持 HTTP keep-alive。无论你在 Flask 代码里怎么改响应头,只要底层服务器没实现连接复用,客户端的 TCP 连接在每次请求后都会被关闭。开发阶段通常不需要关心这个,但一旦部署到生产环境,如果你还在用 flask run 或者直接运行 app.run(),就不要指望 keep-alive 能生效。判断方式很简单:抓一下响应头,看看 Connection 字段是 keep-alive 还是 close。
要真正开启 keep-alive,必须把 Flask 应用挂载到支持持久连接的 WSGI 服务器上,比如 Gunicorn、uWSGI、Waitress。下文以 Gunicorn 为例,因为配置参数最直观。
Gunicorn 配置 keep-alive 的正确方式
使用 Gunicorn 作为 Flask 的 WSGI 服务器时,通过命令行参数 --keep-alive 设置连接保持时间,例如 gunicorn -w 4 -b 0.0.0.0:8000 --keep-alive 5 app:app。该参数控制空闲连接的超时秒数,避免长时间占用连接资源。同时建议结合 --worker-connections 限制每个工作进程的最大并发连接数,防止连接池耗尽。
注意 --keep-alive 的值不是越长越好。对于 Web 应用,典型的空闲超时是 5-10 秒。如果设置成 60 秒,并且客户端(比如浏览器或移动 APP)在发完请求后不再复用连接,这些空闲连接会一直占用服务器资源,直到超时关闭。更合理的方式是——先设一个中间值,比如 5 秒,观察一段时间再调整。
改完后怎么验证
部署生效后,可用 curl 命令验证 keep-alive 是否开启:curl -v http://your-server/ 2>&1 | grep -i 'connection'。若输出为 Connection: keep-alive,则表示配置成功。更严谨的方式是使用 tcpdump 抓包,观察多个 HTTP 请求是否复用了同一 TCP 连接(可通过源端口是否变化来判断)。
单次 curl 只能看到响应头里的 Connection 字段,但无法确认复用。如果想确认连接是否真的被保持,可以连续发送两次请求,并使用 time 命令观察耗时差异——第一次有 TCP 三次握手,第二次通常更快。但最可靠的还是抓包:用 tcpdump -i lo port 8000 抓取本地回环流量,如果同一源端口连续发出多个 HTTP 请求,就说明 keep-alive 生效了。
注意超时设置与并发量的平衡
开启 keep-alive 虽能减少 TCP 握手开销,但若 keep-alive 超时设置过长(如超过 60 秒),当并发量大时易导致后端连接数飙升,甚至超出系统限制。建议根据业务场景将超时控制在 5-10 秒,并配合反向代理(如 Nginx)进行连接管理。另外,需确保服务器进程数(workers)与后端连接池容量匹配,避免大量空闲连接占用内存。
具体来说,Nginx 做反向代理时,可以在 upstream 块里加 keepalive 32; 指令,让 Nginx 与后端 Gunicorn 之间也复用连接。这样整个链路都受益。但如果你的应用本身就是对外的入口,没有反向代理,那么 --keep-alive 和 --worker-connections 这两个参数必须一起调。比如 --worker-connections 100 表示单个工作进程最多同时处理 100 个连接(包括活跃和空闲)。如果每秒并发请求有 500,那么 4 个 worker 理论上可承载 400 个连接,再多就需要调整 worker 数或增加 worker-connections。
别在 Flask 代码里瞎改响应头
一个常见错误是仅修改 Flask 应用代码,却忽略了 WSGI 服务器的配置。例如在 Flask 中设置 app.config['SERVER_NAME'] 或使用 before_request 钩子修改响应头 Connection 是无效的,因为底层服务器的 keep-alive 策略由服务器自身控制。正确做法是将 keep-alive 交给 Gunicorn 或 uWSGI 处理,或通过 Nginx 反向代理时在 upstream 块中添加 keepalive 指令。
我曾经见过有人在 Flask 视图里手动返回 Response(headers={'Connection': 'keep-alive'}),结果抓包发现连接还是被关闭了。因为 Gunicorn 会忽略应用层设置的 Connection 头,它自己决定是否复用连接。所以,如果你发现客户端始终收到 Connection: close,请优先检查 Gunicorn 的启动参数,而不是翻 Flask 代码。
性能测试帮你做决定
开启 keep-alive 能显著提升高并发场景下的小请求响应速度,但并非所有路由都适合。对于频繁超时或短连接的场景(如周期性轮询),保持长连接反而可能降低连接复用率。建议在部署后使用 AB(Apache Bench)或 wrk 工具进行基准测试,比较开启与关闭 keep-alive 时的吞吐量和响应时间,以确定最优配置。
举个例子,如果你的应用大部分是 API 调用,单个请求处理时间不足 10ms,那么 keep-alive 带来的 TCP 握手节省会非常明显。但如果你的应用有大文件下载或者 websocket 长连接,keep-alive 反而可能干扰连接管理。测试时注意控制变量:先关掉 keep-alive 跑一轮,记录平均响应时间和每秒请求数;再打开 keep-alive,用同样的并发数跑一轮。观察两轮差异,如果开启后请求数明显上升且响应时间稳定,那就是收益;如果差异不大甚至下降,就需要考虑是不是空闲连接占用了过多 worker 资源。总之,配好环境后一定要亲手测一下,不要凭感觉决定超时值。