一起 goroutine 泄漏问题的排查

本文讲述了在Go语言中遇到的一次goroutine泄漏问题,通过对SSH服务的深入分析,发现了由于TCP连接的半打开状态和SSH握手阻塞导致的资源泄漏。通过启用KeepAlive、调整SSH握手超时等措施,成功解决了问题,强调了合理管理goroutine生命周期的重要性。
摘要由CSDN通过智能技术生成

作者: yanhengwang,腾讯 PCG 开发工程师

在 golang 中创建 goroutine 是一件很容易的事情,但是不合理的使用可能会导致大量 goroutine 无法结束,资源也无法被释放,随着时间推移造成了内存的泄漏。避免 goroutine 泄漏的关键是要合理管理 goroutine 的生命周期,通过导出 runtime 指标和利用 pprof 可以发现和解决 goroutine 泄漏问题。

笔者维护了一个通过 SSH 连接到目标机器并执行命令的服务,这是一个内部小服务,平时没有问题的时候一般也不会关注。大约 4 个月前,最后一次更新的时候,增加了一个任务计数器并且导出到 prometheus 中监控起来。近期发现这个计数器在稳步增加。

第一反应是,好事!调用量稳步增长了!!但是一想不对啊,这内部小服务哪儿来这么多调用量。于是再看看 goroutine 的监控情况(这个数据从 runtime.NumGoroutine()获取的)

goroutine 的数量也是稳步增加的,单位时间请求量增加,goroutine 数量也增进,没毛病。但是又再转念一想,内部小服务,不可能不可能。

于是再看一下所有请求在 mm 系统的视图:

可以看出,每 5 分钟请求量在 2000 左右,平均下来每分钟 400 的请求量,上面 prometheus 监控图中,每个曲线是一个实例,实际上部署了 4 个实例,因此 400 还要除以 4 得到单个实例(曲线)的请求量应该在 100/min 左右,在服务刚启动的时候该计数器也确实在 100/min 左右,随着时间推移慢慢泄漏了。

Goroutine 泄漏 (Goroutine leak)

虽然心里想着 99%是泄漏了,但是也要看点详细的信息。之前在服务里已经启用了 net/http/pprof,因此直接请求 pprof 暴露出来的 HTTP 接口。

# goroutines摘要
curl http://service:port/debug/pprof/goroutine?debug=1
# goroutines详情
curl http://service:port/debug/pprof/goroutine?debug=2

先看一下导出的 goroutine 摘要:

有 1000+个 goroutine 处于同一个状态,简单看是等待读数据,再看下导出的 goroutine 详情:

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内存泄漏是指在程序执行过程中,动态分配的内存没有被正确释放,导致内存空间被占用并无法再被重复利用的问题。内存泄漏问题排查是找出造成内存泄漏的代码和地方。 在C++中,我们可以通过重载malloc函数来帮助排查内存泄漏问题。malloc函数用于分配内存空间,我们可以自定义一个重载函数,在该函数中添加一些记录和追踪内存分配的操作。 我们可以重载malloc函数来统计分配的内存大小和数量,并将分配的内存记录到一个容器中。可以使用一个全局的哈希表或者链表,每次调用重载的malloc函数时,记录下分配的内存大小和指针地址。当程序结束时,可以输出这个容器中的信息,包括每个分配的内存的大小和对应的指针地址。 通过重载malloc函数,我们可以很容易地定位到哪些地方分配内存后没有及时释放。我们可以在程序中的一些重要位置,比如函数或循环的入口和出口,输出当前的内存分配信息。通过对比入口和出口处的内存分配信息,可以找出内存泄漏的位置。 当然,重载malloc函数仅仅是一种辅助手段,它依赖于程序员的使用和分析。在使用malloc函数时,程序员需要有意识地进行内存的释放操作。只有当程序员规范使用malloc函数,并且及时释放内存时,才能避免内存泄漏问题的发生。 总之,通过重载malloc函数,我们可以在程序运行过程中动态地追踪内存分配的情况,并辅助排查内存泄漏问题。但是,重载malloc函数并不能完全解决内存泄漏问题,程序员仍然需要注意内存的释放操作,以避免内存泄漏的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值