Go:HTTP长连接
一、演示
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
"sync"
"time"
)
var (
client *http.Client
once sync.Once
)
func CreateHTTPClient() *http.Client {
// 使用单例创建client
once.Do(func() {
client = &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 100, // 最大连接数,默认0无穷大
MaxIdleConnsPerHost: 100, // 对每个host的最大连接数量(MaxIdleConnsPerHost<=MaxIdleConns)
IdleConnTimeout: 90 * time.Second, // 多长时间未使用自动关闭连接
},
}
})
return client
}
func main() {
client := CreateHTTPClient()
req, err := http.NewRequest("get", "https://www.baidu.com", nil)
if err != nil {
log.Fatal(err)
}
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
io.Copy(ioutil.Discard, res.Body)
res.Body.Close()
}
二、源码分析
(一)Transport默认实现
var DefaultTransport RoundTripper = &Transport{
Proxy: ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
(二)字段解析
1、MaxIdleConns
最大连接数,默认0无限
2、MaxIdleConnsPerHost
const DefaultMaxIdleConnsPerHost = 2
同一个host最大连接数(MaxIdleConnsPerHost<=MaxIdleConns),如果不设置默认使用DefaultMaxIdleConnsPerHost
3、IdleConnTimeout
多长时间未使用自动关闭连接
三、注意
(一)请求头Connection
http1.0默认短连接,需要连接复用需要显式添加头Connection: keep-alive
http1.1默认长连接,默认:Connection: keep-alive,如果需要当前请求完成关闭连接添加Connection: close
(二)关于响应body数据
只要请求响应包含响应body必须读取出来,否则无法复用连接。如果响应数据不需要可以使用下面示例丢弃响应
io.Copy(ioutil.Discard, res.Body)