好物分享:快速找到 Goroutine 泄露的地方
2022-4-18 18:12:0 Author: mp.weixin.qq.com(查看原文) 阅读量:12 收藏

大家好,我是煎鱼。

Go 语言能够广受大家喜欢,其中一个原因就是他的协程做的非常非常简单,初学的入门者都可以使用。

平时只需 go 关键字一下,成千上万个 goroutines 就出现了:

for ...
  go func(){}

起协程就跟下饺子的。这时就个大问题,因为协程用起来简单,出问题出起来也很快。

也就是常常会出现 goroutine 泄露,查起来很费劲。

goleak

今天给大家推荐一个好物,定位为纯介绍。他来自 Uber 的 Goroutine leak detector[1],他能够结合单元测试去快速的检测 goroutine 泄露,达到避免和排查的目的。

在命令行执行第三方库安装:

go get -u go.uber.org/goleak

channel 会一直阻塞,导致泄露的方法:

func leak() {
 ch := make(chan struct{})
 go func() {
  ch <- struct{}{}
 }()
}

如果我们直接在常规的测试方法中调用:

func TestLeak(t *testing.T) {
 leak()
}

输出结果:

=== RUN   TestLeak
--- PASS: TestLeak (0.00s)
PASS

是不会有任何变化的,正常通过测试。

这时候我们需要在代码中添加 goleak.VerifyNone 方法,如下:

import (
 "testing"
 "go.uber.org/goleak"
)

func TestLeak(t *testing.T) {
 defer goleak.VerifyNone(t)
 leak()
}

再进行验证:

=== RUN   TestLeak
    leaks.go:78: found unexpected goroutines:
        [Goroutine 7 in state chan send, with github.com/eddycjy/awesome-project/tools.leak.func1 on top of the stack:
        goroutine 7 [chan send]:
        github.com/eddycjy/awesome-project/tools.leak.func1(0xc0000562a0)
         /Users/eddycjy/go-application/awesomeProject/tools/leak.go:6 +0x35
        created by github.com/eddycjy/awesome-project/tools.leak
         /Users/eddycjy/go-application/awesomeProject/tools/leak.go:5 +0x4e
        ]
--- FAIL: TestLeak (0.46s)
FAIL

可以从报告中看到,运行结构会明确的告诉你发现泄露的 goroutine 的代码堆栈和泄露类型,非常的省心。

另外在内部的 CI/CD 流程里,把 goleak 结合上,对于平时的 CR 也是一个不错的辅助。

总结

今天我们的好物分享介绍了一个小工具,能够解决大家团队中时长遇到的 goroutine 泄露问题,除了本文提到的 uber-go/goleak,也还有 ysmood/gotrace 等同类型的库能够达到类似的效果。

希望对你排查 goroutine 泄露有所帮助:)

参考资料

[1]

Goroutine leak detector: github.com/uber-go/goleak

关注煎鱼,获取业内第一手消息和知识 👇

你好,我是煎鱼,出版过 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,和大家交流!


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxNzY0NDE3NA==&mid=2247489854&idx=2&sn=be0a94de1e8deeb772773e897d01e97e&chksm=9be336dfac94bfc94cb1f0f6b86302c4568c70abee128d56965aebc45486c079c2e9de4c0936#rd
如有侵权请联系:admin#unsafe.sh