线上Go服务内存每天稳定涨200MB,两周从2G涨到5G,最后OOM被系统杀了。
排查4小时,用pprof一查:goroutine数量从启动时的50涨到5000+,全堆在HTTP调用那块。一看代码,resp,err:=http.Get(url)调完没关resp.Body!
Go的HTTP响应体如果不Close,底层的TCP连接就不会归还连接池,goroutine就一直在那等着,内存越积越多。
解决方案,确保每次都defer关闭:
resp,err:=http.Get(url)
iferr!=nil{
returnerr
}
deferresp.Body.Close()
body,_:=io.ReadAll(resp.Body)
更严谨的写法,自定义Transport控制连接池:
client:=&http.Client{
Transport:&http.Transport{
MaxIdleConns:100,
MaxIdleConnsPerHost:10,
IdleConnTimeout:90*time.Second,
},
Timeout:10*time.Second,
}
还得加govet和staticcheck到CI,漏写deferio.Closer的代码直接拦截。
这个坑太经典了,你写过忘记Close的代码吗