连接池最大 50 个,空闲 10 分钟后取出的连接有 30% 在第一次 send 时抛 BrokenPipeError,重试后才成功。乍看像缓存或者权限的锅,追下去往往不是。

if time.time() - conn.last_used > 300:
    conn.close()
    conn = new_conn()

追下去是这么回事:连接在池里放着,对端或防火墙已经把它关了,池子没有做探活。取出来直接用,第一次写才会发现连接已死。

「连接池死连接」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。

能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。报错里带路径的,先去看那个路径在不在、权限对不对。

同一份配置存在多处的,先确认改的是被加载的那一份。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。

具体做法是,取用前做一次轻量探活;设置 max_idle_time 超过就淘汰;写失败时剔除并重建连接;把重建次数打进监控。

验收就看一点,加上空闲淘汰后 BrokenPipe 从 30% 降到 0.3%,每小时重建次数不到 5 次。

作者 9823189