重用Golang中的http连接
我目前正在努力寻找一种在Golang中制作HTTPpost时重用连接的方法。
我创build了一个传输和客户端,如下所示:
// Create a new transport and HTTP client tr := &http.Transport{} client := &http.Client{Transport: tr}
然后,我将这个客户端指针传入一个goroutine,这个goroutine正在向同一端点发出多个post,如下所示:
r, err := client.Post(url, "application/json", post)
看着netstat这似乎是导致每个职位的新连接导致大量的并发连接正在打开。
在这种情况下重用连接的正确方法是什么?
在调用Close()
之前,你应该确保你阅读直到响应完成 。
例如
res, _ := client.Do(req) io.Copy(ioutil.Discard, res.Body) res.Body.Close()
要确保http.Client
连接重用,请务必做两件事:
- 阅读,直到响应完成(即
ioutil.ReadAll(resp.Body)
) - 调用
Body.Close()
编辑:这是更多的人为每个请求构build传输和客户端的说明。
Transport
是保存连接重用的结构:
http://golang.org/src/pkg/net/http/transport.go#L46
因此,如果您为每个请求创build一个新的传输,则每次都会创build新的连接。 在这种情况下,解决scheme是在客户端之间共享一个传输实例。
如果任何人仍然在如何做到这一点find答案,这是我如何做到这一点。
package main import ( "bytes" "io/ioutil" "log" "net/http" "time" ) var ( httpClient *http.Client ) const ( MaxIdleConnections int = 20 RequestTimeout int = 5 ) // init HTTPClient func init() { httpClient = createHTTPClient() } // createHTTPClient for connection re-use func createHTTPClient() *http.Client { client := &http.Client{ Transport: &http.Transport{ MaxIdleConnsPerHost: MaxIdleConnections, }, Timeout: time.Duration(RequestTimeout) * time.Second, } return client } func main() { var endPoint string = "https://localhost:8080/doSomething" req, err := http.NewRequest("POST", endPoint, bytes.NewBuffer([]byte("Post this data"))) if err != nil { log.Fatalf("Error Occured. %+v", err) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") // use httpClient to send request response, err := httpClient.Do(req) if err != nil && response == nil { log.Fatalf("Error sending request to API endpoint. %+v", err) } else { // Close the connection to reuse it defer response.Body.Close() // Let's check if the work actually is done // We have seen inconsistencies even when we get 200 OK response body, err := ioutil.ReadAll(response.Body) if err != nil { log.Fatalf("Couldn't parse response body. %+v", err) } log.Println("Response Body:", string(body)) } }
去游乐场: http : //play.golang.org/p/oliqHLmzSX
总之,我正在创build一个不同的方法来创build一个HTTP客户端,并将其分配给全局variables,然后使用它来发出请求。 注意
defer response.Body.Close()
这将closures连接并将其设置为可以再次使用。
希望这会帮助别人。
IIRC,默认客户端确实重用连接。 你正在closures响应 ?
读者完成读取后,呼叫者应closuresresp.Body。 如果resp.Body未closures,则客户端的底层RoundTripper(通常是传输)可能无法重新使用持续的TCP连接到服务器,以进行后续“保持活动”请求。