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

 更新时间:2024年01月19日 09:37:40   作者: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,泄漏的问题得到了解决。

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

总结

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

相关文章

  • Golang数据类型比较详解

    Golang数据类型比较详解

    这篇文章主要围绕Golang数据类型比较详细展开,文中有详细的比较过程,需要的朋友可以参考一下
    2023-04-04
  • Go语言学习之接口类型(interface)详解

    Go语言学习之接口类型(interface)详解

    接口是用来定义行为的类型,定义的行为不由接口直接实现,而由通过方法由定义的类型实现,本文就来和大家详细讲讲Go语言中接口的使用吧
    2023-03-03
  • go goroutine 怎样进行错误处理

    go goroutine 怎样进行错误处理

    在 Go 语言程序开发中,goroutine 的使用是比较频繁的,因此在日常编码的时候 goroutine 里的错误处理,怎么做会比较好呢,本文就来详细介绍一下
    2021-07-07
  • Go实现跨平台的蓝牙聊天室示例详解

    Go实现跨平台的蓝牙聊天室示例详解

    这篇文章主要为大家介绍了Go实现跨平台的蓝牙聊天室示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 使用Go语言提高图片分辨率的方法与实践

    使用Go语言提高图片分辨率的方法与实践

    在图像处理和计算机视觉领域,提高图片分辨率是一个常见的问题,随着高分辨率显示设备的普及,如4K、8K电视以及高像素手机摄像头的应用,用户对高质量图片的需求也越来越高,本文将介绍使用Golang语言提高图片分辨率的方法与实践,需要的朋友可以参考下
    2023-12-12
  • Go Gin框架优雅重启和停止实现方法示例

    Go Gin框架优雅重启和停止实现方法示例

    Web应用程序中,有时需要重启或停止服务器,无论是因为更新代码还是进行例行维护,这时需要保证应用程序的可用性和数据的一致性,就需要优雅地关闭和重启应用程序,即不丢失正在处理的请求和不拒绝新的请求,本文将详解如何在Go语言中使用Gin这个框架实现优雅的重启停止
    2024-01-01
  • Go语言函数的延迟调用(Deferred Code)详解

    Go语言函数的延迟调用(Deferred Code)详解

    本文将介绍Go语言函数和方法中的延迟调用,正如名称一样,这部分定义不会立即执行,一般会在函数返回前再被调用,我们通过一些示例来了解一下延迟调用的使用场景
    2022-07-07
  • golang 如何用反射reflect操作结构体

    golang 如何用反射reflect操作结构体

    这篇文章主要介绍了golang 用反射reflect操作结构体的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • golang中对

    golang中对"引用传递"的误解

    这篇文章主要介绍了golang中对“引用传递”的误解,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • Ruby序列化和持久化存储(Marshal、Pstore)操作方法详解

    Ruby序列化和持久化存储(Marshal、Pstore)操作方法详解

    这篇文章主要介绍了Ruby序列化和持久化存储(Marshal、Pstore)操作方法详解,包括Ruby Marshal序列化,Ruby Pstore存储,需要的朋友可以参考下
    2022-04-04

最新评论