公司一个同事使用 Go Websocket 开发了 k8s 在线调试服务,该服务也部署在 k8s 集群中,没几天运维那边通告说 cpu 100% 高负载了,还把限制的范围内的 cpu core 都干满了。由于那人休假,我帮忙处理下。
通常来说这类 cpu 高负载的问题相对好排查,多是 bug 造成的。像这个调试服务在一个量级请求完毕后,cpu 使用率居然还是爆满。???? 不用想,肯定是协程泄露了,造成了某个逻辑的忙轮询。
该服务在 k8s 集群中部署,没有接入 ingress,所以在有外网的 k8s node 上做了一个端口映射。这样开发机就可以 go tool pprof 外网地址。
还有一个好方法是我以前常用的,在 k8s node 上把 golang 的 pprof 可分析数据导入到文件里,然后把文件 post 到一个支持上传的服务,比如 http upload,后面大家就知道该怎么操作了。
下面是pprof生成的火焰图和调用链耗时图,很明显的看到 writeLoop 不断的调用 Close() 方法。
既然确定了问题,通过 pprof source 定位热点代码,为什么会不断调用 wsConn.Close()
呢 ?因为没有 return,既然已感知连接关闭,那么就应该 return 出去!!!
// xiaorui.cc
Total: 2.31s 1.35mi