285
windows
WCF 4.0一個鮮為人知的改變[兼書名征集]
本篇文章介紹可以算是WCF 4.0基於限流(Throttling)的新特性,是在修訂《WCF技術剖析(卷1)》的時候編寫演示實例的時候發現的。這個特性沒有出現在官方文檔上麵,至少在MSDN上的相關介紹依然是錯誤的。
WCF是一個基於多線程的消息監聽、接收和處理框架體係,能夠同時應付來自相同或者不同客戶端的服務調用請求,並提供完善的同步機製確保狀態的一致性。一方麵,我們期望WCF服務端能夠處理盡可能多的並發請求,但是資源的有限性決定了並發量有一個最大值。如果WCF不控製進入消息處理係統的並發量,試圖處理所有抵達的並發請求,一旦超過了這個臨界值,整個服務端將會由於資源耗盡而崩潰。
所以,我們需要在WCF的消息接收係統和消息處理係統之間設置一道道屏障,將流入消息處理係統的請求控製到一個最佳的範圍,以實現對現有資源的有效利用,從而達到確保服務的可用性和提高整體吞吐量的目的。WCF的流向限製(Throttling)為你設置了這些屏障,你可以根據現有的軟硬件環境對該閘門準入的並發流量進行動態的配置。
WCF對限流的控製是通過一個服務行為(Service Behavior)實現的,該服務行為類型名稱為ServiceThrottlingBehavior,定義在System.ServiceModel.Description命名空間下。ServiceThrottlingBehavior定了三個整型的屬性:MaxConcurrentCalls、MaxConcurrentInstances和MaxConcurrentSessions。它們分別代表流量控製的三個閥值,簡單地說,我們所說的限流就是通過設置這三個值控製能夠處理的並發量。
基於.NET Framework 4.0的MSDN對上述三個限流閥值是這樣介紹的:
- MaxConcurrentCalls:獲取或設置一個值,該值指定整個 ServiceHost 中正在處理的最多消息數,默認值為 ;
- MaxConcurrentInstances:獲取或設置一個值,該值指定服務中可以一次執行的最多 InstanceContext 對象數,默認值為 ;
- MaxConcurrentSessions:獲取或設置一個指定 ServiceHost 對象可一次接受的最多會話數的值,默認值為。
通過ServiceThrottlingBehavior的MaxConcurrentSessions屬性表示的最大並發會話數默認為10,果真如此嗎?我們不妨通過一個簡單的實例來驗證。照理以計算服務為例,下麵是契約接口和服務類型的定義。
1: [ServiceContract(Namespace ="https://www.artech.com/")]
2: public interface ICalculator
3: {
4: [OperationContract]
5: double Add(double x, double y);
6: }
7:
8: public class CalculatorService : ICalculator
9: {
10: public double Add(double x, double y)
11: {
12: return x + y;
13: }
14: }
我們采用控製台程序對CalculatorService進行寄宿,如下所示的是采用的配置:
1: <configuration>
2: <system.serviceModel>
3: <services>
4: <service name="Artech.WcfServices.Service.CalculatorService">
5: <endpoint address="https://127.0.0.1:3721/calculatorservice"
6: binding="ws2007HttpBinding"
7: contract="Artech.WcfServices.Service.Interface.ICalculator"/>
8: </service>
9: </services>
10: </system.serviceModel>
11: </configuration>
從上麵的配置中我們知道寄宿的服務具有一個唯一的基於WS2007HttpBinding(支持會話)的終結點。客戶端采用相應的配置並通過如下的代碼進行服務的調用。
1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice"))
2: {
3: bool stop = false;
4: for (int i = 0; i < 1000 && !stop; i++)
5: {
6: ICalculator calcultor = channelFactory.CreateChannel();
7: try
8: {
9: calcultor.Add(1, 2);
10: Console.WriteLine("第{0}個服務代理調用成功!", i + 1);
11: }
12: catch (Exception ex)
13: {
14: Console.WriteLine("出現異常:{0}", ex.Message);
15: stop = true;
16: }
17: }
18: }
在上麵這段用於進行服務調用的代碼中,我們通過基於客戶端終結點配置名稱創建的ChannelFactory<TChannel>對象創建了1000個服務代理進行用其進行1000次服務調用。當上麵這個實例運行的時候,客戶端控製台將會出現如下的輸出結果。實例程序清晰地反映了這樣的事實:雖然我們通過不同的服務代理對象進行了1000次服務調用,但是隻有前麵兩百次是成功的。如果默認的最大並發會話數是10的話,隻有前麵10次服務調用會成功。
1: 第1個服務代理調用成功!
2: 第2個服務代理調用成功!
3: ...
4: 第199個服務代理調用成功!
5: 第200個服務代理調用成功!
6: 出現異常:請求通道在等待 00:00:59.9844000 以後答複時超時。增加傳遞給請求調用的超時值,或者增加綁定上的 SendTimeout 值。分配給此操作的時間可能已經是更長超時的一部分。
通過上麵演示的實例,我們發現默認情況下允許200次並發會話,那麼MaxConcurrentSessions的默認值不是10,而是200嗎?由於三個限流屬性值是通過配置的方式進行指定的,所以要了解它們的默認值,隻需要了解對應的配置元素類型的定義即可。下麵是ServiceThrottlingBehavior對應的配置元素ServiceThrottlingElement 的定義。
1: public sealed class ServiceThrottlingElement : BehaviorExtensionElement
2: {
3: //...
4: [ConfigurationProperty("maxConcurrentCalls", DefaultValue=0x10)]
5: public int MaxConcurrentCalls { get; set; }
6:
7: [ConfigurationProperty("maxConcurrentInstances", DefaultValue=0x74)]
8: public int MaxConcurrentInstances { get; set; }
9:
10: [ConfigurationProperty("maxConcurrentSessions", DefaultValue=100)]
11: public int MaxConcurrentSessions { get; set; }
12: }
13:
從應用在三個配置屬性上ConfigurationPropertyAttribute特性可以看出,MaxConcurrentCalls、MaxConcurrentInstances 和MaxConcurrentSessions 的默認值為16、116和100,而不是MSDN所說的16、26和10。
既然MaxConcurrentSessions的默認值為100,那麼我們的實例為什麼會有200次成功的並發訪問呢?原因很簡單:這三個限流閥值都是針對單個處理器的,由於運行機器采用雙核處理器,自然就是200。
前後花了一年多的時間,終於將《WCF技術剖析(卷2)》完成了,不過在對《卷1》進行修訂的時候又對現有的內容作了較大的改動。這不僅僅添加了許多新的內容,還大刀闊斧的刪除和修改了現有的一些內容。正是由於改動較大,編輯建議換個名字並出上下卷。由於我個人還未給新書想到一個好的名字,希望通過本貼進行征名。你提供的書名一旦采用,在新書出版時我個人會贈送本書的上下兩冊。
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-26 14:04:55
上一篇:
Java和Spring的跨版本升級
下一篇:
像TransactionScope一樣使用DbTransaction
在三四線城市怎麼做新零售?我們找到了一個“農村包圍城市”的樣本
機器人吃人時代,運維和測試崗位如何開啟"第二春"?
OSS移動開發實戰2 (30分鍾快速搭建移動應用上傳回調服務)
HTML5新漏洞被發現:垃圾數據可將用戶硬盤塞滿
請收下這份關於人工智能的根目錄——博客整理係列(一)
10月25日, win8 來了
MySQL 備份和恢複
Nodejs進階:Express常用中間件body-parser實現解析
Android攝像頭開發完美demo---(循環聚焦,縮放大小,旋轉picture,查詢支持的picturesize, ImageButton按鍵效果)
Java常用類庫--觀察者設計模式( Observable類Observer接口)