標籤:wcf
背景:
WCF可以看作是微軟對SOA架構的一種實現,或者說WCF的存在讓開發人員更容易建立面向服務的程式。面向服務本身不是一種技術,而是設計和實現軟體的一種架構方式。從最早的面向過程(PO)、物件導向編程(OO),到後來的面向服務(SO)、面向資源(RO)編程,本身沒有本質區別,反映出的是人們認識世界的方法論的迭代進化。
PO、OO、SO、RO,還有一個不沾邊的O2O,各種概念層出不窮,在學習使用時要切忌混淆。今天這裡記錄的是在WCF架構下(面向服務架構——SOA——的一種實現),如何進行多線程及並發管理。多線程、並發、加鎖、生命週期,這些知識都是老生常談,剖開新架構的外衣,其本質是沒有變化的。
WCF概念介紹:
在進入正題之前,先介紹WCF架構中幾個主要概念。
1.EndPoint
WCF通過終結點EndPoint來發布服務,終結點EndPoint包括ABC三要素:
這裡可以用常見的互連網服務來簡單對比一下,Address就是我們使用的URL、Binding就是HTTP或HTTPS協議,Contract就是GET、POST等各種方法。互連網服務端最最常見的就是Apache Httpd、Apache Tomcat、JBoss等各種容器託管服務軟體,由於HTTP協議是無狀態協議,因此我可以簡單的理解為每一次、每一個使用者請求服務端都會建立單獨的、新的一個響應對象(例如Servlet對象)來處理使用者請求,這就跟我們下面要講到的執行個體(Instance)和會話(Session)有關。
2.Instance vs Session
看一下執行個體(Instance)與會話(Session)兩者的對比,
| 概念 |
含義 |
備忘 |
| 執行個體(Instance) |
WCF中的執行個體管理旨在解決服務執行個體的啟用和服務執行個體生命週期的控制 |
執行個體上下文是對服務執行個體的封裝,是WCF管理服務執行個體的生命週期的依託。 |
| 會話(Session) |
會話的目的在於保持相同用戶端(服務代理)多次服務調用的狀態
會話通過訊息識別機制判斷調用某個服務的訊息來源,從而將來自於同一個用戶端的訊息關聯在一起 |
|
【備忘】:關於生命週期最容易想到的就是Java或C#中的記憶體回收,而這兩種主流商用語言都採用了“跟搜尋演算法”,詳情參見《深入理解Java虛擬機器:JVM進階特性與最佳實務》
WCF執行個體模式與併發模式的對比
高效能(Performance)和高伸縮性(Scalability),是軟體設計與架構中永遠不可以同時兼顧的,原因很簡單,高效能往往需要充足的資源,高擴充性又需要儘可能的節約資源。所以我們才說,軟體設計與架構是一項“權衡”的藝術。
雖然在前文中對比了會話與執行個體的概念,但是具體應用中會話與執行個體往往是分不開的,會話過程中必然用到執行個體來進行請求處理。通過對比WCF中執行個體上下文模式與併發模式,以及最後給出具體的樣本程式,來瞭解一下WCF是如何兼顧高效能和高伸縮性的。
1. 執行個體上下文模式:InstanceContextMode
WCF的執行個體上下文模式InstanceContextMode分為以下三種,
| 執行個體上下文 |
說明 |
| 單調模式(Per-Call) |
決定於單調執行個體上下文模式,即InstanceContextMode |
| 單例模式(Single) |
決定於單例執行個體上下文模式,即InstanceContextMode |
| 會話模式(Per-Session) |
取決於會話執行個體上下文模式、會話通道、會話通道棧,即有會話模式、綁定、執行個體上下文模式的三者決定,如所示: |
服務執行個體的建立過程,其中會使用反射這樣相對影響效能的操作,但是在WCF應用中,真正影響效能的是操作時通道的建立和釋放。服務執行個體的啟用和他們比起來,可以說微不足道。如果在應用中出現對基於相同服務代理的頻繁調用,比如服務調用放在一個for迴圈中調用上百次,服務執行個體的建立帶來的效能損失就不能不考慮了。
2. 併發模式:ConcurrencyMode
註:來自《WCF全面解析(下冊)》,作者蔣金楠
WCF執行個體模式與併發模式的對比執行個體測試1. 設定InstanceContextMode=Single,ConcurrencyMode=Single
由可以看出,在WCF服務包含回調並且InstanceContextMode與ConcurrencyMode同時設定為Single後,會彈出死結問題,該問題原因在於服務端的InstanceContext執行個體在響應用戶端請求後會發起回調請求,而此時用戶端恰恰在等待服務端的返回結果才能啟動回呼函數,因此導致兩者死結。解決方案如下。
2. 設定InstanceContextMode=Single,ConcurrencyMode=Reentrant
用戶端與服務端顯示結果如下,
由可以看出InstanceContextMode標明的是WCF建立InstanceContext的個數,此處設定為Single指的是所有用戶端的請求都由同一個InstanceContext來執行,雖然用戶端使用了ThreadPool.QueueUserWorkItem發起並發請求,但是在服務端的實際運行過程中是串列執行的,為了更好的觀察執行流程,繪製執行時間簡圖如下:
【注意】:為何Reentrant能夠解決死結問題,可以看考一下《WCF全面解析(下冊)》,如下:
【zssure】:有上述可知,Single對執行個體內容相關的加鎖是完整的,直到此次服務要求完成(包括請求、回調、回調響應、回調後操作);而Reentrant在發起回調後會釋放鎖,當然此時如果由其他的用戶端使用了該執行個體上下文,回調響應需要等到其他用戶端釋放該執行個體上下文後方可運行,此時如果逾時就會拋出異常。自己繪製的時間圖中將服務端的InstanceContext分化成了兩個執行個體,一個用於正常請求,一個用於回調,其目的是為了更清晰的標明整個響應流程。至於WCF底層是如何來實現同時響應新的用戶端請求以及發起回調請求的有待進一步核實。
3. 設定InstanceContextMode=Single,ConcurrencyMode=Multiple
正如《WCF全面解析(下冊)》書中所言,將ConcurrencyMode設定為Multiple後,服務端的InstanceContext執行個體可以同時並發響應多個用戶端的請求,實現真正意義上的並發。
4. 設定InstanceContextMode=PerCall,ConcurrencyMode=Multiple
再次將InstanceContextMode設定為PerCall查看一下運行結果,如下所示:
由此可以看出與第3中情況是相同的,但是此時如果在控制台中間InstanceContext具體執行個體的HashCode列印出來會發現,三次用戶端請求會在服務端建立三個InstanceContext執行個體,這是與上面第3中情況不同的地方。
總結
由此可以看出InstanceContextMode主要控制的是服務端如何建立具體的執行個體對象,而ConcurrencyMode控制的是執行個體與用戶端請求之間的分發方式。如所示:
在WCF中通過執行個體上下文模式InstanceContextMode的設定來確定服務響應時如何建立具體的操作執行個體(Instance),另外通過併發模式ConcurrencyMode來控制用戶端請求與具體操作執行個體之間的分發和響應機制。——而這整個過程都可以簡單歸屬為會話層。
[email protected]
時間:2015-11-19
著作權聲明:本文為zssure原創文章,轉載請註明出處,未經允許不得轉載。
【踩坑(Running)填坑(ZSSURE)】:WCF學習之InstanceContextMode與ConcurrencyMode