2016-06-12 110 views
7

我有一個服務器下載1000-2000個網頁,我使用go例程和通道來實現高效率。問題是,我每次運行我的程序多達400個請求失敗,出現錯誤「由對等方重置連接」。很少(可能是10次中的1次),沒有請求失敗。Go http.Get,併發性和「通過對等方重置連接」

我能做些什麼來防止這種情況發生?

有一件有趣的事情是,當我在服務器所在的服務器上運行該程序時,該網站託管在服務器中,0個請求失敗,所以我猜測延遲存在一些問題(因爲它是現在在不同的大陸上的服務器上運行)。

我使用的代碼基本上只是一個簡單的http.get(url)請求,沒有額外的參數或自定義客戶端。

+0

所有或大部分頁面來自同一臺服務器?您正在同時進行的最大請求數是多少? – JimB

+0

所有頁面來自同一臺服務器(編輯問題以反映此問題)。我不確定有多少是同時生成的。我只是開始儘可能多的下載例程,然後讓CPU/Golang強加併發的限制。 – fgblomqvist

+0

對併發沒有限制,你需要自己去做。 – JimB

回答

11

消息connection reset by peer指示遠程服務器發送的RST強行關閉連接,無論是故意作爲一種機制來限制連接,或由於缺乏資源的結果。無論哪種方式,你可能會打開太多的連接,或重新連接太快。

啓動1000-2000個並行連接很少是下載多個頁面的最有效方式,尤其是在大多數或全部來自單個服務器的情況下。如果您測試吞吐量,您會發現最低的併發級別。

您還需要設置Transport.MaxIdleConnsPerHost以匹配您的併發級別。如果MaxIdleConnsPerHost低於預期的併發連接數,服務器連接通常會在請求後關閉,只能立即再次打開 - 這會顯着降低進度並可能達到服務器施加的連接限制。

+1

這是一個很好的答案。最後,我測量了多少同時連接提供了最好的性能,對於這個連接,我目前使用的是大約50個連接,而這些連接幾乎沒有提供額外的性能。我將運行的例程數量限制爲最大值50,並將MaxIdleConnsPerHost設置爲50.現在每次都可用! – fgblomqvist

+0

@ AG1:你在找什麼代碼?答案歸結爲將MaxIdleConnsPerHost設置爲等於併發請求的數量。 – JimB

+0

@JimB我添加了代碼作爲答案,使其更具體。 – AG1

1

您從中下載網頁的服務器可能有某種類型的限制機制,它可以防止每秒/(或類似)的某個數量以上的某個ip請求?嘗試限制爲每秒100個請求或在請求之間添加睡眠。 由對端重置的連接基本上是拒絕服務的服務器。 (What does "connection reset by peer" mean?

+0

考慮到當我在與服務器在同一個國家的服務器上運行它時,一切運行良好,它似乎沒有這樣的限制(除非它們僅限於來自其他國家的人,這在其他國家並沒有多大意義)我的場景)。不過,我會考慮限制每秒的請求數量。 – fgblomqvist

+0

通常服務器只能處理一定數量的併發請求,並且您可能已經超過了該容量。從同一個國家運行良好的原因是,請求可能會花費更少的時間,所以連接不會用完,服務器可以處理更多。 – robbrit

+0

@robbrit我猜可能是這種情況。我將不得不實現我認爲的連接池。 – fgblomqvist

5

仍然是一個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/") 
} 
+1

上一個用於演示此處發佈的解決方案的實際代碼 – fgblomqvist

相關問題