golang 调试
debug 接口的方式适用于 集成测试 ,因为测试用例和目标服务不在同一个进程里,需要 dump 目标进程的 goroutine stack 来获取泄漏信息。
goroutine stack 通常第一行包含着 Goroutine ID,接下来的几行是具体的调用栈信息。有了调用栈信息,我们就可以通过 关键字匹配 的方式来检索是否存在泄漏的情况了。
获取调试信息数据
找到go pprof对应的端口:
"prof": "17020",
docker下的映射:
0.0.0.0:43785->17020/tcp docker_master2_1
curl "127.0.0.1:43785/debug/pprof/goroutine?debug=1" > 1.out
curl "127.0.0.1:43785/debug/pprof/goroutine?debug=2" > 1.log
分析与示例
sync.runtime_SemacquireMutex 这一行就是告诉你,这个goroutine,当前正在等待获取锁,
而后面的调用栈,会告诉你,哪里正在等待锁,
出现sync.runtime_SemacquireMutex并不一定是死锁或者长时间锁等待,
可能只是你的脚本请求页面的那个时刻刚好有锁处于等待状态,但这个锁可能马上就被获取到了,这其实是非常正常的
v.go:135::getID:v.mpsLock.RLock()
1 @ 0x43c20f 0x44c609 0x44c5df 0x44c37d 0x7feac9 0x7fe9d1 0x7eb5c6 0x7ff5e6 0x7b8575 0x804a91 0x469581
#0x44c37c sync.runtime_SemacquireMutex+0x3c /usr/local/go/src/runtime/sema.go:71
#0x7feac8 sync.(*RWMutex).RLock+0x128 /usr/local/go/src/sync/rwmutex.go:50
#0x7fe9d0 github.com[go文件路径].(*Vol).getID+0x30 /go/src/github.com[go文件路径]/v.go:135
#0x7eb5c5 github.com[go文件路径].(*MetaPartition).checkEnd+0xd5 /go/src/github.com[go文件路径]/m.go:191
#0x7ff5e5 github.com[go文件路径].(*Vol).checkM+0x215 /go/src/github.com[go文件路径]/v.go:235
#0x7b8574 github.com[go文件路径].(*Cluster).checkM+0xd4 /go/src/github.com[go文件路径]/c.go:344
#0x804a90 github.com[go文件路径].(*Cluster).startCheckM.func1+0x70 /go/src/github.com[go文件路径]/c.go:327
调用栈,最上面的getID是栈顶,
所以调用逻辑是从下往上看
参考:https://blog.csdn.net/u013536232/article/details/107868474
grep “semacquire” 1.log | awk -F ‘,’ ‘{print $2}’ | awk ‘{print $1}’ | sort -rn | more