【轉】C#多線程環境下調用 HttpWebRequest 併發連接限制

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類的時候,默認會去檢查代理服務器設置,這樣當然就慢了。而且可以在app.config中設置連接數和代理服務器的設置,而不需要在程序中硬編碼了。

 

  <system.net>

    <defaultProxy enabled="false">

      <proxy/>

      <bypasslist/>

      <module/>

    </defaultProxy>

    <connectionManagement>

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

    </connectionManagement>

  </system.net>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章