閱讀841 返回首頁    go 阿裏雲 go 技術社區[雲棲]


控製並發訪問的三道屏障: WCF限流(Throttling)體係探秘[上篇]

WCF是一個基於多線程的消息監聽、接收和處理框架體係,能夠同時應付來自相同或者不同客戶端的服務調用請求,並提供完善的同步機製確保狀態的一致性。一方麵,我們期望WCF服務端能夠處理盡可能多的並發請求,但是資源的有限性決定了並發量有一個最大值。如果WCF不控製進入消息處理係統的並發量,試圖處理所有抵達的並發請求,一旦超過了這個臨界值,整個服務端將會由於資源耗盡而崩潰。

所以,我們需要在WCF的消息接收係統和消息處理係統之間設置一道道屏障,將流入消息處理係統的請求控製到一個最佳的範圍,以實現對現有資源的有效利用,從而達到確保服務的可用性和提高整體吞吐量的目的。WCF的流向限製(Throttling)為你設置了這些屏障,你可以根據現有的軟硬件環境對該閘門準入的並發流量進行動態的配置。我們先來看看如何進行限流控製。

一、如何進行限流控製

WCF對限流的控製是通過一個服務行為(Service Behavior)實現的,該服務行為類型名稱為ServiceThrottlingBehavior,定義在System.ServiceModel.Description命名空間下。我們先來看看ServiceThrottlingBehavior的定義:

   1: public class ServiceThrottlingBehavior : IServiceBehavior
   2: {
   3:     public ServiceThrottlingBehavior();
   4:     void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters);
   5:     void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase);
   6:     void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase);
   7:   
   8:     public int MaxConcurrentCalls { get; set; }
   9:     public int MaxConcurrentInstances { get; set; }
  10:     public int MaxConcurrentSessions { get; set; }
  11: }

從上麵的代碼中我們可以看到,ServiceThrottlingBehavior定了三個整型的屬性:MaxConcurrentCallsMaxConcurrentInstancesMaxConcurrentSessions。它們分別代表流量控製的三個閥值,簡單地說,我們所說的限流就是通過設置這三個值控製能夠處理的並發量。這三個屬性所代表的數值是針對某個ServiceHost而言的。接下來,我們來簡單地說說這個閥值具體代表什麼含義:

  • MaxConcurrentCalls當前ServiceHost能夠處理的最大並發消息數量,默認值為16;
  • MaxConcurrentInstances當前ServiceHost允許存在的InstanceContext的最大數量,默認值為26;
  • MaxConcurrentSessions當前ServiceHost允許的最大並發會話數量,默認值為10。

由於控製流量的ServiceThrottlingBehavior是一個服務行為,我們可以通過編程和配置的方式對上述的三個允許的最大並發值進行設置。

二、通過編程的方式設置最大並發值

由於控製流量的ServiceThrottlingBehavior是一個服務行為,我們在進行服務寄宿(自我寄宿)的時候,直接通過編程的方式將該服務行為添加到服務描述的行為列表之中。在下麵的服務寄宿代碼中,我們將CalculatorService服務的MaxConcurrentCalls、MaxConcurrentSessions和MaxConcurrentInstances分別設置成50、30和20。需要注意的是,所有的設置必須在開啟ServiceHost(調用Open方法)之前完成方能生效。在ServiceHost開啟的狀態下的什麼限流設置均是無效的,至於具體的原因,可以參考《WCF技術剖析(卷1)》第7章關於服務描述和服務寄宿過程相關內容。

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {
   3:     ServiceThrottlingBehavior throttlingBehavior = host.Description.Behaviors.Find<ServiceThrottlingBehavior>();
   4:     if (null == throttlingBehavior)
   5:     {
   6:         throttlingBehavior = new ServiceThrottlingBehavior();
   7:         host.Description.Behaviors.Add(throttlingBehavior);
   8:     }
   9:  
  10:     throttlingBehavior.MaxConcurrentCalls = 50;
  11:     throttlingBehavior.MaxConcurrentInstances = 30;
  12:     throttlingBehavior.MaxConcurrentSessions = 20;
  13:  
  14:     host.Open();
  15:     Console.Read();
  16: }

不過我們很少通過編程的方式進行限流的控製,更多地,還是采用配置的方式。

三、通過配置的方式設置最大並發量

基本上所有服務行為均可用通過配置的方式應用到相應的服務上麵,上述的關於限流的三個最大並發量通常都是采用配置的方式進行設置的。對於係統定義的服務行為來說,WCF均會為其定義相應的配置元素。同理,如果我們希望通過配置的方式應用自定義的服務行為,我們也需要定義相應的配置元素。ServiceThrottlingBehavior的配置元素定義在ServiceThrottlingElement類型中,在具體介紹限流配置之前,我們不妨先來看看ServiceThrottlingElement的定義:

   1: public sealed class ServiceThrottlingElement : BehaviorExtensionElement
   2: {
   3:     //其他成員
   4:     [ConfigurationProperty("maxConcurrentCalls", DefaultValue = 16)]
   5:     public int MaxConcurrentCalls { get; set; }
   6:  
   7:     [ConfigurationProperty("maxConcurrentInstances", DefaultValue = 26)]
   8:     public int MaxConcurrentInstances { get; set; }
   9:  
  10:     [ConfigurationProperty("maxConcurrentSessions", DefaultValue = 10)]
  11:     public int MaxConcurrentSessions { get; set; }
  12: }

ServiceThrottlingElement的定義暴露了ServiceThrottlingBehavior對應配置項的結構。實際上,整個配置項由單純的三個配置屬性構成,它們分別代表上述的三的最大並發值。此外,ServiceThrottlingElement還透露給我們 一個重要的信息,就是這三個最大並發量的默認值。MaxConcurrentCalls、MaxConcurrentInstances和MaxConcurrentSessions在默認的情況下的值為16、26和10,這和上麵的介紹是一致的。

如果通過配置的方式控製限流,我們隻需要將ServiceThrottlingBehavior對應的配置,即通過ServiceThrottlingElement定義的配置元素定義在相應的服務行為配置中即可,相應配置項的名稱為serviceThrottling。通過下麵的配置,我將CalculatorService的三個最大並發量(MaxConcurrentCalls、MaxConcurrentInstances和MaxConcurrentSessions)分別設置為50、30和20。

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <system.serviceModel>
   4:       <behaviors>
   5:         <serviceBehaviors>
   6:           <behavior name="throttlingBehavior">
   7:             <serviceThrottling maxConcurrentCalls="50" maxConcurrentInstances="30" maxConcurrentSessions="20" />
   8:           </behavior>
   9:         </serviceBehaviors>
  10:       </behaviors>     
  11:         <services>
  12:             <service behaviorConfiguration="throttlingBehavior" name="Artech.ConcurrentServiceInvocation.Service.CalculatorService">
  13:                 <endpoint address="https://127.0.0.1:8888/calculatorservice" binding="basicHttpBinding" contract="Artech.ConcurrentServiceInvocation.Service.Interface.ICalculator" />
  14:              </service>
  15:         </services>
  16:     </system.serviceModel>
  17: </configuration>

通過上麵介紹,我們知道了如何通過編程和配置的方式設置相應的最大並發量,從而指導WCF的限流體係按照你設定的值對並發的服務調用請求進行限流控製。那麼,在WCF框架體係內部,整個過程是如何實現的呢?請聽下回分解。


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-27 15:04:40

  上一篇:go  大話MVP
  下一篇:go  控製並發訪問的三道屏障: WCF限流(Throttling)體係探秘[下篇]