1つのサーバーからダウンロードする1000〜2000のWebページがあり、高効率を達成するためにgoルーチンとチャネルを使用しています。問題は、プログラムを実行するたびに最大400のリクエストが「ピアによる接続のリセット」というエラーで失敗することです。まれに(10回に1回程度)、リクエストが失敗することはありません。
これを防ぐにはどうすればよいですか?
興味深いのは、このプログラムをウェブサイトがホストされているサーバーと同じ国のサーバーで実行したときに、リクエストが0件失敗したため、遅延に問題があると思います(現在、別の大陸のサーバー)。
私が使用しているコードは、基本的に単純なhttp.Get(url)リクエストであり、追加のパラメーターやカスタムクライアントはありません。
メッセージ connection reset by peer
は、意図的に接続を制限するメカニズムとして、またはリソースの不足の結果として、リモートサーバーがRST
を送信して接続を強制的にクローズしたことを示します。開いている接続が多すぎるか、再接続が速すぎる可能性があります。
1000〜2000の接続を並列で開始することは、特にほとんどまたはすべてが単一のサーバーからのものである場合、その多くのページをダウンロードする最も効率的な方法であることはめったにありません。スループットをテストすると、はるかに低い最適な同時実行レベルが見つかります。
また、Transport.MaxIdleConnsPerHost
は、同時実行性のレベルに一致させます。 MaxIdleConnsPerHost
が予想される同時接続数より少ない場合、サーバー接続は多くの場合、要求後に閉じられ、すぐに再び開かれるだけです-これにより、進行が大幅に遅くなり、サーバ。
まだ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/")
}
トランスポートにMaxConnsPerHost
オプションを設定することで、良い結果が得られました...
cl := &http.Client{
Transport: &http.Transport{MaxConnsPerHost: 50}
}
MaxConnsPerHostはオプションで、ダイヤリング、アクティブ、アイドル状態の接続を含む、ホストごとの接続の総数を制限します。制限違反の場合、ダイヤルはブロックされます。
https://golang.org/pkg/net/http/#Transport.MaxConnsPerHost
編集:明確にするために、このオプションはGo 1.11でリリースされました。これは、上記の@ AG1または@JimBの回答時に利用できなかったため、これを投稿しました。
Webページのダウンロード元のサーバーに、特定のIPからの1秒あたりの要求数(または同様の要求)が一定数を超えるのを防ぐ、ある種のスロットルメカニズムがある可能性があります。 1秒あたり100リクエストに制限するか、リクエスト間にスリープを追加してください。ピアによる接続リセットは、基本的にサーバーがサービスを拒否することです。 ( 「ピアによる接続のリセット」とはどういう意味ですか? )