配置连接池
初始化http连接池
t1 := &http.Transport{
Proxy: func(*http.Request) (*url.URL, error) {
// 不读取HTTP_PROXY环境变量
return nil, nil
},
DialContext: (&net.Dialer{
// TCP握手超时
Timeout: 3 * time.Second,
// TCP协议的长连接维护,和应用层的http协议无关
KeepAlive: 60 * time.Second,
DualStack: true,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 200,
MaxIdleConnsPerHost: 100,
MaxConnsPerHost: 200,
// 不会自动读取response header里keep-alive项的timeout值
IdleConnTimeout: 20 * time.Second,
// TLS握手超时
TLSHandshakeTimeout: 2 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
// 等待response status的最长时间,可以不配置,只使用http.Client的超时时间
ResponseHeaderTimeout: 90 * time.Second,
}
// 所有http.Client会默认使用此连接池
http.DefaultTransport = t1
自动升级http2
// 利用ALPN机制(TLS扩展)实现升级协议,通过http.Transport的TLSNextProto配置
t2, err := http2.ConfigureTransports(t1)
if err != nil {
panic(err)
}
// 服务端指定了一个TCP连接里最大的并发stream数(多路复用)
// 这里配置的是,超过这个并发后,让客户端等待前面的stream完成
t2.StrictMaxConcurrentStreams = true
// http2客户端定时维护空闲连接
// http2连接的断开,交由http2服务端的IdleTimeout控制(会忽略ping帧)
t2.ReadIdleTimeout = 20 * time.Second
t2.PingTimeout = 3 * time.Second
发起请求
使用http.Client的超时配置
func TestHttpClient(t *testing.T) {
client := &http.Client{
Timeout: time.Second * 30,
}
resp, err := client.Get("https://xxx")
if err != nil {
t.Error(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Error(err)
}
if resp.Proto != "HTTP/2.0" {
t.Error("ALPN failed")
}
log.Printf("响应内容: %s, Protocol: %s", body, resp.Proto)
}