伺服器管理連接句柄方式的限制. 許多讀者都知道,J2EE 支持兩種連"/> 伺服器管理連接句柄方式的限制. 許多讀者都知道,J2EE 支持兩種連"/>
歡迎您光臨本站 註冊首頁

JCA 1.5: 優化和生命周期管理

←手機掃碼閱讀     火星人 @ 2014-03-10 , reply:0

  JCA 規範的新版本不會使應用程序與後端系統之間的連接變得更快,但 JCA 1.5 引入了兩組介面,可以加快使用連接的應用程序的運行.第一組介面解除了以前 JCA 版本中應用伺服器 style="COLOR: #000000" href="http://server.it168.com/" target=_blank>伺服器管理連接句柄方式的限制.

  許多讀者都知道,J2EE 支持兩種連接使用模式,本文稱之為 get-use-close 和 cached-handle.對這些模式的進一步分析有助於理解 JCA 1.5 在這方面所帶來的性能改善.

  get-use-close

  在 get-use-close 模式中,應用程序在需要新連接時,總是先獲取新連接,然後使用,然後再關閉它,如清單 1 所示.(為清楚起見,本文沒有在示例清單中加入異常處理邏輯.)

  清單 1. 使用 get-use-close 模式的一個 Enterprise JavaBean (EJB)

1 public class GetUseCloseEJB implements SessionBean {
2 ...
3 public void businessMethod() {
4 InitialContext context = new InitialContext();
5 DataSource dataSource = (DataSource)context.lookup("java:comp/env/jdbc/mydatasource");

6 Connection connection = datasource.getConnection();
7 ...
8 connection.close();
9 }
10 }

  get-use-close 模式看起來效率不高,但是應用伺服器實現的連接池可降低「獲得」操作的成本.此外,因為應用程序只在需要時才保留連接,應用程序的不同實例或者部分可以重複使用該連接,從而降低了總的資源佔用,如圖 1 所示.

  圖 1. 使用中的 get-use-close 模式

  如圖 1 所示,每當 bean 方法調用 getConnection 時,連接管理器都會重複使用池中託管的連接,並只創建一個新連接句柄.當連接句柄通知連接管理器它已關閉時,託管的連接就被清除並返回池中.圖 1 中的綠色線條表示託管連接與應用程序的這個實例相關聯的時間.

  cached-handle

  在 cached-handle 模式中,應用程序在一開始是獲得連接,然後在一個實例欄位中緩存對它的引用,如清單 2 所示.

  清單 2. cached-handle 模式

1 public class CachedHandleEJB implements SessionBean {
2 private Connection _connection;
3 ...

4 public void ejbCreate() {
5 InitialContext context = new InitialContext();
6 DataSource dataSource = (DataSource)context.lookup("java:comp/env/jdbc/mydatasource");
7 _connection = datasource.getConnection();
8 }
9 public void businessMethod() {
10 ...
11 }
12 }

  應用程序開發人員通常都使用 cached-handle 方法,因為他們認為這樣應用程序的性能會更好.但是因為 get-use-close 模式中連接池的作用,這兩種使用模式的性能差別一般來說是很小的.儘管 cached-handle 模式可使業務方法中的邏輯更簡單,但是需要額外的邏輯以便在鈍化(passivation)時關閉連接,並在激活時重建連接.當容器毀壞 bean 時(如由於方法生成了一個運行時異常),還有可能留下打開的連接.

  cached-handle 模式的最大問題是當 bean 或者 servlet 的一個實例使用該連接時,其他實例就不能使用它——因此連接數最多只會有實例那麼多.如圖 2 所示.

  圖 2. 使用中的 cached-handle 模式

  從圖 2 中可以看到,創建 EJB 時(從綠色線條開始),託管的連接與連接句柄關聯,並且這個 bean 實例以外的任何其他對象都不能使用這個連接.(綠色線條無限延伸.)

  針對這種情況,JCA 1.5 規範引入了兩個新的介面,如清單 3 所示.

  清單 3. 解除關聯(dissociation)和惰性關聯(lazy association)介面

1 public interface DissociatableManagedConnection {
2 void dissociateConnections() throws ResourceException;
3 }
4 public interface LazyAssociatableConnectionManager {
5 void associateConnection(Object connection,
6 ManagedConnectionFactory mcf,
7 ConnectionRequestInfo cxReqInfo)
8 throws ResourceException
9 }

  解除關聯

  資源適配器的託管連接實現第一個介面—— 解除關聯 介面——以向連接管理器表明適配器支持這種優化.當連接暫時超出範圍時(即當 bean 或者 servlet 方法退出時),如果連接管理器支持這種優化的話,它就可以解除由應用程序使用的連接句柄與表示物理資源的託管連接的關聯.這使託管連接可以返回連接池,為應用程序的其他部分所使用.

  惰性關聯

  這種優化使用 惰性關聯,而不是在下次調用方法時重新將連接句柄與託管連接關聯.如果方法沒有使用連接,或者它只調用連接句柄上不需要訪問後端的簡單方法,那麼託管連接未必會從池中移出.相反,當連接句柄確定它不需要與一個託管連接重新關聯時,它就可以將連接管理器強制轉換為 LazyAssociatableConnectionManager 並調用 associateConnection 方法.該方法以連接句柄為第一個參數,然後是託管連接廠,以及對 allocateConnection 的第一次調用時傳遞的請求信息.然後連接管理器從池中找到另一個合適的託管連接,並使用這個託管連接的 associateConnection 方法將它與連接句柄關聯.

  圖 3 顯示了這種優化對 圖 2 中的 cached-handle 用法的效果.

  圖 3. 惰性關聯降低資源用量

  圖 3 中虛線箭頭表示方法完成時 EJB 容器對連接管理器的通知.這時,託管的連接與連接句柄解除關聯,只有當方法試圖使用這個句柄時,託管連接才會重新關聯.短的綠色線條顯示託管連接現在綁定到 EJB 上,以縮短時間並可以在別的地方重新使用.

  徵募,還是不徵募

  大家都知道事務代價很高——特別是 XA(全局)事務.這是的讓事務不執行非必需的工作變得很重要.JCA 1.5 中的另外兩個新介面防止了 XAResource 對象的不必要徵募.

  我們現在來更詳細地分析一下這種增強所針對的問題.假定取用 清單 1 中的 EJB,並用容器託管的事務部署它,將業務方法的事務屬性設定為 RequiresNew.調用這個方法時便開始一個新的事務.創建連接時,連接管理器不知道如何使用它,因此它必須從關聯的託管連接獲得一個 XAResource,並在事務中徵募它.連接可能只用於查詢資料庫或者根本不被使用.但是連接管理器必須徵募連接,以備插入或者更新操作.這意味著,資源適配器至少必須進行開始、提交或者回滾,並結束流程返回後端.圖 4 展示了這樣的事務流程.

  圖 4. 急切事務徵募

  在圖 4 中可以看到,獲得連接后,XAResource 立即徵募到了事務中(即接收一個開始流程).這意味著當事務方法結束時,流程需要在資源處結束,即使方法沒有在事務中使用連接.

  如果在事務中涉及另一項資源,就會強制進行不必要的兩階段提交,導致額外的準備流程.這裡的惟一可取之處是資源管理器仍然可以從準備調用中返回 XA_RDONLY (用於「read only」)以表明它實際沒有做任何工作.事務管理器不需要在那個資源管理器處完成調用,並且如果在事務中只有一個資源管理器真正做了工作,那麼事務管理器也許可以避免日誌文件中的惰性寫操作.

  惰性徵募

  現在您應當認識到除非絕對需要,否則不要在事務中徵募.JCA 1.5 規範提供了一個解決方案:惰性徵募.清單 4 顯示了支持這各種優化所引入的兩個介面.

  清單 4. 惰性徵募的介面

1 public interface LazyEnlistableManagedConnection {
2 }
3 public interface LazyEnlistableConnectionManager {
4 void lazyEnlist(ManagedConnection mc)
5 throws ResourceException;
6 }

  LazyEnlistableManagedConnection 介面是由託管連接實現的標記介面,用以向連接管理器表明在事務中創建新的連接或者在連接已經存在的情況下開始一個新的事務時,它不需要將託管連接急切徵募到現有事務中.如果連接句柄準備執行應當是任一事務中的一部分的某些工作,並且它的託管連接還沒有徵募,那麼應當確定連接管理器是否實施了 LazyEnlistableConnectionManager 介面.如果實施了,那麼它應當調用傳遞託管連接的 lazyEnlist 方法.這個方法不返回任何結果,但是如果調用線程關聯了一個事務,那麼這時就徵募託管連接的 XAResource.如果連接沒有被徵募,那麼它需要在後面每一項工作之前再次調用 lazyEnlist,以檢查在上次調用這個方法之後,是不是沒有啟動過事務.

  圖 5 顯示了這個新的事件序列.

  圖 5. 惰性事務徵募

  在圖 5 中可以看到,在獲得連接時,XAResource 不再急切徵募.相反,連接管理器會等待,直到連接用 lazyEnlist 調用表明它要完成一些事務工作時,才會徵募 XAResource.

  什麼時候出現錯誤

  JCA 規範的第一個版本提供了一種讓資源適配器在連接出現嚴重錯誤時通知連接管理器的機制.這是 ConnectionEventListener 介面的 connectionErrorOccurred 方法.收到這個通知后,連接管理器就會毀環發送事件的託管連接,這樣就不會再使用它.這些都是不錯的.但是,如果到後端的連接丟失了,那麼池中的許多託管連接也很有可能不能再使用.

  針對這個問題,JCA 1.5 以 ValidatingManagedConnectionFactory 介面的方式引入了一種雅潔的解決方案,如清單 5 所示.

  清單 5. 用於確定無效連接的介面

1 public interface ValidatingManagedConnectionFactory {
2 Set getInvalidConnections(Set connectionSet)
3 throws ResourceException;
4 }
5

  由託管連接廠實現的 ValidatingManagedConnectionFactory 介面包含一個方法——getInvalidConnections——它以一組託管連接為參數,返回資源適配器認為無效的一個子集.資源適配器的驗證可以採取任何形式,不過通常涉及到對後端的某種「ping」操作,以測試連接.然後連接管理器在資源適配器指示連接錯誤時調用這個方法,甚至定期調用該方法,以便從池中排除壞掉的連接.

  開始和結束

  最初的 JCA 版本為託管連接及其相關聯的連接句柄提供了詳細的生命周期模式,但是它沒有為資源適配器提供這種概念.只有當創建了託管連接廠后,部署的資源適配器才知道它的存在.JCA 1.5 中引入的 ResourceAdapter 介面對此進行了糾正,如清單 6 所示.

  清單 6. 新資源適配器介面的生命周期方法

1 public interface ResourceAdapter {
2 void start(BootstrapContext ctx)
3 throws ResourceAdapterInternalException;
4 void stop();
5 ...
6 }

  資源適配器可以在其部署描述符(ra.xml)的 resourceadapter-class 元素中給出實現這個介面的類的名稱.除了實現 ResourceAdapter 介面,這個類可以通過 JavaBean 樣式支持某些屬性.與託管連接廠一樣,在部署描述符中可以聲明這些屬性及其默認值,如清單 7 所示.在安裝了資源適配器后,應用伺服器將允許管理員覆蓋這些默認值.

  清單 7. 資源適配器部署描述符

1 <connector>

2 ...
3 <resourceadapter>
4 <resourceadapter-class>
5 example.ExampleResourceAdapterImpl
6 </resourceadapter-class>
7 <config-property>
8 <config-property-name>ServerName</config-property-name>
9 <config-property-type>java.lang.String</config-property-type>
10 <config-property-value>MyServer</config-property-value>

11 </config-property>
12 <config-property>
13 <config-property-name>PortNumber</config-property-name>
14 <config-property-type>java.lang.String</config-property-type>
15 <config-property-value>1976</config-property-value>
16 </config-property>
17 </resourceadapter>

18 ...
19 </connector>

  在啟動時,應用伺服器會創建在部署描述符中指定的類的一個實例,並設置管理員提供的屬性.這個類必須根據這些屬性實現一個 equals 方法,這樣應用伺服器就可以保證它不會創建一個以上同樣的實例.然後會調用 start 方法,向它傳遞一個實現了 BootstrapContext 介面的對象.可以用這個對象創建計時器、調度其他線程上的工作和控制導入的事務,在本系列的第 2 部分中將更詳細地討論所有這些內容.這個方法將不會堵塞並會及時返回.

  應用伺服器通常會在關閉或者解除部署資源適配器之前,對資源適配器調用 stop 方法.JCA 1.5 規範描述了這個過程的兩個階段.,應用伺服器保證依賴資源適配器的所有應用程序都已停止.這可保證程序線程不再使用資源適配器對象,並且所有事務都已完成.然後應用伺服器調用 stop 方法.這時,資源適配器將執行一個有序的關閉(例如,釋放網路和應用伺服器資源,並將所有緩存的數據強行送回後端).調用 stop 后,應用伺服器將不會重新使用資源適配器實例.

  為了保留向後兼容性,ManagedConnectionFactory 沒有改變,但是如果希望外部資源可以利用資源適配器具有的功能,那麼還要實現清單 8 所示的新的 ResourceAdapterAssociation 介面.

  清單 8. ResourceAdapterAssociation 介面

1 public interface ResourceAdapterAssociation {
2 ResourceAdapter getResourceAdapter();
3 void setResourceAdapter(ResourceAdapter ra)
4 throws ResourceException;

5 }

  構建了託管連接廠之後,應用伺服器將調用 setResourceAdapter 方法以便將它與其資源適配器關聯在一起.在託管連接廠的生命周期內這種關聯將會固定下來.這種方法只調用一次.

  結束語

  本文展示了 JCA 1.5 為現有出站契約帶來的四項增強功能.惰性關聯和徵募優化會提高使用連接的應用程序的性能,驗證託管連接廠會改善對故障情況的處理.在資源適配器級別引入生命周期管理為資源適配器提供了多種有趣的新機會.本系列的第 2 部分將分析如何在這個基礎上建立新的工作管理和事務流入契約.


[火星人 ] JCA 1.5: 優化和生命周期管理已經有523次圍觀

http://coctec.com/docs/java/show-post-61952.html