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利用率下降,之后继续观察线上问题是否彻底缓解

相关推荐
pumpkin8451419 分钟前
01 Coze Studio项目中所有关键术语的详细解释和代码示例
golang
code_li26 分钟前
聊聊支付宝架构
java·开发语言·架构
少控科技1 小时前
QT高阶日记01
开发语言·qt
无限进步_1 小时前
【C++】大数相加算法详解:从字符串加法到内存布局的思考
开发语言·c++·windows·git·算法·github·visual studio
“抚琴”的人1 小时前
C#上位机工厂模式
开发语言·c#
巨大八爪鱼1 小时前
C语言纯软件计算任意多项式CRC7、CRC8、CRC16和CRC32的代码
c语言·开发语言·stm32·crc
C+-C资深大佬1 小时前
C++ 数据类型转换是如何实现的?
开发语言·c++·算法
木千2 小时前
Qt全屏显示时自定义任务栏
开发语言·qt
小马爱打代码2 小时前
SpringBoot:封装 starter
java·spring boot·后端
2501_944424122 小时前
Flutter for OpenHarmony游戏集合App实战之俄罗斯方块七种形状
android·开发语言·flutter·游戏·harmonyos