GO PPROF 协程泄漏分析

代码模拟一个协程泄漏
package main

import (
    "fmt"
    "net/http"
    _ "net/http/pprof"
    "os"
    "runtime"
    "runtime/trace"
    "time"
)

func main() {
    f, err := os.Create("trace.out")
    if err != nil {
        panic(err)
    }
    defer f.Close()
    err = trace.Start(f)
    if err != nil {
        panic(err)
    }
    defer trace.Stop()
    runtime.GOMAXPROCS(1)
    runtime.SetMutexProfileFraction(1)
    runtime.SetBlockProfileRate(1)
    registerProf2()
    Goroutine{}.makeG()
}

func registerProf2() {
    port := ":8060"
    go func() {
        err := http.ListenAndServe(port, nil)
        if err != nil {
            panic("pprof start error" + err.Error())
        }
    }()
}

type Goroutine struct {
}

func (g Goroutine) makeG() {
    for {
        time.Sleep(1 * time.Second)
        go func() {
            fmt.Println("make go")
            time.Sleep(10 * time.Second)
            fmt.Println("end go")
        }()
    }
}
使用pprof分析协程信息
go tool pprof -http=:8080 http://localhost:8060/debug/pprof/goroutine

从火焰图或者graph上看协程阻塞原因,使用top查看协程对多的函数

使用trace 工具工具
go tool trace trace.out

可以看到协程阻塞的位置

协程泄漏原因

以下是定位和解决 Go 协程泄漏(Goroutine Leak)问题的系统性方法和工具指南:


一、协程泄漏的常见原因

场景 示例
阻塞的 Channel 操作 协程因等待未关闭或未发送的 Channel 而永久挂起
死循环未设退出条件 for {}select {} 缺少终止逻辑
未正确使用 Context 超时 未设置 context.WithTimeout 导致协程无法被取消
同步原语误用 sync.WaitGroupAddDone 不匹配,或 Mutex 未释放
第三方库/框架未释放资源 HTTP 长连接、数据库连接池未关闭

results matching ""

    No results matching ""