How to Use the HTTP Client in GO To Enhance Performance

In this post, we will discuss how to make HTTP requests for higher performance in Go, and also how to tune it.

Mayank Agarwal
By Mayank Agarwal
January 12, 2021
3 min read

HTTP (hypertext transfer protocol) is a communication protocol that transfers data between client and server. HTTP requests are very essential to access resources from the same or remote server. In Golang, the net/http package comes with the default settings that we need to adjust according to our high-performance requirement.

For setting up HTTP clients for making requests, most programming languages have different frameworks in place. We will take a hands-on approach in the coming sections to explore how HTTP requests can be made in Golang or Go, as I will refer to the language for the rest of the post.

While working on the Golang projects, I realized that improper configuration of HTTP might crash your server anytime.

In the time when I was working with HTTP Client, I Observed some problems and their solutions, listed below:

Problem:1 Default Http Client

The HTTP client does not contain the request timeout setting by default. If you are using http.Get(URL) or &Client{} that uses the http.DefaultClient. DefaultClient has not timeout setting; it comes with no timeout

Suppose the Rest API where you are making the request is broken, not sending the response back that keeps the connection open. More requests came, and open connection count will increase, Increasing server resources utilization, resulting in crashing your server when resource limits are reached.

Solution: Don't use the default HTTP client, always specify the timeout in http.Client according to your use case

var httpClient = &http.Client{
  Timeout: time.Second * 10,
}

For the Rest API, it is recommended that timeout should not more than 10 seconds. If the Requested resource is not responded to in 10 seconds, the HTTP connection will be canceled with net/http: request canceled (Client.Timeout exceeded ...) error.

Problem:2 Default Http Transport

By default, the Golang Http client performs the connection pooling. When the request completes, that connection remains open until the idle connection timeout (default is 90 seconds). If another request came, that uses the same established connection instead of creating a new connection, after the idle connection time, the connection will return to the pool.

Using the connection pooling will keep less connection open and more requests will be served with minimal server resources.

When we not defined transport in the http.Client, it uses the default transport Go HTTP Transport

Default configuration of the HTTP Transport,

var DefaultTransport RoundTripper = &Transport{
	...
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	...
}

const DefaultMaxIdleConnsPerHost = 2

MaxIdleConns is the connection pool size, and this is the maximum connection that can be open; its default value is 100 connections.

There is problem with the default setting DefaultMaxIdleConnsPerHost with value of 2 connection, DefaultMaxIdleConnsPerHost is the number of connection can be allowed to open per host basic. Means for any particular host out of 100 connection from the connection pool only two connection will be allocated to that host.

With the more request came, it will process only two requests; other requests will wait for the connection to communicate with the host server and go in the TIME_WAIT state. As more request came, increase the connection to the TIME_WAIT state and increase the server resource utilization; at the limit, the server will crash.

Solution: Don't use Default Transport and increase MaxIdleConnsPerHost

t := http.DefaultTransport.(*http.Transport).Clone()
t.MaxIdleConns = 100
t.MaxConnsPerHost = 100
t.MaxIdleConnsPerHost = 100
	
httpClient = &http.Client{
  Timeout:   10 * time.Second,
  Transport: t,
}

By increasing connection per host and the total number of idle connection, this will increase the performance and serve more request with minimal server resources.

Connection pool size and connection per host count can be increased as per server resources and requirements.

Conclusion

In this article, we discussed the problems around the 'net/http' client default configurations. By changing some of the default settings of HTTP Client, we can achieve a High-performance HTTP client for production use. If you want to learn more about http, here is an interesting post on HTTP security headers If you like what you read, share your thoughts in the comment section.

Mayank Agarwal

Written by Mayank Agarwal

Mayank is a Software developer at LoginRadius. He graduated with a Bachelor of Technology Degree in Computer Science. He loves to play cricket, watching TV series and listening music.

LoginRadius CIAM Platform

Our Product Experts will show you the power of the LoginRadius CIAM platform, discuss use-cases, and prove out ROI for your business.

Book A Demo Today