golang内存泄漏排查

golang做为一种自带gc(garbage collection)回收机制的语言,往往可能会给人一种错觉,用golang写的程序一般不会存在内存泄漏(因为golang自带的GC会将不用的内存回收掉),实则不然。在实际开发的过程中,出现最多的一种情况是goroutine泄漏造成的内存泄漏,这里重点说怎么排查roroutine泄漏。由于公司对云服务部署的软件有严格的安全要求,直接使用net/http/pprof模块,可能会有安全方面的漏洞,这里先说下怎么在公网使用pprof规避安全漏洞:

// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package pprof serves via its HTTP server runtime profiling data
// in the format expected by the pprof visualization tool.
//
// The package is typically only imported for the side effect of
// registering its HTTP handlers.
// The handled paths all begin with /debug/pprof/.
//
// To use pprof, link this package into your program:
// import _ "net/http/pprof"
//
// If your application is not already running an http server, you
// need to start one. Add "net/http" and "log" to your imports and
// the following code to your main function:
//
//     go func() {
//        log.Println(http.ListenAndServe("localhost:6060", nil))
//     }()
//
// If you are not using DefaultServeMux, you will have to register handlers
// with the mux you are using.
//
// Then use the pprof tool to look at the heap profile:
//
// go tool pprof http://localhost:6060/debug/pprof/heap
正如net/http/pprof/pprof.go中上面我标准红色字体的所说,不指定http的mux,则pprof会使用默认的DefaultServerMux,如果其他做业务的HTTP也没有使用自己的mux,则使用的也是DefaultServerMux,这样及时pprof监听的IP地址是127.0.0.1,也可能存在安全漏洞,示例如下:
pprof监听的IP地址和端口:
go func() {
   pprofHttp.ListenAndServe("localhost:50000", nil)
}()

真正做业务的HTTP服务监听的接口和端口:

func HelloHandler(w http.ResponseWriter, r *http.Request) {
   fmt.Fprintf(w, "Hello World")
}

func main () {
   http.HandleFunc("/", HelloHandler)
   http.ListenAndServe(":8000", nil)
}

假设该软件部署的公网IP地址为:49.215.92.3

则在浏览器上输入:https://49.215.92.3/debug/pprof/,就会看到程序对应的各种信息,比如:所有的goroutine等堆栈信息。公司的安全扫描软件扫到,就会找到你,让你修复这个安全漏洞(如果有些公司对安全不重视,可以忽略该问题)。

要些解决解决这个漏洞,可以将做业务的Http接口改为:

func HelloHandler(w http.ResponseWriter, r *http.Request) {
   fmt.Fprintf(w, "Hello World")
}

func main () {
   mux := http.NewServeMux()
   mux.handle("/", http.HandleFunc(HelloHandler))
   http.ListenAndServe(":8000", nil)
}

这样在浏览器上输入:https://49.215.92.3/debug/pprof/,会提示404,安全漏洞得以解决:

排查goroutine泄漏可以在服务器后台使用命令行:

curl http://localhost:50000/debug/pprof/goroutine?debug=2 > xxxGoroutine.out,这样所有的goroutine堆栈信息都会写到.out文件中,看看那些goroutine阻塞的时间比较长,再结合业务,就会查找到有哪些goroutine泄漏。

 
 

你可能感兴趣的:(golang,程序内存及性能,golang)