Golang HTTP Client链接挂起问题
Golang HTTP Client挂起问题
在写GoRat的时候发现出现了一个奇葩的问题,主机上线2-3小时之后必定掉线,开了dlv挂着差不多1天左右,终于发现了问题所在
请求函数如下
func dialTimeout(network, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(network, addr, time.Second*POST_REMOTE_TIMEOUT)
if err != nil {
return conn, err
}
tcp_conn := conn.(*net.TCPConn)
tcp_conn.SetKeepAlive(false)
return tcp_conn, err
}
func SendRequest(action string, data url.Values, sendType string) string {
transport := http.Transport{
Dial: dialTimeout,
DisableKeepAlives: true,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
client := &http.Client{
Transport: &transport,
}
...
req.Header.Add("X-From", Host)
resp, err := client.Do(req) //总是卡在这里
...
}
最后调试发现,是卡在TLS握手包的位置,最后查资料发现,在go1.1之前,可以通过Dial来控制全局的超时时间
最早是用go1.1开发的,后来切换到了1.5,超时时间需要在http.Transport中单独设置或者使用DialContext进行设置
如果单独设置超时时间,常用的分别有如下几种类型的超时
//TLS握手超时时间,默认是0,既用不超时
TLSHandshakeTimeout: time.Duration(30) * time.Second,
//头响应时间,默认是0,既用不超时
ResponseHeaderTimeout: time.Duration(30) * time.Second,
//链接释放时间
IdleConnTimeout: time.Duration(30) * time.Second,
//Expect头超时时间
ExpectContinueTimeout: time.Duration(30) * time.Second,
然后只需要把前三个的超时时间设置一下 即可修复改bug
其实主要是因为使用了cloudflare的cdn,他的一些ip是被墙或者链接速度比较慢,导致了TLS握手的时候链接挂起。
不使用cdn或用国内访问稳定的CDN就可以了。