Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go使用pprof工具查找goroutine(协程)泄漏

Go语言之使用pprof工具查找goroutine(协程)泄漏

作者:pengpengzhou

这篇文章主要介绍了Go语言之使用pprof工具查找goroutine(协程)泄漏,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

用pprof工具查找goroutine(协程)泄漏

goroutine泄漏指的是goroutine启动之后没有退出导致goroutine的数量持续上升,或者是在实际应用中goroutine占用了很长时间才退出导致在一段时间内goroutine的数量急剧上升。

通常可以采用Go自带的pprof工具来定位问题

如下面这个示例

这是一个简单的HTTP服务,当接收到请求时另起一个goroutine来输出日志,同时返回“Hello, World!\n”。

在记录日志之前可能要处理一个耗时很长的业务逻辑,如通过公网请求第三方的API接口,这里为了简化问题用time.Sleep来示意。

goroutineleak.go

package main
 
import (
	"io"
	"log"
	"net/http"
	_ "net/http/pprof"
	"time"
)
 
func writeLog(msg string) {
	go func() {
		time.Sleep(1 * time.Second)
		log.Println(msg)
	}()
}
func handler(w http.ResponseWriter, r *http.Request) {
	writeLog(r.URL.RequestURI())
	io.WriteString(w, "Hello, world!\n")
}
 
func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

利用Grinder来压测,开8个进程,每个进程开3个线程,同时请求上述服务。

在请求过程中,通过浏览器查看http://pub.pengpengzhou.com:8080/debug/pprof/goroutine?debug=1, 域名是上述服务所在的地址。

从pprof的返回结果中,我们可以看到协程总数是5605,下面列出了5组产生协程的代码stack trace,按产生的协程数量倒排序。

可以看到第一组产生了5597个协程,产生位置在goroutineleak.go的13行“time.Sleep(1 * time.Second)”对应的函数是main.writeLog。

问题很快得到定位,把这一行注释掉,重新再压测,可以得到如下结果, 协程总数一下就降到了8,泄漏的问题得到了解决。

当然,在实际应用中,耗时是不可避免的,通常是用设置超时的办法来规避长时间等待。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文