當前位置:才華齋>IT認證>J2EE>

構建高效能J2EE應用的技巧

J2EE 閱讀(5.81K)

  Java效能的基礎----記憶體管理

構建高效能J2EE應用的技巧

任何Java應用,單機的或J2EE的效能基礎都可歸結到你的應用是如何管理記憶體的問題。Java的記憶體管理包括兩個重要任務:記憶體的分配和記憶體的回收。在記憶體的分配中,目標是要減少需要建立的物件。 記憶體回收是導致效能下降的普遍原因。也就是說,記憶體中的物件越多,垃圾回收越困難。所以我們對建立物件的態度應該越保守越好。

在J2EE應用中常見的兩個記憶體有關的問題是:遊離的物件(也被稱為記憶體洩露)和物件迴圈(指大量頻繁建立和刪除-在Java中體現為解除引用---物件)。

我們應注意確保所有可到達的物件實際是活的,即這些物件不但在記憶體中,而且也要在執行的程式碼中是存在的。當物件在應用中已經沒有用了,而我們卻忘記了刪除對該物件的引用時,遊離的物件就出現了。

我們知道垃圾回收會佔用CPU時間。短期物件的大量建立增加了垃圾回收的頻率會造成效能下降。

  不要在Servlet中實現業務邏輯

在構建J2EE應用時,架構工程師通常會使用到J2EE的基本部分,Servlet。

如果架構師不使用Session Beans, Entity Beans, 或 Message Beans, 那麼改進效能的方法就很少。只能採用增加CPU或更多的物理伺服器等方法。EJB使用了快取(cache)和資源池等方法可以提高效能和擴充套件性。

  儘可能使用本地介面訪問EJB

在早期的J2EE (遵循EJB1.X規範)應用中,訪問EJB是`通過RMI使用遠端介面實現的。隨著EJB2.0的出現,可以通過本地介面訪問EJB,不再使用RMI,在同一個JVM中使用遠端方法已經少多了。但是現在還是有一些使用EJB1.X實現的應用和不知道使用本地介面的一些EJB新手。為說明這點,我們作個比較:

1, 客戶端應用呼叫本地Stub

2, 該Stub裝配引數

3, 該Stub傳到skeleton

4, 該skeleton分解引數

5, 該skeleton呼叫EJB物件

6, EJB物件執行容器服務

7, EJB物件呼叫企業BEAN例項

8, 企業BEA執行操作

9, 執行組裝/分解步驟然後返回

與遠端介面處理相比較,本地介面的EJB方法是:

1. 客戶端呼叫本地物件

2. 本地物件執行容器服務

3. 本地物件呼叫企業Bean例項

4. 企業Bean例項執行操作

5. 沒有其他返回步驟!!

如果你不需要從遠端的客戶端訪問一個特殊EJB,就應該使用本地方法。

  在實現Session Bean的.服務中封裝對實體EJB的訪問

從Servlet訪問實體EJB不但效率低而且難於維護。使用Session Facade(會話外觀)模式可把對實體EJB的訪問封裝在會話EJB中,在該會話EJB中通過使用本地介面訪問實體EJB而避免過多的遠端呼叫。

這項技術會有額外的效能和擴充套件方面的好處,這是因為會話和實體EJB可以使用快取和資源池技術來進行改進。另外,由於負載的需要,會話和實體EJB可被擴充套件部署到其他硬體裝置上,這比將Servlet層複製擴充套件到其他硬體裝置上要簡單的多。

  儘量粗粒度訪問遠端EJB

當訪問遠端EJB時,呼叫set/get方法將產生過多的網路請求,同時也導致遠端介面處理的過載。為避免這種情況,可考慮將資料屬性集中在一個物件中,這樣通過一次對遠端EJB的呼叫就可以傳遞所有資料。這項技術就是資料傳輸物件(Data Transfer Object)模式。

  優化SQL

J2EE的架構設計工程師和開發人員通常不是SQL專家或經驗豐富的資料庫管理員。首先應該確保SQL使用了資料庫提供的索引支援。在某些情況下,將資料庫的索引和資料分開存放會提高效能。但要知道,增加額外的索引可以提高SELECT效能但也會降低INSERT的效能。對於某些資料庫,關聯表之間的排序會嚴重影響效能。可以多向資料庫管理員諮詢。

  避免在實體EJB中過多執行SQL

有時候,通過實體EJB訪問資料會執行多個SQL語句。根據J2EE 規範,第一步,將呼叫實體Bean的find(發現)方法;第二步,在第一次呼叫實體EJB的業務方法時,容器會呼叫ejbLoad()從資料庫中獲得資訊。

很多CMP(容器管理永續性)在呼叫發現方法時就快取了實體資料,所以在呼叫ejbLoad()時就不再訪問資料庫了。應該避免使用BMP(Bean管理的永續性)或者自己實現快取演算法避免二次訪問資料庫。

  使用Fast Lane Reader 模式訪問只讀資料

J2EE應用經常要以只讀方式訪問大量長時間不變的資料,而不是訪問單個實體,例如瀏覽線上產品目錄。在這種只讀情況下,使用實體EJB訪問資料會導致嚴重過載並且實現很麻煩。實體EJB 適合於對單個實體的粗粒度訪問,訪問大量的列表只讀資料時效率不高。不管是使用CMP還是BMP,一定需要編寫程式碼操作多個實體EJB及其關聯。這將導致訪問多個數據庫並存在大量的也是不必要的事務開銷。

  利用Java Messaging Servce(訊息服務)

J2EE規範在JMS中提供了內建的非同步處理服務。當涉及到系統需求時,應該瞭解在什麼情況下應該採用JMS進行非同步處理的設計。一旦確定要執行一些非同步處理,那麼同步處理的任務就應該越少越好,將資料庫密集的操作安排在稍後的非同步處理中完成。

  快取JNDI Lookup查詢

很多操作在進行JNDI查詢時要消耗大量資源。通常應該快取JNDI資源避免網路呼叫和某些處理的過載。可以快取的JNDI查詢包括:

EJB Home Interfaces

Data Sources

JMS Connection Factories

MS Destinations/Topics

一些JNDI包實現了快取功能。但是呼叫對EJB主介面的narrow方法時,這種功能作用有限。

快取查詢的設計應該使用共享的IntialContext例項,儘管構建它很麻煩。這是因為需要訪問多種資料來源,包括應用資原始檔erties,系統屬性的各項引數,傳入到建構函式的各項引數。