GoLang net/http内存不断增加的连续请求

qpgpyjmq  于 2023-02-14  发布在  Go
关注(0)|答案(1)|浏览(418)

我在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处理多个请求,但它看起来仍然像是增加了内存占用的大小。

to94eoyn

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?

相关问题