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

相关推荐
甄同学5 分钟前
第十七篇:Bash Executor命令执行器,安全运行Shell命令
开发语言·安全·bash
张3236 分钟前
Go语言基础 Map 函数值 闭包
开发语言·golang
范闲8 分钟前
第三章: 从 ChatModel 到 Agent:Octo 项目的架构演进
后端
江华森9 分钟前
深入理解 Flask 实现原理
后端·python·flask
Nturmoils16 分钟前
LEFT JOIN 到底什么时候会被优化器偷偷改写成 INNER JOIN
后端
杜子不疼.27 分钟前
【C++ 在线五子棋对战】- 会话管理模块实现
开发语言·c++
有点。31 分钟前
C++深度优先搜索(DFS)的概念(一)
开发语言·c++·深度优先
时间的拾荒人36 分钟前
C语言编译与链接:从源码到可执行程序的完整解析
c语言·开发语言
人道领域38 分钟前
【0-1的agent进阶篇】Prompt 与上下文工程
java·开发语言·prompt·mcp
aaPIXa62239 分钟前
C++大型项目模块化拆分实战记录
开发语言·c++