去http.Get,并发和"通过对等重置连接"

fgb*_*ist 10 concurrency http go

我有1000-2000个网页从一台服务器上下载,我正在使用go例程和渠道来实现高效率.问题是,每次运行我的程序时,最多400个请求都会失败并显示错误"peer by peer".很少(可能是10次中的1次),没有请求失败.

我该怎么做才能防止这种情况发生?

有趣的是,当我在与托管网站的服务器相同的国家/地区的服务器上运行此程序时,0请求失败,因此我猜测延迟存在一些问题(因为它现在正在运行在不同的大陆上的服务器).

我使用的代码基本上只是一个简单的http.Get(url)请求,没有额外的参数或自定义客户端.

Jim*_*imB 19

该消息connection reset by peer表明远程服务器发送RST强制关闭连接,故意作为限制连接的机制,或者由于缺乏资源.无论哪种方式,您可能打开太多连接,或重新连接太快.

并行启动1000-2000连接很少是下载那么多页面的最有效方式,特别是如果大多数或全部来自单个服务器.如果您测试吞吐量,您将找到一个低得多的最佳并发级别.

您还需要设置Transport.MaxIdleConnsPerHost匹配您的并发级别.如果MaxIdleConnsPerHost低于预期的并发连接数,服务器连接通常会在请求后关闭,只能立即再次打开 - 这将显着降低您的进度,并可能达到服务器强加的连接限制.

  • 这是一个很好的答案。我最终对有多少同时连接提供了最佳性能进行了一些测量,对于我目前使用的这个连接,结果大约是 50 个,比这更多的连接几乎没有额外的性能。我将运行的 go 例程的数量限制为最大 50,并将 MaxIdleConnsPerHost 设置为 50。现在每次都有效! (2认同)

AG1*_*AG1 17

仍然是一个golang新手,希望这会有所帮助.

var netClient = &http.Client{}

func init() {
    tr := &http.Transport{
        MaxIdleConns:       20,
        MaxIdleConnsPerHost:  20,
    }
    netClient = &http.Client{Transport: tr}
}

func foo() {
    resp, err := netClient.Get("http://www.example.com/")
}
Run Code Online (Sandbox Code Playgroud)

  • 上一本用于演示此处发布的解决方案的实际代码 (3认同)

Jam*_*all 5

MaxConnsPerHost通过设置交通选项,我得到了很好的结果......

cl := &http.Client{
    Transport: &http.Transport{MaxConnsPerHost: 50}
}
Run Code Online (Sandbox Code Playgroud)

MaxConnsPerHost 可以选择限制每个主机的连接总数,包括处于拨号、活动和空闲状态的连接。违反限制时,拨号盘将被阻止。

https://golang.org/pkg/net/http/#Transport.MaxConnsPerHost

编辑:为了澄清,这个选项是在 Go 1.11 中发布的,在上面 @AG1 或 @JimB 的答案时不可用,因此我发布了这个。

  • 不是,仔细阅读我的答案,AG1使用了“MaxIdleConnsPerHost”,这对我不起作用,“MaxConnsPerHost”是在Go 1.11(2018年11月发布)中引入的,当AG1发布他的答案时甚至还没有发布...... (5认同)
  • 抱歉,您的答案读得太快了一点。尽管如此,感谢您的澄清,肯定会对未来的读者有所帮助。 (2认同)