1. 程式人生 > >快速入門系列--WCF--02消息、會話與服務寄宿

快速入門系列--WCF--02消息、會話與服務寄宿

abc align bsp 不同的 cpu .org 程序 伸縮 網絡

經過WCF基礎的ABC學習,已經可以構建簡單的WCF的服務,使用不同的服務地址和綁定類型,根據業務提供所需的服務契約。但不禁想問,服務所使用的消息報文是什麽樣的形式麽?蘊含什麽樣內容呢?WCF服務是否支持會話?WCF所提供的服務是單例的呢還是單調的呢?服務寄宿和客戶端代理是如何實現的呢?接下來,將以這些問題為線索進行深入學習,包容包括XML序列化與SOAP消息、會話與實例、服務寄宿與客戶端代理。

技術分享

可以這麽說,整個WCF服務都是構建在SOAP消息的基礎上的,而SOAP消息是建立在XML這種跨平臺的數據格式的基礎上的,有人可能會說WCF也支持Restful風格的服務並支持json格式的數據,的確是這樣,但這只是當時情況下的折中。現在可以發現,基本上以json格式為基礎的restful服務其實都轉化為了WebAPI項目,而不是WCF。所以仍然可以認為,WCF的初衷是為企業提供可靠的分布式SOA服務的,而WebAPI的出現,為WCF的不足之處進行了有利補充,用於提供公共的對外服務,更加的輕量級並與當下的互聯網環境結合的更妥當。說了這麽多,目的只有一個就是學習WCF一定要意識到學習SOAP相關知識的重要性,因為整個WS-*網絡服務標準協議簇都建立在其之上,而與SOAP的基礎XML相關的知識也就同樣凸顯出來了,其中最重要的就是XML的序列化,接下來通過圖表進行簡要的介紹。

知識點 詮釋
消息格式化器MessageFormatter WCF中消息的序列化和反序列化操作依賴該組件,服務器端(DispatchMessageFormatter)和客戶端(ClientMessageFormatter),此外還可以通過實現IDispatch/ClientMessageFormatter接口自定義消息格式化器,例如壓縮消息。
序列化器的選擇 包括DataContractSerializer和XmlSerializer,後者存在多年,簡單有效;前者是WCF專門構建的,可以用於復雜場景,是默認選擇。
數據契約的等價性 在生產系統中,會出現修改接口的場景(例如添加刪除接口方法數據成員,盡量避免),可能會對原有系統造成破壞,可以通過使用系統提供的擴展字段來避免這樣的情況發生,附上一個可空的例子。 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:tns="http://www.sory.com"> <xs:complexType name="Customer"><xs:sequence> <xs:element name="Address" nillable="true" type="xs:string"/></xs:sequence> </xs:complexType> </xs:schema>
數據契約和數據成員 DataContractAttribute和DataMemberAttribute的本質是通過反射進行序列化為數據流,WCF支持集合數據和字典數據的數據契約

.此外,XML的文檔結構描述方式,xsd文件和原來的DTD文件的相關知識也註意學習,可以參看http://utopialxw.iteye.com/blog/1218622。

接下來的消息部分,內容很多,但實際中比較重要的僅僅是WS-Addressing的相關屬性和在消息頭中添加安全信息。WS-Addressing的相關屬性如下表所示。

屬性名 詮釋
<To> 以URI的形式表示消息發送的目標地址,如果沒有顯示指定,則采用默認地址http://www.w3.org/2005/08/addressing/anonymous
<From> 以終結點引用的形式表示源終結點,不太常用
<ReplyTo> 以終結點引用的形式表示接受/回復消息的終結點,若未指定,則采用默認地址http://www.w3.org/2005/08/addressing/anonymous
<Action> * 以URI的形式表示消息的意圖,比如調用服務操作
<MessageID> 以URI的形式表示消息的唯一標識
<RelatesTo> 表示關聯消息的<MessageID>,比如將恢復消息的<RelatesTo>屬性設置為請求消息的<MessageID>,從而關聯兩者
<ReferenceParameters> 可以以任何XML元素提供額外的輔助信息

另一個為添加安全信息:messageProperty.Headers.Add(HttpRequestHeader.Cookie, "SecurityToken="+securityToken);

常見的,XML編碼通常設計XmlDictionary,XmlDictionaryWriter和XmlDictionaryReader等幾個類。

技術分享

這部分的內容主要集中在對實例上下文的概念和單例、單調、會話三種模式的理解。在托管應用程序中,當創建一個托管對象時,CLR會在托管堆為該對象分配內存空間,對象的生命的終結對應內存的回收。負責該部分工作的模塊為GC,其對沒有被"根"引用的對象進行回收,對於WCF來說,其實例上下文即為其根,其層級關系為ServiceHost->InstanceContext->ServiceInstance。

實力上下文的模式包括PerCall單調、會話PerSession和Single三種。在單調模式時,系統的並發性最好,但對資源的消耗很大,比如數據庫支持100個並發,這是有100個服務實例同時打開,那麽第101請求就無法得到服務。而單例模式對資源的消耗較少,每次完成調用就釋放資源,但是當請求多時,會有很多請求需要排隊,響應不夠及時。而會話模式,根據用戶來創建服務示例,算是一種折衷。

Tip:高性能和可伸縮性是軟件設計與架構中永遠不可同時兼顧的,高性能需要充足的資源,高擴展性需要盡可能的節約資源,所以才有軟件架構是意向"權衡"的藝術,目的不是使得各方面達到最優,而是找到一個平衡點使得整體最優,在實踐中,沒有完美的方案,只有適合方案,必須具體問題具體分析。

技術分享

服務寄宿的內容比較簡單,主要包括ServiceHost,iis寄宿和window寄宿的介紹。

ServiceHost:是服務寄宿的核心,包括創建、終結點添加、開啟和關閉等基本步驟,服務描述的創建和運行時框架體系的構建也與其息息相關。

對於iis寄宿和windows寄宿來說,在當下的互聯網環境下,iis寄宿顯得更加合理,其優點包括:自動化的進程激活和關閉;自動化的進程回收;自動化的進程健康監測;ASP.NET共享寄宿模式,將多個應用寄宿在通過一個工作進程,改善服務器密度和可伸縮性;ASP.NET動態編譯。通過.svc文件來標識服務,提供ASP.NET並行和兼容兩種模式,默認使用第一種,第二種僅在需要共享SessionState時,不常用。

客戶端代理的內容相對稍微多一點,其涉及透明代理和真實代理的概念,一個精簡的WCF框架和服務限流操作的例子。

服務代理:作為服務在客戶端的本地代理,本身不承擔功能實現,僅僅是在服務與客戶端之間起到一個中介的作用,是一種透明代理,可以通過RemotingServices.IsTransparentProxy方法來判斷,其最終都通過ChannelFactory<TChannel>創建。在托管環境中,AppDomain提供了一種輕量級的隔離機制,不同AppDomain之間通過封送(Marshaling)來傳遞對象。封送分為按值封送和按引用封送兩種形式,前者通過序列化/反序列化重建一個相同的本地對象,實現不同AppDomain的數據共享;後者將遠程對象的引用傳遞給本地,實現跨應用程序與的遠程調用(RPC)。那麽如何實現RPC呢,簡單來說,如果需要在A域(應用程序域)調用B域創建對象,那麽B域需要為該對象創建其引用System.Runtime.Remoting.ObjRef對象,並將其按值封送帶A域。A域基於它創建代理對象,之後再調用時,代理對象通過ObjRef將調用請求跨域發送給遠程對象,最後將遠程調用得到的結果返回給客戶端程序。實際上,代理對象包含兩種類型,一種是上面提到的透明代理,另一種為System.Runtime.Remoting.Proxies.RealProxy表示的真是代理。透明代理依托於真實代理,其將調用請求轉發給真實代理,真實代理完成真正的遠程調用,如下圖所示。

技術分享

精簡的WCF框架

服務端的流程包括:請求消息的接受和回復信息的發送;請求消息的解碼和回復消息的編碼;請求消息的反序列化和回復消息的序列化;服務對象的創建;服務操作的執行。

客戶端的流程包括:請求消息的序列化和回復消息的反序列化;請求消息的編碼和回復消息的解碼;請求消息的發送和回復消息的接收。整體過程如下圖所示。

技術分享

最後介紹一下服務限流(Throttling)機制,WCF具有一個MaxConcurrentSessions的閾值,表示服務端允許的最大並發會話數量,默認為100(針對一個CPU),一旦超過服務端就會拒絕之後的服務。而客戶端的調用在限定時間內如果無法被及時處理,就會拋出一個TimeoutException異常。

參考資料:

[1]蔣金楠. WCF全面解析[M]. 上海:電子工業出版社, 2012.

快速入門系列--WCF--02消息、會話與服務寄宿