-- lostall
本文不介紹完整的基礎知識,相關部分請參閱相關書籍
本文主要提供了一個例子,說明了COM+程式的一個簡單的架構,程式啟動並執行如下:
1、資源管理員RM(Resource Manager)
RM是一個可以跨越COM+事務並管理持久系統狀態的軟體。RM知道當參與事務的對象改變它所管理的資源時,
如何把資源的變化緩衝起來。然後,如果事務被提交了,RM知道如何把這些變化發布出去;如果事務被放
棄了,RM知道如何把這些變化丟棄掉。
大多數的資料庫都提供了COM+資源管理員,包括SQL Server、Oracle、DB2等。另外比較特殊的是微軟消
息隊列管理器MSMQ也提供了這種功能,這樣把訊息佇列與事務結合在一起,也可以通過SetComplete來保
證放在訊息佇列中的方法調用能正確地發送到伺服器上。
事務的最終提交過程是由RM來完成的,既SetComplete、SetAbort之後的打操作。RM通過兩階段交易認可方法
來完成這一過程。第一個階段是準備階段,RM主要工作是把所有相關資訊存到日誌中,日誌是關鍵的資料
結構,不同的RM有不同的實現方法。如果RM從準備階段返回成功,則對客戶來說就意味著提交已經成功。
儘管資料庫這時還沒有真正的更新,剩下的工作都是RM的責任了。既RM承擔了使變化永久化的全部責任。
比如說如果準備階段成功完成之後資料庫完成更新這前系統崩潰了,則在下次系統重啟時,RM會詢問DTC,
完成剩下的工作。第二個階段是提交階段,RM負責完成最後的資料庫更新操作。
RM要實現的一個關鍵介面是ICrmCompensator,通過它的介面方法來完成事務的提交過程,調用過程如:
事務提交: 準備階段: BeginPrepare()
PrepareRecord()
EndPrepare()
提交階段: BeginCommit()
CommitRecord()
EndCommit()
事務中止: BeginAbort()
AbortRecord()
EndAbort()
2、安全性
要想正確使用COM+提供的安全性,必須在Component Service中正確的設定,包含以下步驟:
(1)在應用程式的屬性/安全設定/授權中選中"強制對應用程式進行訪問檢查"
(2)在應用程式的屬性/安全設定/安全級中選中"對進程級和組件級運行訪問檢查"
(3)在組件的屬性/安全設定/授權中選中"強制組件級訪問檢查"
(4)在應用程式中加入適當的角色
(5)在組件的屬性/安全設定中選中允許訪問的角色
這五步缺一不可,且其中有(2)就必須有(5)。另要注意時常關閉前一次的應用服務程式
3、及時啟用JIT(Just-In-Time activation)
JIT特性對COM+組件不必須的。事務型組件必須支援JIT,非事務型組件可以使用JIT也可以不使用。
對象啟用(Activate)的時機:
(1)調用CoCreateInstance建立對象後,第一次調用組件的方法時啟用物件
(2)對象處於無效狀態時,調用對象的方法時會啟用物件
對象無效(Deactivate)的時機:
(1)調用SetComplete或SetAbort後會使對象無效。這時會銷毀對象(如果有對象池就放入池中,如果沒有
就delete它),但代理/存根、RPC通道不變。
(2)可以設定在方法調用結束後使對象無效,其效果等同於調用SetComplete和SetAbort的效果。
(3)調用Release會使對象無效。這時會銷毀對象(如果有對象池就放入池中,如果沒有就delete它),同時
銷毀代理/存根及RPC通道。
JIT發揮作用的條件:JIT的作用在於節省系統資源。但由於對象被無效時代理存根和通道並沒有被釋放,所
以只有當對象消耗了比這些COM+的基礎設施更多的資源時,JIT才真正發揮了作用。
4、對象池
對象池與JIT啟用兩種機制結合起來是COM+獲得最大速度的途徑。JIT保證了對象可以及時被釋放,對象池
避免了對象被頻繁地建立。
池對象必須滿足三個條件:
(1)必須實現IObjectControl
(2)必須是可彙總的(否則建立組件時會出錯)。這是因為COM+在組件外面加了個封裝器,可能是Context Wrapper
(3)強烈推薦執行緒模式為Free或Neutral型,但並非必需。這是因為池對象可能會被不同執行緒模式的客戶使用,
使用Free或Neutral型會提高訪問速度,避免公寓間調度。另外在COM+中強烈推薦組件為Neutral型公寓。
對象池發揮作用的條件:對象池的作用在於節省了組件建立的時間,這樣只要做一些初始化工作就可以了。但
只有初始化對象的時間比建立一個新的對象的時間少很多的時侯,對象池才真正發揮了作用。
5、連接點問題
在本文給出的例子中使用了傳統的連接點方式來實現組件對客戶的事件通知。但這種方式在COM+有一些問題。
(1)本例中,客戶程式首先通過CoCreateInstance建立對象,然後調用Advise建立串連,然後調用組件方法。
在組件的Activate、Deactivate和CanBePooled三個函數中我試圖通過連接點來向客戶程式返回資訊。但
是通過運行程式,發現在對象建立時和對象銷毀時連接點沒有發揮作用,在其他時侯連接點工作正常。其原
因在於,當調用Advise時,COM+先調用了Activate,通知群組件它已經被啟用,然後才調用組件其他相關函數
以建立串連,所以這時在Activate中不可能通過串連返回資訊。同樣的道理,在組件銷毀時,COM+先去除了
串連,然後才調用Deactivate和CanBePooled,所以這時也不能通過串連返回資訊。
(2)對象是有狀態的,它含有串連的資訊。如果在Deactivate裡刪除了這種串連資訊,那就意味著客戶程式每
次在對象被無效後都要重新Advise以建立串連,有時這是很不方便的。但如果在Deactivate裡什麼也做的
話,就會出現本例中的有趣情況:
第一,每次去活後再重新啟用,串連仍然存在,顯然這是因為對象仍保留著原來的狀態。
第二,如果同時運行多個客戶程式,則在一個程式中操作的結果會同時顯示在其他程式中。這是因為本例中
設定每個函數返回後都會無效,所以對象始終是放在池中的,即一個時刻只會有一個程式調用組件(因為是
在一台機器上,不會並發執行),所以操作的是同一個對象,連接點就串連了多個客戶了。
COM+中有一種新的實現事件的方法,既發行者和訂閱者。但這種方法有一些局限,能否取代傳統的連接點還有
待進一步學習實踐,我將另文闡述這個問題。