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来控制全局的超时时间
-w823

最早是用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就可以了。

标签: none