skip to Main Content
var (
    httpClient *http.Client
)

const (
    MaxIdleConnections int = 20
    RequestTimeout     int = 5
)

// init HTTPClient
func init() {
    client := &http.Client{
        Transport: &http.Transport{
            MaxIdleConnsPerHost: MaxIdleConnections,
        },
        Timeout: time.Duration(RequestTimeout) * time.Second,
    }

    return client
}

func makeRequest() {
    var endPoint string = "https://localhost:8080/doSomething"

    req, err := http.NewRequest("GET", ....)
    
    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()
        body, err := ioutil.ReadAll(response.Body)
        if err != nil {
            log.Fatalf("Couldn't parse response body. %+v", err)
        }
        
        log.Println("Response Body:", string(body))
    }
}

I have the following code in Go. Go uses http-keep-alive connection. Thus, from my understanding, httpClient.Do(req) will not create a new connection, since golang uses default persistent connections.

  1. From my understanding HTTP persistent connection makes one request at a time, ie the second request can only be made after first response. However if multiple threads call makeRequest() what will happen ? Will httpClient.Do(req) send another request even before previous one got a response ?

  2. I assume server times-out any keep-alive connection made by client. If server were to timeout, then the next time httpClient.Do(req)is called, would it establish a new connection ?

2

Answers


  1. an http.Client has a Transport to which it delegates a lot of the low-level details of making a request. You can change pretty much anything by giving your client a custom Transport. The rest of this answer will largely assume that you’re using http.DefaultClient or at least a client with http.DefaultTransport.

    When making a new request, if an idle connection to the appropriate server is available, the transport will use it.

    If no idle connection is available (because there never was one, or because other goroutines are using them all, or because the server closed the connection, or there was some other error) then the transport will consider making a new connection, limited by MaxConnsPerHost (default: no limit). If MaxConnsPerHost would be exceeded, then the request will block until an existing request completes and a connection becomes available. Otherwise, a new connection will be made for this request.

    On completion of a request, the client will cache the connection for later use (limited by MaxIdleConns and MaxIdleConnsPerHost; DefaultTransport has a limit of 100 idle connections globally, and no limit per-host).

    Idle connections will be closed after IdleConnTimeout if they aren’t used to make a request; for DefaultTransport the limit is 90 seconds.

    All of which means that by default, Go will make enough connections to satisfy parallelism (up to certain limits which you can adjust) but it will also reuse keep-alive connections as much as possible by maintaining a pool of idle connections for some length of time.

    Login or Signup to reply.
  2. It will not affect the http keep-alive connection, base on your code, you are using global httpClient, this will not create a new connection if called in multiple thread as you expected, Also it read the response.Body before it closed. If the provided response.Body is an io.Closer, it will closed after the request.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search