我已经建立了一个用Go编写的http服务器,每天有超过数千名访问者。我有一个累积的Goroutine问题(从未被释放)。在一天的过程中,我似乎从http服务器上获得了一万多个新的Goroutines。我使用pprof
来检查问题的来源,我得到了:
Link: memory consumption: SVG pprof
堆:
下面是我的两个goroutines
500 @ 0x410255 0x5a9255 0x5a9e25 0x5aa615 0x5990cf 0x5ada95 0x59d23f 0x4367b1
# 0x5a9255 net._C2func_getaddrinfo+0x55 /usr/local/go/src/net/:26
# 0x5a9e25 net.cgoLookupIPCNAME+0x1c5 /usr/local/go/src/net/cgo_unix.go:96
# 0x5aa615 net.cgoLookupIP+0x65 /usr/local/go/src/net/cgo_unix.go:148
# 0x5990cf net.lookupIP+0x5f /usr/local/go/src/net/lookup_unix.go:64
# 0x5ada95 net.func·026+0x55 /usr/local/go/src/net/lookup.go:79
# 0x59d23f net.(*singleflight).doCall+0x2f /usr/local/go/src/net/singleflight.go:91
157871 @ 0x423985 0x4239f8 0x411464 0x410c93 0x5a9d68 0x5aa615 0x5990cf 0x5ada95 0x59d23f 0x4367b1
# 0x5a9d68 net.cgoLookupIPCNAME+0x108 /usr/local/go/src/net/cgo_unix.go:85
# 0x5aa615 net.cgoLookupIP+0x65 /usr/local/go/src/net/cgo_unix.go:148
# 0x5990cf net.lookupIP+0x5f /usr/local/go/src/net/lookup_unix.go:64
# 0x5ada95 net.func·026+0x55 /usr/local/go/src/net/lookup.go:79
# 0x59d23f net.(*singleflight).doCall+0x2f /usr/local/go/src/net/singleflight.go:91
在这里,我们可以看到 singleflight.go 占用了大部分goroutints,它是Go的本地库。
我的代码在这个函数中被包围了
func getXmlVast(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", errors.New("request error A(" + err.Error() + ")")
}
defer resp.Body.Close()
// read xml http response
xmlData, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", errors.New("request error B(" + err.Error() + ")")
}
return string(xmlData), nil
}
为什么Go永远不会释放goroutines以及 singleflight.go 做什么。
答案 0 :(得分:0)
我将Go版本从1.4更新为1.5,它解决了问题。
我之前做了一些研究以找到问题的来源我注意到很多人都有同样的问题,没有人知道为什么。我认为这个问题出现在http/net
库中因为我说的在我的问题中,充分利用goroutints的函数是单步,这个函数由http.Get(url)
调用