Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does multithreading affect http keep-alive connection?

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 ?

like image 625
JavaDeveloper Avatar asked Sep 06 '20 02:09

JavaDeveloper


People also ask

How do I keep my HTTP connection alive?

using HTTP/1.0, started to add an unofficial extension (to the protocol) named "keep-alive" in order to allow the reuse of a connection for multiple requests/responses. When the server receives this request and generates a response, if it supports keep-alive then it also adds the same above header to the response.

What does connection keep alive mean in HTTP?

HTTP keep-alive, a.k.a., HTTP persistent connection, is an instruction that allows a single TCP connection to remain open for multiple HTTP requests/responses. By default, HTTP connections close after each request.

Is http keep alive default?

Keep-alive connections are enabled by default in HTTP/1.1 while not in HTTP/1.0. HTTP/1.0 was designed to close the connection after every request between client and server.

How long does connection keep alive last?

It sets how long your server should wait for new requests from clients. A value between 7 to 10 seconds is usually ideal. With higher traffic this value can go extremely higher to make sure there is no frequent TCP connection re-initiated. If this value goes down too much, Keep-Alive loses it's purpose!


2 Answers

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.

like image 154
hobbs Avatar answered Oct 11 '22 11:10

hobbs


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.

like image 20
Adriel Artiza Avatar answered Oct 11 '22 12:10

Adriel Artiza