Redis 连接池配置不当导致 TIME_WAIT 暴涨、端口被打满的排查与优化前言最近线上服务出现了一个比较典型的问题——服务器端口被打满导致新连接无法建立。排查后发现根因是 Redis 客户端连接池配置不合理产生了大量短连接进而导致 TIME_WAIT 状态的连接持续堆积。这里记录一下整个排查和优化过程希望能帮到遇到类似问题的同学。问题现象线上告警显示服务出现连接异常登录服务器后通过netstat统计 TIME_WAIT 状态的连接数netstat -ant | awk $6TIME_WAIT{c} END{print c}多次执行后发现TIME_WAIT 连接数在持续攀升22644 22934 23499 22640 22775 24984 25503 26096 25853 26123 26630 27101 27518 27791 27146 27327 27858 28190 28638 28033从22k一路涨到28k而且没有回落趋势。Linux 默认的本地端口范围是32768~60999大约 28000 个端口此时已经接近打满。原因分析排查发现问题出在 Redis 客户端的连接池配置上。原来的配置如下RdbClient redis.NewClient(redis.Options{ Addr: host : port, Password: pass, DB: db, PoolSize: 100, MinIdleConns: 10, MaxIdleConns: 20, })这个配置存在几个关键问题1. PoolSize 过小PoolSize: 100意味着连接池最多持有 100 个连接。在高并发场景下100 个连接远远不够用。当池内连接全部被占用时客户端会创建新的连接来处理请求而这些临时连接用完就关闭变成了短连接。2. 空闲连接管理不合理MinIdleConns: 10、MaxIdleConns: 20让连接池对空闲连接的保留非常吝啬。大量连接在空闲后迅速被回收等下一波请求来了又得重新建连造成连接的频繁创建和销毁。3. 缺少空闲超时配置没有设置ConnMaxIdleTime导致空闲连接的生命周期管理缺失。核心矛盾连接池容量不足 空闲连接回收过激 →大量短连接→ TCP 四次挥手后进入 TIME_WAIT → TIME_WAIT 堆积 →端口耗尽简单回顾一下 TCP 的 TIME_WAIT 机制主动关闭连接的一方会进入 TIME_WAIT 状态默认持续2 × MSL通常 60 秒。在这段时间内这个端口是不可复用的。所以短连接越多TIME_WAIT 堆积越严重。优化方案调整后的 Redis 客户端配置RdbClient redis.NewClient(redis.Options{ Addr: host : port, Password: pass, DB: db, PoolSize: poolSize, // 可配置按实际负载调整 MinIdleConns: 0, // 不强制维护空闲连接 ConnMaxIdleTime: idleTimeout, // 空闲连接超时释放 MaxActiveConns: poolSize * 2, // 限制最大活跃连接数 MaxConcurrentDials: 10, // 限制并发建连数 })逐项说明参数调整内容目的PoolSize固定值 → 可配置变量根据业务实际并发量灵活调整MinIdleConns10 → 0避免维护不必要的空闲连接减少资源浪费ConnMaxIdleTime无 →idleTimeout让空闲连接有序超时释放而非突然被回收后又立即重建MaxActiveConns无 →poolSize * 2给活跃连接加上天花板防止突发流量下无限制创建新连接MaxConcurrentDials无 → 10限制并发建连的协程数避免瞬间大量 dial 造成系统抖动关键思路就是提高连接复用率减少短连接的产生。效果优化上线后TIME_WAIT 连接数明显下降并趋于稳定端口耗尽的问题不再出现。小结几个 takeawayRedis 连接池的PoolSize一定要根据实际并发量合理设置不要拍脑袋给个固定小值MinIdleConns和MaxIdleConns配置不当会导致连接频繁创建销毁反而得不偿失别忘了配置ConnMaxIdleTime让空闲连接的回收有章可循MaxActiveConns可以作为最后一道防线防止连接数失控遇到端口耗尽问题先用netstat看 TIME_WAIT 数量往往就能找到方向