Why isn't the Go HTTPS client reusing connections?

I have an http client that creates multiple host connections. I want to set the maximum number of connections that it can establish for a specific host. There are no such options in the request. Transportation. My code looks like

package main import ( "fmt" "net/http" "net/url" ) const ( endpoint_url_fmt = "https://blah.com/api1?%s" ) func main() { transport := http.Transport{ DisableKeepAlives : false } outParams := url.Values{} outParams.Set("method", "write") outParams.Set("message", "BLAH") for { // Encode as part of URI. outboundRequest, err := http.NewRequest( "GET", fmt.Sprintf(endpoint_url_fmt, outParams.Encode()), nil ) outboundRequest.Close = false _ , err = transport.RoundTrip(outboundRequest) if err != nil { fmt.Println(err) } } } 

I expect this to create 1 connection. As I call it in the loop. But this creates an infinite number of connections.

Where, as a similar Python code, using the query library, only one connection is created.

 #!/usr/bin/env python import requests endpoint_url_fmt = "https://something.com/restserver.php" params = {} params['method'] = 'write' params['category'] = category_errors_scuba params['message'] = "blah" while True: r = requests.get(endpoint_url_fmt, params = params) 

For some reason, go code does not reuse http connections.

EDIT: The go code needs the body to be closed to reuse the connection.

  resp , err = transport.RoundTrip(outboundRequest) resp.Close() // This allows the connection to be reused 
+6
source share
1 answer

Based on additional clarifications from the OP. The default client reuses connections.

Be sure to close the answer .

Callers should close resp.Body when finished reading from it. If resp.Body is not closed, the Client underlying RoundTripper (usually Transport) may not be able to reuse a permanent TCP connection to the server for a subsequent keep-alive request.

In addition, I found that I also had to read until the answer was complete before calling Close ().

eg.

 res, _ := client.Do(req) io.Copy(ioutil.Discard, res.Body) res.Body.Close() 

To ensure reuse of the http.Client connection, be sure to do two things:

  • Read until response is complete (i.e. ioutil.ReadAll(resp.Body) )
  • Call Body.Close()

An old answer, useful for speed limits, but not what happened after the OP:

I don't think max connections are possible through the golang 1.1 http API. This means that you can keep up with tons of TCP connections (until you finish the file descriptors or something else) if you are not careful.

However, you can limit the speed at which you invoke the routine procedure for a specific host (and therefore outgoing requests and connections) via time.Tick.

For instance:

 import "time" requests_per_second := 5 throttle := time.Tick(1000000000 / requests_per_second) for i := 0; i < 16; i += 1 { <-throttle go serveQueue() } 
+12
source

Source: https://habr.com/ru/post/950669/


All Articles