2014-01-24 71 views
2

我有一個使用BeginRead/EndRead異步I/O範例實現套接字服務器的.NET Windows服務。現在這個套接字代碼需要調用一些async/Task /等待異步代碼。當您使用Task.Run時,會發生什麼情況以致線程池耗盡?

我一直在使用Nito.AsyncEx庫的AsyncContext類'運行方法,但我對是否阻止EndRead進行調用並保留工作線程人質持保留態度。我得到的建議是my earlier question是使用Task.Run而不是Nito.AsyncEx的AsyncContext.Run。這將調用提交到異步/等待代碼並立即返回。我想到,在負載情況下,客戶端不會阻止請求淹沒線程池。

我會重新問我關於Nito.AsyncEx的AsyncContext.Run的原始問題:它是否保存它被調用的線程(池線程調用我的套接字的EndRead回調)人質,還是釋放該線程它調用的異步I/O發生在後臺?

如果Nito.AsyncEx的AsyncContext.Run真的阻塞,那麼Task.Run似乎是我唯一的選擇。有關如何阻止客戶端請求以防止線程池耗盡的任何建議?

回答

7

AsyncContext.Run的目的是阻止所有異步操作完成。它確實持有線程,直到發生這種情況。

我建議你重新考慮每一個假設至今:

  1. 你真的需要一個套接字服務器?在TCP/IP套接字周圍存在噸的問題。認真。 A lot其中。是否有任何你可以自主託管WebAPI嗎?這將是一個lot比套接字服務器更容易工作。
  2. 爲什麼您需要將工作推送到線程池線程? End*回調已在線程池線程上調用。
  3. 你確定你需要油門嗎?沒有任何代碼可以阻止充分動機的DoS攻擊。

如果你確定你需要實現自己的TCP/IP服務器,你不能做的工作在同步回調,並且你需要節制......再考慮Reactive ExtensionsTPL Dataflow。這兩個庫都有內置的可選節流。

+0

套接字服務器是少數和高吞吐量客戶端的低開銷需求。我們還支持HTTP,並且該代碼使用HttpTaskAsyncHandler,因此我不擔心可擴展性,並且具有更低吞吐量要求的客戶端。使用AsyncContext.Run不會爲我們的許多請求類型推回客戶端(它們會自己開始/結束......)。我對客戶端推遲的擔憂是沒有根據的擔心......我們正在控制誰連接到我們的套接字服務器。 Task.Run應該沒問題。 –

2

這取決於你的應用程序在做什麼。這裏是一些假設:

您從每個客戶端處理數據流

客戶端每次發送一些數據,你的服務器處理每封郵件,因爲它涉及在這種情況下,有可能是否定的。需要在單獨的線程中運行處理。當你阻塞時,TCP堆棧正在建立一個緩衝區供你閱讀。如果剩餘緩衝區大小太小,則TCP堆棧將向客戶端發送窗口大小警告。

客戶端可以發送消息的突發每個都需要冗長的處理

客戶端將消息發送到服務器中的脈衝串。每條消息都需要大量的時間來處理。以串行方式處理消息會導致大量的TCP重試,並且存在問題。在這種情況下,請關閉Task.Run,不要擔心耗盡線程池。

客戶可以發送更多的數據比你可以處理來自客戶

處理信息非常耗時,並且客戶可以發送現實比你可以處理更多的工作。在這種情況下,您可能需要某種特定於應用程序的流量控制。也許客戶端在發送消息之前需要輪詢服務器狀態。如果客戶無論如何都發送信息,你不得不忽視這些信息。

+0

感謝您的TCP/IP見解。我沒有這樣想過。如果我們被淹,我們會被淹。我們只需要有足夠的服務器來支持我們的客戶端負載。 –

相關問題