Go pprof 快速分析 CPU 高负载问题
公司一個同事使用 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.ccTotal:???????2.31s???1.35mins?(flat,?cum)?99.25%76????????????.??????????.????????????????}?77????????????.??????????.???????????}?78????????????.??????????.????????????79????????????.??????????.???????????//?發送協程?80????????????.??????????.???????????func?(wsConn?*WsConnection)?wsWriteLoop()?{?81????????330ms??????330ms????????????????defer?fmt.Println("write?exited")?82????????????.??????????.????????????????for?{?83????????740ms???1.05mins????????????????????????select?{?84????????720ms??????730ms????????????????????????case?msg?=?<-wsConn.outChan:?85????????????.??????????.????????????????????????????????if?err?=?wsConn.socket.WriteMessage(msg.MessageType,?msg.Data);?err?!=?nil?{?86????????????.??????????.????????????????????????????????????????log.Error("websocket?write?message?error",?err)?87????????????.??????????.????????????????????????????????}?88????????220ms??????220ms????????????????????????case?<-wsConn.closeChan:?89????????300ms?????16.21s????????????????????????????????wsConn.Close()?90????????????.??????????.????????????????????????}?91????????????.??????????.????????????????}?92????????????.??????????.???????????}相比性能調優,這類由于 bug 引起的 cpu 高負載問題反而特別容易處理,基本上通過 pprof 看火焰圖就可以快速定位問題。
總結
以上是生活随笔為你收集整理的Go pprof 快速分析 CPU 高负载问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 启用读者群
- 下一篇: 推荐一个 Service Mesh 专栏