連接改善,資源適配器煥發(fā)生機
級別: 中級 |
Staff Software Engineer, IBM UK Ltd.
2005 年 4 月 21 日
本系列共三部分,在第一部分中,Java 開發(fā)人員 David Currie 介紹了 Java 2 Enterprise Edition (J2EE) Connector Architecture (JCA) 1.5 中所作的一些優(yōu)化,它們可以加快現(xiàn)有或新外部資源適配器的運行速度。他還分析了一些使資源適配器煥發(fā)生機的新功能。若想提高現(xiàn)有資源適配器的性能或要加入新的功能,或者正在考慮編寫新的 JCA 1.5 資源適配器,那么本系列是必不可少的。若要編寫使用資源適配器的應用程序,并想知道更多的幕后情況,那么本系列也值得一讀。
JCA 1.5 是 J2EE Connector Architecture 的最新版本,它包含了許多重要的增強和新增功能。討論這些變化的系列文章分為三個部分,本文是第一部分,將介紹該版本中所作的一些優(yōu)化,它們可以加快那些使用出站資源適配器的應用程序,特別是那些使用事務的應用程序的運行速度。然后介紹對生命周期管理契約所作的擴展,它們可以防止應用程序的連接斷開,并使資源適配器煥發(fā)新生。這將為第 2、3 部分奠定基礎。第 2 部分討論新的工作管理和事務流入契約,第 3 部分探討期待已久的消息流入契約,其更常見的叫法是消息驅動的 bean (MDB) 支持。
本文假定讀者對 JCA 連接管理契約有一定的了解。原來 1.0 規(guī)范中的所有內容仍然適用,因此如果剛剛接觸 JCA,建議先看一看 Willy Farrell 的入門教程(請參閱 參考資料)。
連接加快
JCA 規(guī)范的新版本不會使應用程序與后端系統(tǒng)之間的連接變得更快,但 JCA 1.5 引入了兩組接口,可以加快使用連接的應用程序的運行。第一組接口解除了以前 JCA 版本中應用服務器管理連接句柄方式的限制。
許多讀者都知道,J2EE 支持兩種連接使用模式,本文稱之為 get-use-close 和 cached-handle。對這些模式的進一步分析有助于理解 JCA 1.5 在這方面所帶來的性能改善。
get-use-close
在 get-use-close 模式中,應用程序在需要新連接時,總是先獲取新連接,然后使用,然后再關閉它,如清單 1 所示。(為清楚起見,本文沒有在示例清單中加入異常處理邏輯。)
|
get-use-close 模式看起來效率不高,但是應用服務器實現(xiàn)的連接池可降低“獲得”操作的成本。此外,因為應用程序只在需要時才保留連接,所以應用程序的不同實例或者部分可以重復使用該連接,從而降低了總的資源占用,如圖 1 所示。
如圖 1 所示,每當 bean 方法調用 getConnection
時,連接管理器都會重復使用池中托管的連接,并只創(chuàng)建一個新連接句柄。當連接句柄通知連接管理器它已關閉時,托管的連接就被清除并返回池中。圖 1 中的綠色線條表示托管連接與應用程序的這個實例相關聯(lián)的時間。
cached-handle
在 cached-handle 模式中,應用程序在一開始是獲得連接,然后在一個實例字段中緩存對它的引用,如清單 2 所示。
|
應用程序開發(fā)人員通常都使用 cached-handle 方法,因為他們認為這樣應用程序的性能會更好。但是因為 get-use-close 模式中連接池的作用,這兩種使用模式的性能差別一般來說是很小的。盡管 cached-handle 模式可使業(yè)務方法中的邏輯更簡單,但是需要額外的邏輯以便在鈍化(passivation)時關閉連接,并在激活時重建連接。當容器毀壞 bean 時(如由于方法生成了一個運行時異常),還有可能留下打開的連接。
cached-handle 模式的最大問題是當 bean 或者 servlet 的一個實例使用該連接時,其他實例就不能使用它——因此連接數(shù)最多只會有實例那么多。如圖 2 所示。
從圖 2 中可以看到,創(chuàng)建 EJB 時(從綠色線條開始),托管的連接與連接句柄關聯(lián),并且這個 bean 實例以外的任何其他對象都不能使用這個連接。(綠色線條無限延伸。)
針對這種情況,JCA 1.5 規(guī)范引入了兩個新的接口,如清單 3 所示。
清單 3. 解除關聯(lián)(dissociation)和惰性關聯(lián)(lazy association)接口
|
解除關聯(lián)
資源適配器的托管連接實現(xiàn)第一個接口—— 解除關聯(lián) 接口——以向連接管理器表明適配器支持這種優(yōu)化。當連接暫時超出范圍時(即當 bean 或者 servlet 方法退出時),如果連接管理器支持這種優(yōu)化的話,它就可以解除由應用程序使用的連接句柄與表示物理資源的托管連接的關聯(lián)。這使托管連接可以返回連接池,為應用程序的其他部分所使用。
惰性關聯(lián)
這種優(yōu)化使用 惰性關聯(lián),而不是在下次調用方法時重新將連接句柄與托管連接關聯(lián)。如果方法沒有使用連接,或者它只調用連接句柄上不需要訪問后端的簡單方法,那么托管連接未必會從池中移出。相反,當連接句柄確定它不需要與一個托管連接重新關聯(lián)時,它就可以將連接管理器強制轉換為 LazyAssociatableConnectionManager
并調用 associateConnection
方法。該方法以連接句柄為第一個參數(shù),然后是托管連接廠,以及對 allocateConnection
的第一次調用時傳遞的請求信息。然后連接管理器從池中找到另一個合適的托管連接,并使用這個托管連接的 associateConnection
方法將它與連接句柄關聯(lián)。
圖 3 顯示了這種優(yōu)化對 圖 2 中的 cached-handle 用法的效果。
圖 3 中虛線箭頭表示方法完成時 EJB 容器對連接管理器的通知。這時,托管的連接與連接句柄解除關聯(lián),只有當方法試圖使用這個句柄時,托管連接才會重新關聯(lián)。短的綠色線條顯示托管連接現(xiàn)在綁定到 EJB 上,以縮短時間并可以在別的地方重新使用。
征募,還是不征募
大家都知道事務代價很高——特別是 XA(全局)事務。這使得讓事務不執(zhí)行非必需的工作變得很重要。JCA 1.5 中的另外兩個新接口防止了 XAResource
對象的不必要征募。
我們現(xiàn)在來更詳細地分析一下這種增強所針對的問題。假定取用 清單 1 中的 EJB,并用容器托管的事務部署它,將業(yè)務方法的事務屬性設定為 RequiresNew
。調用這個方法時便開始一個新的事務。創(chuàng)建連接時,連接管理器不知道如何使用它,因此它必須從關聯(lián)的托管連接獲得一個 XAResource
,并在事務中征募它。連接可能只用于查詢數(shù)據(jù)庫或者根本不被使用。但是連接管理器必須征募連接,以備插入或者更新操作。這意味著,資源適配器至少必須進行開始、提交或者回滾,并結束流程返回后端。圖 4 展示了這樣的事務流程。
在圖 4 中可以看到,獲得連接后,XAResource
立即征募到了事務中(即接收一個開始流程)。這意味著當事務方法結束時,流程需要在資源處結束,即使方法沒有在事務中使用連接。
如果在事務中涉及另一項資源,就會強制進行不必要的兩階段提交,導致額外的準備流程。這里的惟一可取之處是資源管理器仍然可以從準備調用中返回 XA_RDONLY
(用于“read only”)以表明它實際沒有做任何工作。事務管理器不需要在那個資源管理器處完成調用,并且如果在事務中只有一個資源管理器真正做了工作,那么事務管理器也許可以避免日志文件中的惰性寫操作。
惰性征募
現(xiàn)在您應當認識到除非絕對需要,否則不要在事務中征募。JCA 1.5 規(guī)范提供了一個解決方案:惰性征募。清單 4 顯示了支持這各種優(yōu)化所引入的兩個接口。
WebSphere 為 JCA 1.5 打下基礎 JCA 1.5 在其惰性征募支持中還采用了 WebSphere Application Server V5 的 延遲事務征募 擴展。 請閱讀 developerWorks 中 Kevin Kelle 等人撰寫的文章以了解更多的 WebSphere 擴展(請參閱 參考資料)。 |
|
LazyEnlistableManagedConnection
接口是由托管連接實現(xiàn)的標記接口,用以向連接管理器表明在事務中創(chuàng)建新的連接或者在連接已經(jīng)存在的情況下開始一個新的事務時,它不需要將托管連接急切征募到現(xiàn)有事務中。如果連接句柄準備執(zhí)行應當是任一事務中的一部分的某些工作,并且它的托管連接還沒有征募,那么應當確定連接管理器是否實施了 LazyEnlistableConnectionManager
接口。如果實施了,那么它應當調用傳遞托管連接的 lazyEnlist
方法。這個方法不返回任何結果,但是如果調用線程關聯(lián)了一個事務,那么這時就征募托管連接的 XAResource
。如果連接沒有被征募,那么它需要在后面每一項工作之前再次調用 lazyEnlist
,以檢查在上次調用這個方法之后,是不是沒有啟動過事務。
圖 5 顯示了這個新的事件序列。
在圖 5 中可以看到,在獲得連接時,XAResource
不再急切征募。相反,連接管理器會等待,直到連接用 lazyEnlist
調用表明它要完成一些事務工作時,才會征募 XAResource
。
什么時候出現(xiàn)錯誤
JCA 規(guī)范的第一個版本提供了一種讓資源適配器在連接出現(xiàn)嚴重錯誤時通知連接管理器的機制。這是 ConnectionEventListener
接口的 connectionErrorOccurred
方法。收到這個通知后,連接管理器就會毀環(huán)發(fā)送事件的托管連接,這樣就不會再使用它。這些都是不錯的。但是,如果到后端的連接丟失了,那么池中的許多托管連接也很有可能不能再使用。
針對這個問題,JCA 1.5 以 ValidatingManagedConnectionFactory
接口的方式引入了一種雅潔的解決方案,如清單 5 所示。
|
由托管連接廠實現(xiàn)的 ValidatingManagedConnectionFactory
接口包含一個方法——getInvalidConnections
——它以一組托管連接為參數(shù),返回資源適配器認為無效的一個子集。資源適配器的驗證可以采取任何形式,不過通常涉及到對后端的某種“ping”操作,以測試連接。然后連接管理器在資源適配器指示連接錯誤時調用這個方法,甚至定期調用該方法,以便從池中排除壞掉的連接。
開始和結束
最初的 JCA 版本為托管連接及其相關聯(lián)的連接句柄提供了詳細的生命周期模式,但是它沒有為資源適配器提供這種概念。只有當創(chuàng)建了托管連接廠后,部署的資源適配器才知道它的存在。JCA 1.5 中引入的 ResourceAdapter
接口對此進行了糾正,如清單 6 所示。
|
資源適配器可以在其部署描述符(ra.xml)的 resourceadapter-class
元素中給出實現(xiàn)這個接口的類的名稱。除了實現(xiàn) ResourceAdapter
接口,這個類可以通過 JavaBean 樣式支持某些屬性。與托管連接廠一樣,在部署描述符中可以聲明這些屬性及其默認值,如清單 7 所示。在安裝了資源適配器后,應用服務器將允許管理員覆蓋這些默認值。
|
在啟動時,應用服務器會創(chuàng)建在部署描述符中指定的類的一個實例,并設置管理員提供的屬性。這個類必須根據(jù)這些屬性實現(xiàn)一個 equals
方法,這樣應用服務器就可以保證它不會創(chuàng)建一個以上同樣的實例。然后會調用 start
方法,向它傳遞一個實現(xiàn)了 BootstrapContext
接口的對象。可以用這個對象創(chuàng)建計時器、調度其他線程上的工作和控制導入的事務,在本系列的第 2 部分中將更詳細地討論所有這些內容。這個方法將不會堵塞并會及時返回。
應用服務器通常會在關閉或者解除部署資源適配器之前,對資源適配器調用 stop
方法。JCA 1.5 規(guī)范描述了這個過程的兩個階段。首先,應用服務器保證依賴資源適配器的所有應用程序都已停止。這可保證程序線程不再使用資源適配器對象,并且所有事務都已完成。然后應用服務器調用 stop
方法。這時,資源適配器將執(zhí)行一個有序的關閉(例如,釋放網(wǎng)絡和應用服務器資源,并將所有緩存的數(shù)據(jù)強行送回后端)。調用 stop
后,應用服務器將不會重新使用資源適配器實例。
為了保留向后兼容性,ManagedConnectionFactory
沒有改變,但是如果希望外部資源可以利用資源適配器具有的功能,那么還要實現(xiàn)清單 8 所示的新的 ResourceAdapterAssociation
接口。
ResourceAdapterAssociation
接口
|
構建了托管連接廠之后,應用服務器將調用 setResourceAdapter
方法以便將它與其資源適配器關聯(lián)在一起。在托管連接廠的生命周期內這種關聯(lián)將會固定下來。這種方法只調用一次。
結束語
本文展示了 JCA 1.5 為現(xiàn)有出站契約帶來的四項增強功能。惰性關聯(lián)和征募優(yōu)化會提高使用連接的應用程序的性能,驗證托管連接廠會改善對故障情況的處理。在資源適配器級別引入生命周期管理為資源適配器提供了多種有趣的新機會。本系列的第 2 部分將分析如何在這個基礎上建立新的工作管理和事務流入契約。
- 您可以參閱本文在 developerWorks 全球站點上的 英文原文。
- 可以從 Sun Microsystems 的 J2EE 1.4 Documentation 頁中下載 J2EE Platform、EJB 2.1、J2EE Connector 1.5 和 Java Message Service 規(guī)范。
- 下載試用版的 WebSphere Application Server 以自行體驗 JCA 1.5。
- 查看內容不繼增多的 兼容 J2EE 1.4 的應用服務器列表。
- Introduction to the J2EE Connector Architecture(developerWorks,2002 年 11 月)是一個內容豐富的教程,由 Willy Farrell 編寫,它介紹了作為 1.5 版的基礎的最初的 JCA 規(guī)范。
- J2EE Connector Architecture Extensions in WebSphere Application Server V5 (developerWorks,2003 年 2 月)詳細介紹了 IBM 的兩項創(chuàng)新,它們都成為 JCA 1.5 規(guī)范的一部分。
- 理解 JCA 事務 (developerWorks,2004 年 10 月)介紹了不同的企業(yè)信息系統(tǒng)如何通過 JCA 參與事務處理。
- Developing applications with JCA-based tools (developerWorks,22002 年 1 月)通過使用 IBM 的工具創(chuàng)建、測試、部署和運行一個 J2EE EJB 應用程序,介紹了 JCA 的實用特性(摘自 Rahul Sharma、Beth Stearns 和 Tony Ng 的 J2EE Connector Architecture and Enterprise Application Integration,Addison-Wesley,2001 年)。
- Build JCA-compliant resource adapters with WebSphere Studio Application Developer(developerWorks,2003 年 8 月)介紹如何自已編寫兼容 JCA 的資源適配器。
- Getting started with EJB technology (developerWorks,2003 年 4 月)是一個全面的教程,介紹了 EJB 編程和 J2EE 環(huán)境的基本內容。
- 可以在 developerWorks 的 Java 技術專區(qū) 找到關于 Java 編程的各個方面的文章。
- 通過參與 developerWorks blogs 加入 developerWorks 社區(qū)。
- 訪問 The Developer Bookstore 可以獲得技術書籍的完整清單,其中包括數(shù)百本與 Java 主題相關 的書籍。
- 還可訪問 developerWorks 中的 Java 技術專區(qū)教程,獲得 Java 主題教程的完整清單。
關于作者![]() |