是否有必要读取并关闭响应主体以重试 TCP 连接?

我正在使用http.RoundTripperGo 实现重试。这是一个实现示例。


type retryableRoundTripper struct {

    tr            http.RoundTripper

    maxRetryCount int

}


func (t *retryableRoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) {

    for count := 0; count < t.maxRetryCount; count++ {

        log.Printf("retryableRoundTripper retry: %d\n", count+1)

        resp, err = t.tr.RoundTrip(req)


        if err != nil || resp.StatusCode != http.StatusTooManyRequests {

            return resp, err

        }

    }


    return resp, err

}

问题


是否有必要读取并关闭响应主体以重试 TCP 连接?


func (t *retryableRoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) {

    for count := 0; count < t.maxRetryCount; count++ {

        log.Printf("retryableRoundTripper retry: %d\n", count+1)

        resp, err = t.tr.RoundTrip(req)


        if err != nil || resp.StatusCode != http.StatusTooManyRequests {

            return resp, err

        }

    }


    // add

    io.Copy(ioutil.Discard, resp.Body)

    resp.Body.Close()


    return resp, err

}

作为旁注,我编写了一个测试并确认重试按预期工作。(在 Go Playground 中,它超时,但它在本地工作。)


https://play.golang.org/p/08YWV0kjaKr


慕的地6264312
浏览 130回答 1
1回答

慕少森

当然,您需要阅读连接以确保它可以重复使用,并且需要按照文档说明关闭连接。如文档中所述:客户端完成后必须关闭响应正文和如果正文未读完并关闭,则默认 HTTP 客户端的传输可能不会重用 HTTP/1.x “保持活动” TCP 连接。如果服务器想要发送的数据超出初始读取缓冲区的容量,它将被阻止发送响应。这意味着如果传输尝试通过该连接发送新请求,服务器可能无法处理它,因为它从未完成第一个请求。这通常会导致客户端错误connection reset by peer和服务器错误write: broken pipe。如果您想尝试重用连接,但限制读取量,请使用io.LimitedReader和/或检查ContentLength值。这样,当处理错误和建立新连接比读取无限量的数据更快时,您可以丢弃连接。请参阅限制在响应 HTTP GET 请求中读取的数据量。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go