C#多線程環境下調用 HttpWebRequest 並發串連限制

來源:互聯網
上載者:User

HttpClient是否有預設並發數限制?

在.Net 4.0之前,一直是依靠HttpWebRequest實現Http操作的。它預設有一個非常保守的同一網站下最大2並發數限制,導致預設情況下HttpWebRequest往往得不到理想的速度(估計這個策略鬱悶了不少碼農),必須修改App.config或ServicePointManager.DefaultConnectionLimit的值。

MS在.Net 4.5中引入了一個HttpClient類專門處理Http操作,本來我以為HttpClient和HttpWebRequest遵循一樣的策略的。今天在寫一個多線程下載的程式的時候,用到了10個並發串連,發現在預設的情況下,HttpClient並沒有並發數限制。

最初我以為是.Net 4.5取消了這個並發數限制(畢竟現在基本上沒有誰遵循這個標準了),然後用WebRequest重寫了相關代碼,發現依然是2並發上限,並且ServicePointManager.DefaultConnectionLimit的值也是2。也就是說: HttpClient不受HttpWebRequest並發策略控制,也沒有系統級的並發限制。

另外,測試的時候發現,HttpWebRequest預設也不是對所有地址都2並發上限的。例如,對本地的http地址串連(http://localhost/*)就沒有並發限制。

 

C#多線程環境下調用 HttpWebRequest 並發串連限制

.net 的 HttpWebRequest 或者 WebClient 在多線程情況下存在並發串連限制,這個限制在案頭作業系統如 windows xp , windows 7 下預設是2,在伺服器作業系統上預設為10. 如果不修改這個並發串連限制,那麼用戶端同時可以建立的 http 串連數就只有2個或10個。對於一些諸如瀏覽器或網路蜘蛛的應用,2個或10個並發數量實在太少,大大影響應用的效能。之所以有這個並發串連限制,是因為 http 1.0 和 http 1.1 標準規定並發串連數最大為2. 不過目前主流的瀏覽器都已經不遵循這個規則了,但 .net framework 依然預設遵循這個規則。

很多文章說用非同步方式訪問 HttpWebRequest 可以提高並發效能,但我測試下來,如果不修改這個預設並發串連數,同步或非同步方式訪問效能都很不好。

調整這個預設並發串連限制的方法很簡單

只要在程式中設定:

System.Net.ServicePointManager.DefaultConnectionLimit = 512;

這個值最好不要超過1024。

我們也可以在app.config 中對最大並發串連數進行設定,方法如下:

<configuration>
<system.net>
<connectionManagement>
<add address = "http://www.google.com" maxconnection = "512" />
<add address = "*" maxconnection = "512" />
</connectionManagement>
</system.net>
</configuration>

修改了這個設定後,並發效能明顯提高,從原來每秒鐘20次直接上升到每秒鐘1000多次。

 

 

 

注意DotNet的ConnectionLimit

 

由於不熟悉C#的開發,在做一個系統WS介面的壓力測試時走了彎路。發現這個問題的原委是要在用C#壓力測試我們的一個REST Web Service.伺服器上我理論預計的效能是100並發,4s內響應完成。這個系統提供了給DotNet的用戶端,使用hammock庫編寫而成,在壓力測試中,系統效能總是上不來,在查看伺服器日誌後發現請求都是串列處理的,所以維持了400ms每個請求的效能水平,而理論上的十個通道的平行處理的效能沒有達到。我開始以為是否是同事編寫的用戶端有問題,檢查之後發現沒有任何問題;轉而尋求是否是Hammock庫的問題,未果。然後懷疑伺服器的問題,我使用Java,restclient庫編寫了一個測試程式,發現10個通道全部啟用,達到了理論效能,伺服器方面完成不成問題。所以應該是C#方面的問題,Hammock的源碼比較複雜,看了半天也沒啥發現,在我們的這個RestClient中有點殺雞用牛刀的感覺,是否是其中的什麼Bug呢?所以準備自行編寫用戶端。由於伺服器上使用Rest,XML傳輸格式的XSD檔案也已經產生,用戶端上都是使用xsd檔案反向產生的POCO對象,查了一下C#的文檔,直接使用XmlSerializer就可以很方便的實現序列化和還原序列化了。並且System.Net命名空間中有HttpWebRequest類,很容易自行實現自己的用戶端,而不是用hammock庫,這樣就可以排除hammock的問題。昨晚自己寫了一下,一測試效能還是無法達到,使用netstat查看串連,居然發現同時還只有兩個串連到伺服器。覺得奇怪,所以使用C# Socket Connection limit之類的關鍵字Google,原來C#類庫中,HttpWebRequest預設的最大串連數為2,為什麼是個二呢?想不通,其實我覺得既然作為類庫,C#完全不必要限制用戶端的串連數,這是由程式員控制的啊。有兩個辦法設定不同的串連數。

1. HttpWebRequest.ServicePoint.ConnectionLimit

2. ServicePointManager.DefaultConnectionLimit

任意設定一個到我的最大平行處理數,比如時,效能馬上就上去了,幾乎逼近於理論效能,但是相比使用Java測試的結果還是要整體慢3s左右,因為不知道什麼原因,在首次串連伺服器時,會有一個幾秒的延遲。不知道具體原因是什麼,是否又有什麼預設設定?又經過了一番搜尋和研究,終於發現了真正的原因,在使用HttpWebRequest類的時候,預設會去檢查Proxy 伺服器設定,這樣當然就慢了。而且可以在app.config中設定串連數和Proxy 伺服器的設定,而不需要在程式中寫入程式碼了。

  <system.net>

    <defaultProxy enabled="false">

      <proxy/>

      <bypasslist/>

      <module/>

    </defaultProxy>

    <connectionManagement>

      <add address="*" maxconnection="10"/>

    </connectionManagement>

  </system.net>

PS:最近用Visual Studio,用C#,不知道仍然是先入為主的習慣問題,總覺得沒有使用Eclipse編寫Java好用,首先是自己對代碼編寫的快速鍵不熟悉,所以效率要慢一半

為什麼不能用源碼綁定到dll上,就像在eclipse裡把src綁定到jar包上一樣

為什麼就沒有一個快速鍵全部快速自動匯入命名空間呢

為什麼就沒有一個Ctrl+O,快速定位到類或者資源呢,不要跟我說Ctrl+,,把方法,類,欄位啥都混在一起了

最後經過了一番搜尋,發現了有個Visual Studio的外掛程式,Productive PowerTools,可以增強有些特性,比如使用Alt+Up上移一行代碼,Alt+Down下移當前行代碼,這跟在Eclipse中的操作習慣一致了,不過這並沒有自動把移動的代碼格式化,這是Eclipse要強大的地方。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.