在Go

时间:2018-02-21 08:01:18

标签: http go

我知道通过执行以下操作来指定HTTP请求超时的常用方法:

httpClient := http.Client{
    Timeout: time.Duration(5 * time.Second),
}

但是,我似乎无法弄清楚在跟踪HTTP请求时如何做同样的事情。以下是我正在处理的代码:

func timeGet(url string) (httpTimingBreakDown, error) {
    req, _ := http.NewRequest("GET", url, nil)

    var start, connect, dns, tlsHandshake time.Time
    var timingData httpTimingBreakDown
    timingData.url = url

    trace := &httptrace.ClientTrace{
        TLSHandshakeStart:    func() { tlsHandshake = time.Now() },
        TLSHandshakeDone:     func(cs tls.ConnectionState, err error) { timingData.tls = time.Since(tlsHandshake) },
    }

    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
    start = time.Now()

    http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 10 // hacky way, worked earlier but don't work anymore

    if _, err := http.DefaultTransport.RoundTrip(req); err != nil {
        fmt.Println(err)
        return timingData, err
    }

    timingData.total = time.Since(start)

    return timingData, nil
}

我在goroutine中触发了这个函数。我的样本数据集是100个网址。所有goroutines都会激活,但最终程序会在30秒内结束,就像超时为30秒一样。

早些时候我做了同样的工作,使用hacky方法将其内部的默认值更改为10秒,任何花费太长时间,超时并且程序以10.xxx秒结束但现在以30.xx结束秒。

在这种情况下指定超时的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

  

我知道通过执行以下操作来指定HTTP请求超时的常用方法:

httpClient := http.Client{
    Timeout: time.Duration(5 * time.Second),
}

实际上,首选方法是在请求中使用context.Context。您使用的方法只是一个适用于简单用例的快捷方式。

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
    return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()
req = req.WithContext(ctx)

这种方法也可以很好地适应你的情况。