Golang协程泄漏定位和排查
- 1 场景:无缓冲channel写阻塞
- 2 排查和定位思路
- 2.1 Golang pprof
- 2.2 协程数监控
- 2.3 操作系统内存泄漏
- 参考
1 场景:无缓冲channel写阻塞
package mainimport ("log""net/http"_ "net/http/pprof""time""github.com/gin-gonic/gin"
)func main() {go func() {log.Println(http.ListenAndServe("localhost:6060", nil))}()// 你的程序逻辑...g := gin.Default()g.GET("/hello", func(ctx *gin.Context) {ch := make(chan bool)go func() {time.Sleep(2 * time.Second)ch <- true}()select {case <-ch:breakcase <-time.After(time.Second):break}ctx.JSON(200, map[string]interface{}{"success": true,})})g.Run("127.0.0.1:8080")}
2 排查和定位思路
2.1 Golang pprof
stack和数量check匹配
2.2 协程数监控
在Golang中,可以使用runtime包的函数来监控和获取Goroutines的相关信息,如:
runtime.NumGoroutine():获取当前系统中的Goroutines数量
runtime.Gosched():主动让出CPU,让其他Goroutine运行
runtime.GOMAXPROCS():设置同时运行的最大CPU数量
2.3 操作系统内存泄漏
ePBF
# -a 表示显示每个内存分配请求的大小以及地址
# -p 指定案例应用的PID号
$ docker cp app:/app /app
$ /usr/share/bcc/tools/memleak -p $(pidof app) -a
Attaching to pid 12512, Ctrl+C to quit.
[03:00:41] Top 10 stacks with outstanding allocations:addr = 7f8f70863220 size = 8192addr = 7f8f70861210 size = 8192addr = 7f8f7085b1e0 size = 8192addr = 7f8f7085f200 size = 8192addr = 7f8f7085d1f0 size = 819240960 bytes in 5 allocations from stackfibonacci+0x1f [app]child+0x4f [app]start_thread+0xdb [libpthread-2.27.so]
参考
1 Go 项目中的 Goroutine 泄露及其防范措施
2 案例篇:内存泄漏了,我该如何定位和处理?
3 golang并发编程实践之goroutines的监控与调试技巧
4 go pprof 性能分析
5 Golang 内存泄漏详解:原因、检测与修复