我在Go语言中做了一个URL获取器,有一个要获取的URL列表,我向每个URL发送http.Get()请求并获取它们的响应。
http.Get()
resp,fetch_err := http.Get(url)
我如何为每个Get请求设置自定义超时?(默认时间很长,这会使我的fetcher非常慢。)我希望我的fetcher有一个大约40-45秒的超时,在此之后它应该返回“request timed out”并继续下一个URL。我如何才能做到这一点?
jyztefdp1#
显然在Go语言1.3中http.客户端有超时字段
client := http.Client{ Timeout: 5 * time.Second, } client.Get(url)
这对我来说已经够了。
qfe3c7zg2#
您需要使用自己的传输设置自己的客户端,该传输使用围绕DialTimeout的自定义拨号功能。类似于(完全 * 未经测试 *)this:
var timeout = time.Duration(2 * time.Second) func dialTimeout(network, addr string) (net.Conn, error) { return net.DialTimeout(network, addr, timeout) } func main() { transport := http.Transport{ Dial: dialTimeout, } client := http.Client{ Transport: &transport, } resp, err := client.Get("http://some.url") }
fcy6dtqo3#
如果您希望对每个请求执行此操作,则为了简洁起见,忽略错误处理:
ctx, cncl := context.WithTimeout(context.Background(), time.Second*3) defer cncl() req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://google.com", nil) resp, _ := http.DefaultClient.Do(req)
6yt4nkrj4#
为了补充Volker的答案,如果您还想设置除连接超时之外的读/写超时,可以执行如下操作
package httpclient import ( "net" "net/http" "time" ) func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) { return func(netw, addr string) (net.Conn, error) { conn, err := net.DialTimeout(netw, addr, cTimeout) if err != nil { return nil, err } conn.SetDeadline(time.Now().Add(rwTimeout)) return conn, nil } } func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client { return &http.Client{ Transport: &http.Transport{ Dial: TimeoutDialer(connectTimeout, readWriteTimeout), }, } }
这段代码已经过测试,正在生产中运行。完整的测试要点可以在这里找到https://gist.github.com/dmichael/5710968请注意,您需要为每个请求创建一个新客户端,因为conn.SetDeadline引用了time.Now()中的未来某个时间点
conn.SetDeadline
time.Now()
vs91vp4v5#
又急又脏的道:
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45
这是一个没有任何协调的全局状态的变化。但是它可能对你的url提取器来说是好的。否则创建一个http.RoundTripper的私有示例:
http.RoundTripper
var myTransport http.RoundTripper = &http.Transport{ Proxy: http.ProxyFromEnvironment, ResponseHeaderTimeout: time.Second * 45, } var myClient = &http.Client{Transport: myTransport} resp, err := myClient.Get(url) ...
未对上述内容进行测试。
qqrboqgw6#
在Go http模块中有几个客户端超时,并且有一些关于当前答案的超时示例。这里有一张图片说明客户端超时,请参阅The complete guide to Go net/http timeouts
http
有两种方法可以设置HTTP请求的超时
client := http.Client{ Timeout: 3 * time.Second, } resp, err := client.Do(req)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() req, err := http.NewRequestWithContext(ctx, http.MethodGet, URL)
The difference between them为
Do
deadline/timeout
wi3ka0sx7#
timeout := time.Duration(5 * time.Second) transport := &http.Transport{Proxy: http.ProxyURL(proxyUrl), ResponseHeaderTimeout:timeout}
这可能会有所帮助,但请注意,ResponseHeaderTimeout仅在建立连接后启动。
ResponseHeaderTimeout
7条答案
按热度按时间jyztefdp1#
显然在Go语言1.3中http.客户端有超时字段
这对我来说已经够了。
qfe3c7zg2#
您需要使用自己的传输设置自己的客户端,该传输使用围绕DialTimeout的自定义拨号功能。
类似于(完全 * 未经测试 *)this:
fcy6dtqo3#
如果您希望对每个请求执行此操作,则为了简洁起见,忽略错误处理:
6yt4nkrj4#
为了补充Volker的答案,如果您还想设置除连接超时之外的读/写超时,可以执行如下操作
这段代码已经过测试,正在生产中运行。完整的测试要点可以在这里找到https://gist.github.com/dmichael/5710968
请注意,您需要为每个请求创建一个新客户端,因为
conn.SetDeadline
引用了time.Now()
中的未来某个时间点vs91vp4v5#
又急又脏的道:
这是一个没有任何协调的全局状态的变化。但是它可能对你的url提取器来说是好的。否则创建一个
http.RoundTripper
的私有示例:未对上述内容进行测试。
qqrboqgw6#
在Go
http
模块中有几个客户端超时,并且有一些关于当前答案的超时示例。这里有一张图片说明客户端超时,请参阅The complete guide to Go net/http timeouts
有两种方法可以设置HTTP请求的超时
The difference between them为
Do
方法。deadline/timeout
专门用于每个请求,则使用context,否则,如果您希望每个出站请求都有1个超时,则使用client timeout就足够了。wi3ka0sx7#
这可能会有所帮助,但请注意,
ResponseHeaderTimeout
仅在建立连接后启动。