我在GoLang中有以下代码
package main
import (
"bytes"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"time"
)
func httpClient() *http.Client {
var transport http.RoundTripper = &http.Transport{
DisableKeepAlives: false,
}
client := &http.Client{Timeout: 60 * time.Second, Transport: transport}
return client
}
func sendRequest(client *http.Client, method string) []byte {
endpoint := "https://httpbin.org/post"
values := map[string]string{"foo": "baz"}
jsonData, err := json.Marshal(values)
req, err := http.NewRequest(method, endpoint, bytes.NewBuffer(jsonData))
if err != nil {
log.Fatalf("Error Occurred. %+v", err)
}
resp, err:= client.Do(req)
if err != nil {
defer resp.Body.Close()
log.Fatalf("Error sending request to API endpoint. %+v", err)
}
// Close the connection to reuse it
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Couldn't parse response body. %+v", err)
}
return body
}
func main() {
// c should be re-used for further calls
c := httpClient()
for i := 1; i <= 60; i++ {
response := sendRequest(c, http.MethodPost)
log.Println("Response Body:", string(response))
response = nil
time.Sleep(time.Millisecond * 1000)
}
}
当执行时,它保持内存大小增加,一小时内增长到90mb。gc工作不正常吗?即使我使用相同的httpclient处理多个请求,但它看起来仍然像是增加了内存占用的大小。
1条答案
按热度按时间to94eoyn1#
我建议您使用像 pprof 这样的工具,这些工具在解决这类问题时非常有用。
您已经将
DisableKeepAlives
字段设置为false,这意味着即使在请求发出后,它也会保持打开的连接,从而导致进一步的内存泄漏。您还应该在调用ioutil.ReadAll(resp.Body)
之后调用defer resp.Body.Close()
。这正是defer
关键字的目的-防止内存泄漏。GC并不意味着绝对的内存安全。此外,在main之外避免使用
log.Fatal
。使用分级日志记录器,如zap或zerolog,因为log.Fatal
调用os.Exit(1)
会立即生效,这意味着您的defer
语句将无效,或者调用普通panic
。请参见Should a Go package ever use log.Fatal and when?