0%

tcp keepalive in go

http 1.1 默认开启了 tcp keepalive,复用 tcp 连接. go 中发起 http 请求,如何使用 keepalive 呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
var (
QHTTPTransport http.RoundTripper = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 5,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}

QHTTPClient = &http.Client{
Transport: QHTTPTransport,
}
)

发起 http 请求时,使用 QHTTPClient.
go 服务端 http.ListenAndServe(":8080",nil) 默认开启了 keepalive.

使用 man 7 tcp查看 tcp_keepalive_time,默认保持时间是 7200秒,tcp_keepalive_intvl默认是 75秒
自定义:

1
2
3
4
   srv := http.Server{
Handler: mux,
}
srv.SetKeepAlivesEnabled(false)

或者自定义 listener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type tcpKeepAliveListener struct {
*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
tc, err := ln.AcceptTCP()
if err != nil {
return nil, err
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(time.Second*10) // 设置 keepalive period
return tc, nil
}
func main(){
err = srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

gin 框架自定义 keepalive

1
2
3
4
5
6
7
8
router := gin.Default()

s := &http.Server{
Addr: ":8080",
Handler: router, // < here Gin is attached to the HTTP server
}
s.SetKeepAlivesEnabled(false)
s.ListenAndServe()