go 1.18.1
pprof报告
3549.93kb 49.73% 49.73% 3549.93kb 49.73% src/lag_monitor.publishlagmetrictodatadog
514kb 7.20% 56.93% 514kb 7.20% bufio.newwritersize
512.88kb 7.18% 64.11% 512.88kb 7.18% encoding/pem.decode
512.69kb 7.18% 71.30% 1536.98kb 21.53% crypto/x509.parsecertificate
512.50kb 7.18% 78.48% 512.50kb 7.18% crypto/x509.(*certpool).addcert
这段代码似乎没有释放内存,根据pprof,下面的函数是消耗内存最多的函数。内存图
func caller() {
events := make([]string, 0)
//....
PublishLagMetricToDataDog(ctx, strings.Join(events, ","))
}
func PublishLagMetricToDataDog(ctx context.Context, events string) error {
msg := `{
"series": [%v]
}`
b := []byte(msg)
resp, err := http.Post("https://api.datadoghq.com/api/v1/series?api_key="+env.GetDataDogKey(), "application/json", bytes.NewBuffer(b))
if err != nil {
logger.Error(ctx, "Error submitting event to datadog, err = ", err)
return err
}
logger.Info(ctx, resp)
return nil
}
上面的函数是在循环中调用的。由于没有全局变量,也没有对 publishlagmetrictodatadog 中的字节切片的引用,因此我无法查明内存泄漏。我读到了有关 reset() 和 truncate() 的内容,但这不会释放底层内存。
正确答案
您必须关闭收到的每个 http 响应的响应正文。不这样做可能会导致资源泄漏,就像您所观察到的那样。
解决方案:
resp, err := http.Post("https://api.datadoghq.com/api/v1/series?api_key="+env.GetDataDogKey(), "application/json", bytes.NewBuffer(b))
if err != nil {
logger.Error(ctx, "Error submitting event to datadog, err = ", err)
return err
}
logger.Info(ctx, resp)
_ = resp.Body.Close() // <--- Add this
return nil
}