爱上开源之golang入门至实战第三章 - goroutine分析
Goroutine
Pprof中的Goroutine是对当前时间点的goroutine(协程)数据的采样,我们经常使用pprof对可能发送goroutine(协程)泄漏的可能点进行分析;goroutine(协程)泄漏是goroutine启动之后没有退出导致goroutine的数量不会减少,或者是在实际应用中goroutine占用了很长时间才退出导致在一段时间内goroutine的数量急剧上升; 虽然goroutine(协程)相对于线程的开销来说更加的轻量级,但是对于一个高并发的对性能要求比较高的系统,一样会由于协程的持续无谓的开销而导致整体性能的降低;甚至更严重的由于协程不断的增加,最后由于资源不够充足而无法进行分配,导致整个系统宕机。
我们还是先一起来看看;pprof提供出来的goroutine是怎样的采样数据; 如下图所示:
runtime/pprof/pprof.goruntime/pprof/pprof.goprintCountProfile技巧选择一个好的IDE对于语言的学习非常的有作用;golang的IDE,笔者首选intellij公司出品的Idea;Idea功能强大;体验感非常的强;用idea来研究golang的源代码非常的高效
下图为Idea里的源代码片段
技巧在Idea里,输入ctrl+Shift+R就可以出现快捷搜索框,在搜索框里输入pprof.go就可以快速把pprof.go源文件定位出来;在Idea的左下窗口,structure window可以显示出该源文件里定义的Type, 结构体,函数。变量等等;
在源代码窗口里, 点击ctrl同时鼠标移动到函数名上面, 就可以直接看到该函数的具体信息;如果需要进一步查看该函数的实现内容,点击函数名,就可以直接跳转到函数的方法体;通过idea的熟练使用;在查看和分析golang的源代码的,完全可以做到事半功倍
在golang的源代码里,可以看到很多文档或者网上资料都没有见到过的东西;毕竟相对于java或者其他语言;golang还相对年轻;并且由于golang相对于java的优点,更让golang适合去做一些云原生生态里的底仓服务;本身对开发者要求高;涉众没有java那么广泛,生态圈和社区都没有特别全面;一些底仓的东西;有时候我们必须学会去翻源代码已确定实现的细节
下面来看看goroutine pprof中使用
goroutine: Stack traces of all current goroutines
所以首先要明确的就是; goroutine pprof是程序栈里当前的所有协程; 这里强调的当前的;即这个也是一个快照量;反映的是当前采集时间点上的协程状况
Goroutine的手工埋点
StartCPUProfileWriteHeapProfilego tool pprof goroutine-prof-1下面通过一个实例,来演示一下goroutine pprof分析; 演示程序在主协程里启动多个协程,协程在收到指定的通道信号后,退出协程;没有收到通道的退出信号前;协程处于阻塞状态;然后在主协程里,进行goroutine采样; 采样结束后;往指定的通道发送退出信号;子协程全部退出后,在主协程再次进行goroutine采样;
代码如下
技巧golang具有多并发编程的良好基因, 通过上面的go func(){}的方式,就可以非常方便的启动一个比线程轻量很多的routine; 同时通过chan的实现; 进行不同routine里的消息通信;通过WaitGroup的方式实现主子协程同步的操作
goroutine-prof-1goroutine-prof-2goroutine-prof-1goroutine-prof-2通过pprof对采样数据进行分析
执行Top命令
Showing nodes accounting for 102, 100% of 102 total此时共有102个协程
其中
查看第一行的101个协程的具体调用栈信息
charpter-01.TestGoroutinePprof.func1.1runtime.main具体查看100个协程的相关源头
在第一个分析段落里,我们共看到了102个协程,以上由我们的测试代码已经找到了101个协程的来历; 还有一个在哪里呢?
继续分析;找到第一个分析段落里的1个协程的
traces runtime_goroutineProfileWithLabels
通过这里可以看到,是在我们执行routine采样的代码,产生了一个新的协程
list runtime_goroutineProfileWithLabels在这里启动了新的协程;
以上是对第一个采样点的分析;第一个分析点,是在退出信号没有发出的时候,进行采样的,我们创建的100个协程都没有退出; 下面来看看第二个分析点,第二个分析点,是在主协程已经给所有的子协程发出退出信号后,并且等待并确保所有100子协程都全部退出后,在主协程里进行goroutine采样;
通过pprof对第二个采样数据进行分析
执行Top命令
Showing nodes accounting for 2, 100% of 2 total此时共有2个协程
其中
按照第一轮的分析方法;我们可以看到一个是主协程,一个是采样数据的新启动的协程
使用图形化web命令进行分析
在pprof的交互模式里输入web命令
下图为第一次采样点对应的图形化
下图为第二次采样点对应的图形化
图形化的结果很直观,和trace的结果是一致的; 在无法安装图形化的情况下;可以通过traces来查看类似图形调用树的结果
使用traces命令查看采样数据
通过pprof我们进行goroutine的分析;本文中的例子;仅仅是笔者用来演示分析过程只用, 在项目过程中,都是通过压力测试的场景下,查看goroutine的资源情况,然后采样,在进行分析数据; 用以上的分析过程,同样的适用于这样的场景。