HTTP重用连接条件

时间:2017-06-25 14:32:23

标签: go tcp connection keep-alive

从官方文档https://golang.org/pkg/net/http/#Client.Do来看,似乎RoundTripper 可能无法为下一个" keep-alive"重新使用TCP连接。请求Body是否未关闭且未完全阅读。这可能的内容是什么?

从我看到的内容当读取整个Body时,不一定需要调用Close。那么连接重用的必要条件是什么?

代码片段(注释为defer resp.Body.Close()),它在循环中创建多个连接,并通过netstat分析它,似乎所有连接都使用相同的TCP连接:

for nextPage != "" {
    req, err := http.NewRequest("GET", nextPage, nil)
    req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *token))
    if err != nil {
        panic(err)
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    // defer resp.Body.Close()
    result := []*User{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        panic(err)
    }

    nextPage = getNextPage(resp.Header.Get("Link"))
}

2 个答案:

答案 0 :(得分:0)

文件没有说Don't call Close() for keep-alive。只需说if you want to re-use connection, you MUST call Close() and fully read.

答案 1 :(得分:0)

您只能依靠文档中的内容。在某些情况下(转换版本,操作系统,体系结构,响应内容长度等),可能重用连接而不完全读取它,或者它可能不会。如果你想确保连接将被重用,你必须完全读取正文并关闭它。

我通常写一个快速帮手:

func cleanUpRequest(req *http.Request) {
    if req != nil && req.Body != nil {
        io.Copy(ioutil.Discard, req.Body)
        req.Body.Close()
    }
}

即使在错误检查之前,这对defer也是安全的。