2011-06-02 15 views
9

我有一個WCF服務,並希望使用TCP綁定連接到它。這一切都很好,但你應該如何處理客戶?我注意到,如果你爲每個呼叫創建一個新的客戶端,它不會重新使用該通道,並且留下一堆TCP連接,直到它們超時。WCF TCP客戶端 - 如何使用它們的基本指導原則?

創建客戶端,調用其上的方法然後關閉它是否正常使用?

如果要重新使用連接,該怎麼辦?這有什麼限制?你能不同線程同時進行呼叫嗎?如果你不能,你必須做自己的連接池嗎?當重新使用連接時,在打電話之前是否必須檢查連接狀態,並在發生故障時進行清理?

回答

16

好吧,這是很多問題,情況真的有點複雜。當你創建一個客戶端時,你可以通過服務引用來完成,並從ClientBase<ServiceContract>獲得類,或者你可以使用ChannelFactory<ServiceContract>並手動創建通道(前一種情況在內部使用ChannelFactory)。

這與您的問題有關嗎?讓我們先看看真正的TCP連接。當您定義NetTcpBinding時,您可以設置其MaxConnections屬性(默認值爲10)。該屬性定義池連接的數量。這意味着如果您爲服務器創建客戶端通道並關閉通道,則連接不會立即終止。它在池中保持打開狀態,直到它被另一個打開的客戶端通道用於同一臺服務器,或者直到其空閒超時過期。您可以打開儘可能多的連接,但服務器允許您進行連接,但只有關閉相關客戶端通道後,纔會合併由MaxConnections定義的號碼。其他連接將立即終止。如果您創建了CustomBinding,則可以直接使用TCP傳輸,也可以控制空閒超時(我認爲默認值爲2分鐘)。只要相關的ChannelFactory未被破壞,連接就會被合併=每個應用程序使用一個ChannelFactoryClientBase內部執行)。

現在我們來談談渠道本身,因爲它與您的其他問題有關。 WCF不同於sessionfull和sessionless通道。 TcpTransportChannel是sessionfull。這意味着一旦你打開了頻道,你就創建了一個會話。會話意味着來自單個客戶端代理的所有請求默認始終由相同的服務實例(每個會話實例)提供服務。但實例默認爲單線程。這意味着您可以使用同一個代理擁有多個線程,但該服務將按順序處理請求。如果你想讓你的服務同時處理多個請求,你必須用[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple]來標記它。一旦你做了它,你就負責服務中的線程安全處理(多線程訪問相同的服務實例)。

偶爾的渠道有一個很大的缺點。服務上的任何故障或異常都會中斷通道,並且在您嘗試再次使用該通道後(通常處於故障狀態且無法使用該通道的情況除外),您通常會知道該通道。您必須始終正確處理這些情況,並且您必須正確關閉通道/代理,一旦您不想使用它們或在發生故障後中止它們。故障通道無法修復 - 必須中止,並且您必須創建新的代理/通道。如果不這樣做,我不確定連接是否返回到池中。

重複使用代理/通道取決於您正在構建的應用程序的類型。我絕對不會在Web應用程序中的多個請求中重複使用代理/通道,但在WinForm或WPF應用程序中重複使用絕對可以。

編輯:

ClientBase使用ChannelFactory內部。 ChannelFactory的使用方式隨着時間而改變。在.NET 3.0中,工廠是爲每個ClientBase實例創建的。由於.NET 3.5 WCF使用內部MRU緩存(最近使用),最多可以緩存32個最後使用的工廠。要利用此緩存,您必須使用不帶參數的代理構造函數,或使用endpointConfigurationNameremoteAddress/EndpointAddress。您不得在代碼中創建端點 - 這些代理不使用緩存。有關該主題的更多信息是here

+1

這是非常翔實的,謝謝。 – 2011-06-02 19:21:12

+0

Ladislav,如果使用SessionMode = NotAllowed定義了wcf服務,是否意味着該服務的客戶端服務代理不需要關閉? – 2011-06-02 19:29:38

+0

@Otter:如果使用'SessionMode = NotAllowed'定義服務,則不能使用任何會話通道,包括net.tcp。你應該總是關閉或中止代理。它實現了'IDisposable' - 一旦你看到它,你應該總是處理它。 – 2011-06-02 19:43:01

0

您是否在客戶端關閉了服務代理?

IService service = channelFactory.CreateChannel(); 

service.DoStuff(); 

((IContextChannel) service).Close(); 

這適用於所有WCF客戶端,不管綁定是否爲TCP。

欲瞭解更多信息,請參閱:http://msdn.microsoft.com/en-us/library/aa355056.aspx