1. 了解http.Transport
Go语言中的http包提供了HTTP客户端和服务端功能,而http.Transport就是HTTP客户端的核心结构体。下面我们来了解一下http.Transport的基本特性。
1.1 http.Transport介绍
http.Transport实现了一个HTTP客户端的传输机制。Transport可以安全地同时被多个goroutine调用,对内部网络连接池进行了封装,从而在并发场景下提高了效率。如果在没有配置情况下,HTTP客户端将会默认使用http.DefaultTransport,它使用了http.DefaultTransport = &http.Transport{...}来提供http连接的管理。
1.2 Transport结构体中的一些参数
// http.Transport结构体的基本定义如下:
type Transport struct {
Proxy func(*Request) (*url.URL, error)
DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
Dial func(network, addr string) (net.Conn, error)
DialTLS func(network, addr string) (net.Conn, error)
DialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
DialTLSConfig *tls.Config
DisableKeepAlives bool
DisableCompression bool
MaxIdleConns int
MaxIdleConnsPerHost int
IdleConnTimeout time.Duration
TLSHandshakeTimeout time.Duration
ExpectContinueTimeout time.Duration
ProxyConnectHeader Header
MaxConnsPerHost int
writeBufferSize int
ReadBufferSize int
ForceAttemptHTTP2 bool
...
}
在这些参数中,MaxIdleConns和MaxIdleConnsPerHost限制了keep-alive连接的数量,即可复用但保持空闲状态的连接数。IdleConnTimeout字段表示一个keep-alive连接的最大保存时间,超过此时间连接会被销毁。
2. 设置http.Transport的最大并发数
在高并发的场景下,我们需要在一定程度上控制并发数,以避免HTTP请求过多造成服务器的压力过大。而http.Transport提供的MaxIdleConnsPerHost和MaxConnsPerHost参数可以帮助我们控制并发数。
2.1 MaxIdleConnsPerHost
MaxIdleConnsPerHost用于限制每个host的空闲连接数,从而防止大量的请求导致服务器内存占用。在一个HTTP会话中,如果请求一直使用同一个TCP连接,就可以使用keepalive功能来避免频繁建立和释放连接,通过MaxIdleConnsPerHost参数可以控制一个Host对应的空闲连接最大数量。
2.2 MaxConnsPerHost
如果MaxIdleConnsPerHost所控制的连接数量无法满足高并发场景下的需求,就需要通过设置MaxConnsPerHost来进一步增加连接池大小。虽然MaxIdleConnsPerHost可以控制单个host的空闲连接数,但MaxConnsPerHost可以控制的是并发的连接数量,从而可以有效地降低连接不够用的风险,提高HTTP请求的处理效率。
3. 优化http.Transport的性能
在一些特殊的场景下,设置MaxIdleConnsPerHost和MaxConnsPerHost可能无法满足高并发的需求,这时候需要对http.Transport做一些性能方面的优化。
3.1 keep-alive机制
在高并发场景下,如果关闭HTTP keep-alive机制,频繁新建连接会带来性能的巨大浪费。因此,在允许的情况下,我们必须启用HTTP keep-alive机制,并设置合理的可重用连接数。
3.2 Connection: Close头信息
当客户端在短时间内频繁发起HTTP请求时,可能会因为socket连接被迅速耗尽而给服务器带来压力,这时可以通过在请求头添加Connection: Close头信息仅限本次HTTP请求,等到响应后关闭连接从而保留socket连接供更多的HTTP请求使用。
4. 代码实战
下面是在http.Transport中增加MaxIdleConnsPerHost、MaxConnsPerHost参数,同时启用keep-alive机制和Connection: Close头信息的代码实例。
httpClient := &http.Client{
Transport: &http.Transport{
MaxIdleConnsPerHost: 4096,
MaxConnsPerHost: 4096,
DisableCompression: true,
DisableKeepAlives: false,
IdleConnTimeout: 60 * time.Second,
ResponseHeaderTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSHandshakeTimeout: 5 * time.Second,
DialContext: (&net.Dialer{
Timeout: time.Duration(time.Duration(30) * time.Second),
KeepAlive: time.Duration(time.Duration(30) * time.Second),
DualStack: true,
}).DialContext,
},
Timeout: 300 * time.Second,
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}
req.Header.Add("Connection", "Close")
resp, err := httpClient.Do(req)
if err != nil {
return "", err
}
5. 总结
通过对http.Transport的参数和特性的了解,我们可以在实际应用中合理地调整MaxIdleConnsPerHost、MaxConnsPerHost,同时启用keep-alive机制和Connection: Close头信息,有效地控制HTTP请求的并发。在高并发场景下,提高HTTP请求的性能和效率对于保证系统稳定性和可用性至关重要。