說說WCF中的可信賴會話
幾天前,有朋友在QA上問有關WCF中可信賴會話(ReliableSession)的問題。今天重新梳理一下,主要目就是真正的弄清楚可信賴會話的作用,方法和現實意義。
正如那位的疑惑一樣,很多做過WCF開發的朋友,也都對ReliableSession不太理解。查閱msdn,可以發現ReliableSession是System.ServiceModel命名空間下的一個類。主要的作用如下所述:
| 提供對可靠會話綁定元素屬性的便捷訪問,這些屬性是在使用系統提供的綁定之一時提供的。 |
包括兩個重要的屬性(Property)成員:
1.InActivityTimeout
文檔中的說明是:獲取或設置服務在關閉之前保持非活動狀態的時間間隔。
說白了一點呢,就是如果服務停留多長時間沒有工作,那我們就關閉他(嘿嘿,有點像公司對待員工一樣,偶 爾休息一下子,不干活還行,時間長了,老板會炒你魷魚的哦!)
2.Ordered
文檔中說明為:獲取或設置一個值,該值指示消息傳遞是否必須保持與消息發送一致的順序。
任何一方,無論是客戶端發送請求消息(Request Message),還是服務端發送相應消息(Response Message)。發送出來的消息都有先后次序,而接收方在接收這些消息的時候,有時候會出現錯位的現象,有的消息可能后發先至,而有的可能先發后至,這就影響了通訊雙方正常的交互。產生這樣現象的主要的原因有兩點:
1)未使用可靠連接協議,使得在傳輸層中出現類似現象
2)雖然試用了可靠連接協議,但在發送端或者接收端的通道中(Channel)發送或者接收有順序問題
tcp協議用于解決第一個問題,而ReliabelSession的Ordered正可以解決第二個問題。
在WCF的缺省綁定中,只有以下幾種支持或者默認打開了ReliableSession的功能,他們為:
wsHttpBinding
wsDualHttpBinding
wsFederationHttpBinding
netTcpBinding
其中netTcpBinding,wsHttpBinding,wsFederationHttpBinding中的ReliableSession屬性均是RelibaleSession的一個派生類型,名為OptionRelibaleSession,也就是提供了可選的功能。相比ReliableSession,OptionReliableSession僅僅多了一個屬性:Enabled,用這個屬性可以指示是否開啟可信會話。true代表開啟,false的話就不開啟了,那么對InActivityTimeout和Ordered的設置將無效。這里面wsHttpBinding和wsFederationHttpBinding其實都繼承自wsHttpBindingBase,所在在討論ReliableSession的時候,這兩個Binding表現一致。而對與wsDualHttpBinding則默認的將ReliableSession屬性的Ordered設置為了true.也就是說wsDualHttpBinding是缺省支持可信會話的。而ReliableSession的InActivityTimeout默認情況是是10分鐘。
在上面對ReliableSession的描述中,我們可以清楚的看到便捷描述的字樣。這是怎么一回事情呢?原來ReliableSession這個class并沒有缺省的構造函數,而只是有一個接收ReliableSessionBindingElement類型的構造,這就引出了相比更重要的角色:ReliableSessionBindingElement. 下面就來說說它,并說說它和ReliableSession之間,和Binding之間有著怎樣的聯系
ReliableSessionBindingElement:
BindingElement的一個派生類,也就是說它是一個綁定元素。熟悉WCF架構或者讀過大俠Artech<<WCF后續之旅>>的朋友,應該知道WCF的Foundation是如何的。不知道的也沒有關系,我也來說說大概,WCF暴露給外界的是終結點(EndPoint),在WCF基礎部門,一個終結點又有主要的三部分組成:1)地址 (Address) 2) 綁定Binding 3) 契約 (Contract),也就是傳說中的"ABC",呵呵。地址相對比較簡單,契約是用于WCF框架留給開發人員創建具體業務邏輯代碼的地方,而WCF中,最核心,也是最具有魅力的地方就在于Binding.對于Bind的認識可以幫助我們更清楚的解析WCF的一些特征。一個Binding會維護一個BindElement的集合,這個在Binding的派生類CustomBinding中作為Elements屬性來表示,Elements是一個Collection<BindingElement>的類型。在Elements中的每個BindingElement都有著各自的功能,比如在NetTcpBinding中,就存在這這樣的一種BindingElement組織方法
處于第一個位置的是TransactionFlowBindingElement,如果支持ReliableSession的話,那么ReliabelSessionElement就處于NetTcpBinding中的第二個位置 ,如果不支持ReliableSession,則此元素將存在,緊接著的是SecurityBindingElement,隨后是BinaryMessageEncodingBindingElement用于消息編碼,隨后是用于通訊安全的Element,它的類型由NetTcpSecurity屬性來決定。最后是TcpTransportBindingElement.而且需要注意的是,每一個Binding中,最后一個Element必須都為TransportBindingElement。在上面的所談論到的BindingElement中,各自都有各自的功能,他們各司其職,Binding只是將他們緊密的組織在了一起。但每個BindingElement是不是真正的執行者呢?NO!他也是一個組織者,他組織的對象主要有兩個:
ChannelFactory
ChannelListener
其中ChannelFactory是作為客戶端使用的,而ChannelListener是作為服務端時候使用的。不幸的是,無論是ChannelFactory還是ChannelListener,也都不是真正的執行者,他們是IChannel的工廠類。真正在里面辛勤勞動的還是實現了IChannel的Channel對象。至于說ChannelFactory和ChannelListener是如何組織Channel的,和Channel的一些具體行為,篇幅有限,不再贅述。為了給大家一個詳細的認識,畫了幾幅圖:
接下來,我們分別放大終結點,將終結點的詳細構造用圖形表達出來:
BindingElement管理兩個對象ChannelFactory和ChannelListener
這一級的表示圖如下:
上面說了這么多有關WCF基礎架構的(Infrastructor)的,下面返回再來看ReliableSessionElement,首先我們就會從宏觀上理解它了,它就是一個類型的BindingElement,它包含如下的主要屬性成員:
InActivityTimeout
Ordered
MaxRetryCount
上面的幾個重要屬性中,InActivityTimeout和Ordered兩個屬性和ReliabelSession的作用是一致的。而MaxRetryCount用于如果指定了使用可信通道,也就是Ordered為True的時候,當可信通道沒有收到消息的時候,通過在基礎通道上調用Send方法重發此消息的次數
ReliabelSession是ReliableSession的一種快捷表示,原因是在構造Binding的時候的,會首先構造一個ReliableSessionElement對象,然后將這個對象的引用傳遞給ReliableSession對象,這樣其實ReliableSession對象其實就是ReliableSessionElement對象中的一部分數據,只是由于暴露ReliabelSessionElement給開發人員,有些不優雅,所以單獨設計了這么一個ReliableSession的類,用于快捷表示ReliableSessionElement.
好了,從理論上講,我所認識的ReliableSession說的差不多了。下面借鑒一個有趣的實例來檢驗一下ReliableSession到底有何作用。使用它和不使用它有何異同。
這個試驗的構思來源于WindowsCommunicationFoundation Unleashed<<WCF揭秘>>一書。傳說中,這個示例的構思來自于WCF項目經理Shy Cohen.他的思路是將1張圖片分成100分,每一份作為一個消息發送給接受者,接受者在根據接收到的消息產生繪制圖像。而在發送的過程中,通過插入一個自定義的BinddingElement,將數據分概率的截取下來不予發送。這時候,如果不采用ReliableSession,那么接收方收到的圖像是不完整的。有一小部分缺失,而如果采用了ReliableSession呢,那盡管發送的時候,在被攔截的時候的當此發送中,消息的確沒有發出去,但基礎通道會嘗試進行重發,重發的包有很小幾率會再次被攔截,如果再次被攔截,那么會再次重發,那么被攔截的幾率會更小,這時候接受者收到的是完整的圖像。
在Shy Cohen的試驗中,由三個組件構成:
發送者(Sender)
接受者 (Receiver)
對照者 (Router)
他們之間的關系如圖:
對照者能夠指定發送者漏包的比率,比如1%,10%等,發送者與對照者之間一直使用的是沒有可靠連接的會話,試驗的步驟是:
1)首先將接受者和發送者都設置為不接受可信賴會話。設置的方法就是將各自config中的添加<reliableSession Ordered="false"/>。此時,運行三個程序,在對照者中調整丟包頻率,在發送者中選擇一幅圖片,注意:最好是它例子中給定的Seattle.jpg,因為其他圖片可能因為過大,而造成異常。選擇圖片之后,點擊發送。此時,在對照者和接受者中會顯示出接收到的包數目,丟失的數目,和發送的數目。如果設置的比率比較大的話,會發現接受者所形成的圖像有明顯缺失。對照者中的丟包數目也大于0
通過這一步驟,可以得出結論,如果沒有采用可信會話,消息在發送的過程中是有可能丟失或者錯位的,盡管我們使用的是Tcp協議
2)將接受者和發送者config中的配置更改為<reliableSession Ordered="true"/>,此時,再次選擇圖片,發送,會發現在偶爾的幾次中,發送操作進行的非常遲鈍,但發送完成之后,接受者的圖像是完整的,而對照者仍然存在著一些丟失的消息。
通過這個試驗,能清晰的表達可信會話的功能和意義。我這里這是做了一個介紹,更多更詳細的請閱讀<<WCF揭秘>>第四章。
出處:http://jillzhang.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

浙公網安備 33010602011771號