个人随记 —— 记录一次服务链接泄露路程
问题描述
该团队最近一次发布后,pod 一天会重启40次左右,时间间隔固定,代码回退后发现依旧会有重启,跟发布前一样,但是时间间隔较长。
问题分析
出现该问题,说明程序有一定的 BUG,一般来说是内存泄露可能性较多,积累到一定阈值后,便会发生 oom 导致重启。
通过监控发现在有问题的版本中内存确实积累过快导致 OOM,但是其他版本中其实没有达到阈值 2G 就发生了 crash,这说明应该不是业务内部内存导致使用的问题,大概率是文件 IO 或者网络 IO 异常导致的,沟通了解到该团队没有什么读文件操作,所以问题锁定在网络 IO 这方面。
通过命令,发现连接数确实有异常
netstat -anp | awk '{print $5}' | sort | uniq -c | sort -r
那么问题就定位在是 io 没有及时回收导致的。
了解到团队是使用的 go http client,这边了解到业务中会每次新建 client 来进行访问请求,这边咨询了当前 http client 的配置,只配置简单的接口超时时间为 30s,但是客户端默认配置中是使用长连接方式的,加上服务端也是使用长连接方式,所以导致了这次问题。
问题临时解决方案
通过设置 disableKeepalives 参数为 true,先禁用长连接方式,保证连接可以回收,配置后问题得到环境,连接数一直保持稳定的数量,且状态会变更为 TIME_WAIT 状态。
问题根本解决方案
代码上进行优化,复用 client,且配置好最大连接数,idle 超时时间等配置,从根本上解决问题。