golang协程泄漏排查实战

问题背景

某个周末,线上实例开始偶发cpu利用率到达80%的报警,且当时业务几乎无流量,个别实例的cpu利用率仍居高不下

业务是处理websocket的长连接,在请求结束时会通过channel的关闭事件通知各协程退出

排查过程

  1. 首先通过pprof命令采集了一段时间的cpu时间的占用情况,发现大量时间被运行时的协程调度占用,但当时已无流量,所以这种占用情况是不符合预期的
  2. 通过以下命令拉取当时存活的协程
bash 复制代码
curl http://localhost:6790/debug/pprof/goroutine?debug=2 > goroutines.txt
less goroutines.txt
grep yourFunc goroutines.txt

详细的pprof命令可以参考这里

分析过程

其中存活的协程分为以下两部分

  1. hertz, mertrics这些长期存活的和服务监听或者是监控上报有关,本身监控或者对端口的监听会持续存在,这部分没问题。
  2. 另一部分是少量的业务处理过程中开辟的协程,这部分应该随着请求的结束而推出,但实际并没有,问题看来就出现在了这里,因为大量协程没有退出导致调度成本越来越大

解决方案

当前程序对于开辟的协程管理十分不严谨,是通过在各协程中感知channel的close行为然后自行退出,并且关闭channel的行为仅发生在处理请求的过程中。将其修改为go自带的context管理,感知context的cancel行为,将原来对channel的关闭替换为对cancel的调用,并且在websocket被对端关闭的情况下调用cancel。

上线观察几天后,cpu利用率下降,之后继续观察线上问题是否彻底缓解

相关推荐
To Be Clean Coder2 小时前
【Spring源码】getBean源码实战(一)
java·后端·spring
派大鑫wink2 小时前
【Day21】NIO入门:通道、缓冲区与非阻塞IO基础
java·开发语言
quant_19862 小时前
BTC 行情预警系统实战教程
开发语言·后端·python·websocket·程序人生·金融
世转神风-2 小时前
qt-基础打印-不换行打印
开发语言·qt
DYS_房东的猫2 小时前
学习总结笔记三:让网站“活”起来——处理静态文件、表单验证与用户登录(第3章实战版)
笔记·学习·golang
Ralph_Y2 小时前
C++数据库操作
开发语言·数据库·c++
superman超哥2 小时前
Rust 日志级别与结构化日志:生产级可观测性实践
开发语言·后端·rust·可观测性·rust日志级别·rust结构化日志
每天早点睡2 小时前
continue语句
后端
每天早点睡2 小时前
while语句
后端