6

我正在研究一種應用程序,它需要一種類型的消息去擊中數據庫,另一種類型的消息去打一些外部xml api。HttpWebRequest和I/O完成端口

我必須處理一個很大的挑戰之一是讓HttpWebRequest類表現良好。我最初開始只使用標準的同步方法,並將整個線程化。這並不好。

那麼一點閱讀後,我看到推薦的方式做,這是使用的開始/結束的方法來工作委託給IO完成端口,從而釋放線程池,併產生更好的性能。這似乎並不是這種情況...性能稍微好一些,但我相信與線程池相比,我完全看不到IO完成端口的使用。

我有一個線程輪換並向我發送線程池中可用的工作線程+完成端口。完成端口總是非常低(我見過的最大值是9),而且我總是使用大約120個工作線程(有時更多)。我用所有的方法httpwebrequest的開始/結束模式:

Begin/EndGetRequestStream 
Begin/EndWrite (Stream) 
Begin/EndGetResponse 
Begin/EndRead (Stream) 

我這樣做對嗎?我錯過了什麼嗎?我可以同時使用(有時)多達2048個http連接(來自netstat輸出) - 爲什麼完成端口號會很低?

如果有人可以給一些嚴肅的建議,關於如何做好這個管理工作者線程,完成端口和httpwebrequest將非常感激!

編輯:.NET是一個合理的工具嗎?我可以獲得大量的使用.NET和System.Net堆棧的httpconnections嗎?有人建議使用類似WinHttp(或其他C++庫)的東西,並從.NET中調用它,但這不是我特別想做的事情!

+0

您的外部API是否正確處理負載?我有一個外部服務,如果我發送太多的請求,服務服務器上的性能會有明顯的下降。 – btlog 2011-01-26 14:13:36

+0

@btlog - >是的,好像我禁用了一些外部提供者,其他提供者產生更好的時間(但接收到相同的呼叫量)。如果問題是在他們身上,那麼無論我對其他XML服務做什麼都不會影響其他服務。 – peteisace 2011-01-27 07:08:03

回答

6

我的理解是,你不會捆綁一個I/O完成端口全部一個異步請求未完成的時間 - 只有當數據已被返回並正在處理相應的線程。希望你沒有非常在回調中做很多工作,這就是爲什麼你在任何時候都沒有很多使用中的端口。

您是否其實雖然表現不佳?你關心的僅僅是低數量嗎?你是否獲得了你期望的吞吐量?

有一個問題你可能有的是任何一個主機的HTTP連接池都比較小。如果您對同一臺計算機有數百個請求,則默認情況下,一次只能創建2個請求實際上爲,以避免DoS攻擊相關主機(並獲得保持活動的好處)。你可以通過編程或者使用app.config來增加它。當然,這可能不是問題,因爲您已經解決了問題,或者因爲您的所有請求都是針對不同的主機。 (如果netstat顯示2048個連接,那聽起來不錯。)

0

也許您的EndRead方法應該只將結果寫入線程安全隊列,然後您可以從您控制的少量工作線程讀取結果。和/或使用HttpWebRequest在完成時發出等待對象的信號這一事實,並編寫自己的邏輯以等待來自單個(或少量)線程的所有未完成請求。

0

只有9個完成端口線程實際上意味着你可能正確和有效地使用它們。我假設你正在運行的機器有8個內核或4個超線程內核,這意味着操作系統會隨時嘗試保持最多8個活動(不是休眠/阻塞/等待)完成端口線程。

如果其中一個正在運行的線程變爲非活動狀態(sleep/block/wait)並且還有額外的工作項需要處理,那麼會創建一個附加線程來將活動計數保持爲8.如果看到9個線程,意味着您在完成端口線程的方法中實際上不會引入阻塞,並且實際上正在對它們執行CPU工作。

如果您有8個線程主動在8個內核上進行CPU綁定工作,那麼添加更多線程只會減慢速度(線程之間的上下文切換將是浪費的時間)。

你應該注意的是爲什麼你有120 其他線程和他們在做什麼。