• goroutine泄漏检测神器goleak


    goroutine泄漏检测神器---goleak
    在日常开发中,go 出去的goroutine通常伴随着死循环,这些goroutine可能处于阻塞状态,一直运行,直到进程结束。

    对于线上服务来说,一直是在运行的,除非panic重启等,不然一旦出现goroutine泄漏,资源被一直占用,cpu/内存将会直线陡增,对于线上服务影响巨大,通常出了问题,可以采用pprof来进行分析,日常开发中,如果能做到边开发,边检测出这种泄漏问题,将会非常有用,这里便会引用到了goroutine离线检测工具:goleak。

    1.使用
    func TestA(t *testing.T) {
    defer goleak.VerifyNone(t)

    // test logic here.
    }
    在进行单元测试时可以直接使用,非常方便。

    例如:下面是有异常的goroutine,使用goleak检测的结果:

    found unexpected goroutines:
    [Goroutine 23 in state chan receive, with go.uber.org/goleak.TestIgnoreCurrent.func2.1 on top of the stack:
    goroutine 23 [chan receive]:
    go.uber.org/goleak.TestIgnoreCurrent.func2.1(0xc000118c60)
    /go_proj/goleak/leaks_test.go:111 +0x34
    created by go.uber.org/goleak.TestIgnoreCurrent.func2
    /go_proj/goleak/leaks_test.go:110 +0x11d
    ]
    2.原理
    像这种检测工具具体怎么实现的呢?比较好奇,就阅读了一下源码,发现源码非常的少,里面有很多技巧与学习的东西。

    第一个点:如何检测?

    这里的检测是尝试20次,每次最大时间睡眠100ms(允许耗时的goroutine运行)。每次检测过程为:过滤掉传入的goroutine,通过runtime.Stack获取到各种状态的goroutine,20次之后如果还有剩余的goroutine,那么就是有问题的,输出出来就好了。

    内部实现的一些技巧:

    过滤函数

    对外暴露IgnoreTopFunction接口允许传入goroutine关键字符串,内部会去做匹配,用户不用关心细节,内部函数作为参数,调用addFilter,还支持传入当前goroutine,调用IgnoreCurrent。

    func IgnoreTopFunction(f string) Option {
    return addFilter(func(s stack.Stack) bool {
    return s.FirstFunction() == f
    })
    }
    func IgnoreCurrent() Option {
    excludeIDSet := map[int]bool{}
    for _, s := range stack.All() {
    excludeIDSet[s.ID()] = true
    }
    return addFilter(func(s stack.Stack) bool {
    return excludeIDSet[s.ID()]
    })
    }
    func addFilter(f func(stack.Stack) bool) Option {
    return optionFunc(func(opts *opts) {
    opts.filters = append(opts.filters, f)
    })
    }
    获取所有goroutine的栈信息

    内部通过定义stack结构体,创建私有的getStacks进行解析,getStacks会解析出多个stack结构,内部实现原理为读取runtime.Stack的所有goroutine信息。

    // Stack represents a single Goroutine's stack.
    type Stack struct {
    id int
    state string
    firstFunction string
    fullStack *bytes.Buffer
    }
    最后,会获取到每个goroutine的id、状态、函数名,栈信息。
    ————————————————
    版权声明:本文为CSDN博主「guangcheng0312q」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/guangcheng0312q/article/details/125326007

  • 相关阅读:
    JAVA学习日报 8.26
    JAVA学习日报 8.25
    JAVA学习日报 8.24
    JAVA学习日报 8.23
    Docker 详解
    DRF 3 请求响应异常处理
    DRF 2 序列化器
    DRF 1 API接口规范
    计算机计算小数的方法
    软件结构体系第二章
  • 原文地址:https://www.cnblogs.com/ExMan/p/16612988.html
Copyright © 2020-2023  润新知