整個可靠會話的機制是完全在信道層實現的而整個信道層的最終締造者就是綁定所以可靠會話編程是圍繞著綁定進行的《上篇》對實現可靠會話的綁定元素已經如何使用系統綁定實現可靠會話進行了介紹下篇將和你探討WCF可靠會話編程模型余下兩個主題自定義綁定和對消息傳遞的強制約束一為自定義綁定的可靠會話進行設置
綁定是一系列綁定元素的有序組合但是系統綁定為我們提供適應了某種典型通信環境的綁定元素組合方式可以看成是套餐但是如果套餐不符合您的胃口你應該查看菜單點你喜歡的菜肴自定義綁定給了你最大的自由度是能能夠根據具體的通信環境自由組合需要的綁定元素
關於可靠會話如果你采用系統綁定你定制的范圍其實很窄(僅限於InactivityTimeout和Ordered屬性)但是如果你采用自定義綁定由於你操作的對象就是ReliableSessionBindingElement綁定元素所有你可以對所有的選項進行自由配置雖然我們可以通過編程的方式之間將創建的ReliableSessionBindingElement對象添加到綁定的綁定元素集合中但是我們還是強烈建議你通過配置的方式來對可靠會話的相關選項進行定制為了讓讀者能夠了解某個特性的配置我個人覺得最好的辦法就是直接讓讀者看看相關配置節的定義WCF將ReliableSessionBindingElement的配置定義在如下所示的ReliableSessionElement類型中通過ReliableSessionElement你不但可以了解可靠會話相關的配置屬性還可以了解到其他相關的配置信息比如最大值最小值和默認值等你可以驗證一下它們是否和我們前面的介紹一致
: public sealed class ReliableSessionElement : BindingElementExtensionElement
: {
: [ConfigurationProperty(acknowledgementInterval DefaultValue=::) TypeConverter(typeof(TimeSpanOrInfiniteConverter)) ServiceModelTimeSpanValidator(MinValueString=::)]
: public TimeSpan AcknowledgementInterval { get; set; }
: public override Type BindingElementType { get; }
: [ConfigurationProperty(flowControlEnabled DefaultValue=true)]
: public bool FlowControlEnabled { get; set; }
: [ServiceModelTimeSpanValidator(MinValueString=::) TypeConverter(typeof(TimeSpanOrInfiniteConverter)) ConfigurationProperty(inactivityTimeout DefaultValue=::)]
: public TimeSpan InactivityTimeout { get; set; }
: [IntegerValidator(MinValue= MaxValue=x) ConfigurationProperty(maxPendingChannels DefaultValue=)]
: public int MaxPendingChannels { get; set; }
: [IntegerValidator(MinValue=) ConfigurationProperty(maxRetryCount DefaultValue=)]
: public int MaxRetryCount { get; set; }
: [ConfigurationProperty(maxTransferWindowSize DefaultValue=) IntegerValidator(MinValue= MaxValue=x)]
: public int MaxTransferWindowSize { get; set; }
: [ConfigurationProperty(ordered DefaultValue=true)]
: public bool Ordered { get; set; }
: protected override ConfigurationPropertyCollection Properties { get; }
: [TypeConverter(typeof(ReliableMessagingVersionConverter)) ConfigurationProperty(reliableMessagingVersion DefaultValue=WSReliableMessagingFebruary)]
: public ReliableMessagingVersion ReliableMessagingVersion { get; set; }
: }
在對自定義綁定進行配置的時候我們只需要在綁定元素集合中添加ReliableSessionElement配置元素並對相應的配置屬性進行設置即可下面的XML是服務端的WCF配置我們采用自定義綁定作為終結點綁定該自定義綁定由三個綁定元素組成通過TextMessageEncodingElement對消息進行基於文本編碼通過TransportBindingElement采用協議進行傳輸在兩者之間的ReliableSessionBindingElement實現了對消息的可靠傳輸在bindings/binding/reliableSession配置節中我對所有的屬性進行的顯式設置
: <?xml version= encoding=utf ?>
: <configuration>
: <systemserviceModel>
: <bindings>
: <customBinding>
: <binding name=reliableSessionBinding>
: <textMessageEncoding />
: <reliableSession acknowledgementInterval=:: flowControlEnabled=false inactivityTimeout=:: maxPendingChannels= maxRetryCount= maxTransferWindowSize= reliableMessagingVersion=WSReliableMessaging />
: <Transport />
: </binding>
: </customBinding>
: </bindings>
: <services>
: <service name=ArtechMessageInspectionReceiverCalculatorService>
: <endpoint address=:///calculatorservice
: binding=customBinding bindingConfiguration=reliableSessionBinding
: contract=ArtechMessageInspectionReceiverICalculator />
: </service>
: </services>
: </systemserviceModel>
: </configuration>
看到這裡我想有的讀者會問這麼一個問題一個綁定可以有一系列綁定元素構成那麼ReliableSessionBindingElement應該置於何處呢?要搞清楚這個問題需要對WCF的綁定模型有一個大致的了解綁定的目的創建一個用於處理和傳輸消息的信道棧信道在信道棧的順序決定於對應的綁定元素的排列順序可靠會話將客戶端和服務端通過ReliableSessionBindingElement創建的可靠信道作為分界線並在它們之間提供消息可靠傳輸保障也就是說信道棧中位於可靠信道之下(靠近傳輸信道)部分存在於可靠會話的勢力范圍之中而上面部分則脫離可靠會話的管轄范圍這也是在前面給出的實例中為何我們將用於模擬不可靠網絡的綁定元素配置到ReliableSessionBindingElement之下的原因所在
由於在實際的應用中我們主要通過可靠會話為網絡傳輸的不穩定性提供可靠傳輸的保障所以我們一般將ReliableSessionBindingElement配置到傳輸綁定元素之上至於消息編碼綁定元素是置於ReliableSessionBindingElement之上或者之下均沒有關系如果你認真閱讀過《WCF技術剖析(卷)》第章你會知道消息編碼綁定元素並不參與信道的創建而是將編碼的方式傳入綁定上下文傳輸信道據此采用相應的編碼方式進行消息的編碼或者解碼此外為了保證可靠會話的安全性我們需要將可靠會話綁定到一個通過安全會話信道提供的安全上下文中在這種情況下ReliableSessionBindingElement需要位於安全綁定元素之上
我們說WCF可靠會話編程完全就是圍繞著綁定進行的可以說得更加具體點是圍繞著ReliableSessionBindingElement進行的除了對系統綁定或者自定義綁定進行設置關於可靠會話編程模型還涉及到一個契約行為DeliveryRequirementsAttribute我們可以利用DeliveryRequirementsAttribute對服務契約進行一些基於可靠會話的強制性約束
二通過DeliveryRequirementsAttribute對可靠會話進行強制約束
DeliveryRequirementsAttribute這個自定義特性實際上是一個契約行為我們可以將其應用到服務契約類型或者服務類型上強制要求相應終結點綁定必須滿足設定的關於消息傳輸方面的要求DeliveryRequirementsAttribute定義如下其中忽略了實現IContractBehavior接口的個方法
: [AttributeUsage(AttributeTargetsInterface | AttributeTargetsClass AllowMultiple=true)]
: public sealed class DeliveryRequirementsAttribute : Attribute IContractBehavior IContractBehaviorAttribute
: {
: //其他成員
: public QueuedDeliveryRequirementsMode QueuedDeliveryRequirements { get; set; }
: public bool RequireOrderedDelivery { get; set; }
: public Type TargetContract { get; set; }
: }
DeliveryRequirementsAttribute定義了兩個屬性QueuedDeliveryRequirements和RequireOrderedDelivery分別代表相應的終結點綁定必須滿足的兩個要求隊列傳遞和有序交付隊列傳遞及采用消息隊列(即MSMQ)的機制進行消息傳遞在下一個系列中我們會對隊列服務進行單獨介紹而有序交付就是本章涉及的可靠消息傳輸的有序交付IContractBehavior屬性是對IContractBehaviorAttribute的實現當我們將DeliveryRequirementsAttribute特性應用到某個實現了多個服務契約的服務上時可以指定設置的消息傳遞要求是針對某個服務契約
在服務端當基於服務類型創建的ServiceHost對象被開啟的時候如果相應終結點綁定無法滿足通過將DeliveryRequirementsAttribute特性應用到服務契約類型或者服務類型上設置的關於隊列傳輸或者有序交付的要求時會拋出一個InvalidOperationException異常如果將DeliveryRequirementsAttribute特性應用到服務契約上客戶端在試圖開啟ChannelFactory<TChannel>對象的時候同樣會驗證用於服務調用的終結點綁定是否滿足相應的要求如果無法滿足同樣會拋出一個InvalidOperationException異常
舉個例子假設我們定義如下一個IOrderService的服務契約用於處理訂單在IOrderService接口上應用了DeliveryRequirementsAttribute特性並將RequireOrderedDelivery設置成True要求終結點綁定強制開啟可靠消息的有序交付特性
: [ServiceContract(Namespace = ://)]
: [DeliveryRequirements(RequireOrderedDelivery = true)]
: public interface IOrderService
: {
: [OperationContract]
: void Process(Order order);
: }
現在我們對實現該服務契約的服務進行寄宿相應的配置如下從中我們可以看到我們采用WSBinding作為終結點的綁定通過綁定配置開啟了可靠會話但是將ordered屬性配置成False
: ?xml version= encoding=utf ?>
: <configuration>
: <systemserviceModel>
: <bindings>
: <wsBinding>
: <binding name=reliableSessionBinding>
: <reliableSession ordered=false enabled=true />
: </binding>
: </wsBinding>
: </bindings>
: <services>
: <service name=ArtechMessageInspectionReceiverOrderService>
: <endpoint address=://:/OrderService binding=wsBinding
: bindingConfiguration=reliableSessionBinding contract=ArtechMessageInspectionReceiverIOrderService />
: </service>
: </services>
: </systemserviceModel>
: </configuration>
當進行服務寄宿的時候你會得到如圖所示的InvalidOperationException異常當你進一步看清具體的異常消息的時候你可能第一感覺就是作者把圖片弄錯了因為終結點綁定部滿足DeliveryRequirementsAttribute設定的關於有序交付的要求和隊列傳遞根據就不相關但是圖就是真實運行後的截圖這是WCF自身的一個Bug在《WCF 中關於可靠會話的BUG!!》這篇文章中有對該Bug的原因的深入探討
圖 終結點綁定不能滿足DeliveryRequirementsAttribute設定的要求導致的異常
到此為止關於WCF可靠會話編程方面的內容就到此為止下一篇我們對可靠會話架構體系進行進一步的挖掘對可靠會話具體的實現原理進行深入剖析敬請期待
From:http://tw.wingwit.com/Article/program/net/201311/12872.html