CONN_MAX_AGE 能省多少?代价是什么?这篇在 gunicorn + PostgreSQL 上分别量 0 / 60 / None 三种设置的延迟和连接数,再故意把数据库连接上限调到 30,看第二个服务起来之后会发生什么。
CONN_MAX_AGE 中位(ms) p99(ms) 不同 pid 数 结束后连接数 0(默认) 2.78 3.90 300 0 60 0.65 1.34 1 1 None 0.52 0.94 1 1
本机回环上,每请求建连的代价大约 2 ms(认证 + 后端进程 fork);持久连接把它省掉。真实网络、TLS、连接认证更复杂时,这个差距会更大(本文没有测)。
服务 A(16 个处理线程)被打满后,数据库端连接数: 15 错误数: 0
再开服务 B(同样 16 个线程)并打满:数据库端连接数 psql 自己也连不上:sorry, too many clients already 状态码/错误分布: {500: 3}
数据库日志里的相关行: ['2026-09-30 20:19:54.979 CST [11263] FATAL: sorry, too many clients already', '2026-09-30 20:19:55.045 CST [11265] FATAL: sorry, too many clients already']每个 worker × 线程都会各自占一个连接,并且在空闲时也占着。服务实例多了(扩容、滚动发布时新旧实例并存)很容易超过数据库的 max_connections。解决办法是限制线程/进程数,或者在应用和数据库之间放连接池(第 134 篇)。