軟體項目實訓及課程設計指導——如何應用EhCache緩存框架提高應用系統持久層響應性能
1、在Web應用系統中應用持久層相關的緩存框架
在Java應用程式開發實現和J2EE Web應用系統的設計和開發實現中,軟體應用系統的設計和開發實現人員可以在系統的表示層和系統的持久層中充分地應用緩存機制和相應實現技術能夠大大地提高Web應用系統的訪問性能。
比如資料庫連接池、多線程應用中的線程池、對象復用池以及各種應用框架中的緩存插件,如Hibernate框架中常使用的二級緩存插件EHCache,分布式應用環境中的高速緩存系統MemCache,基於key-value(鍵/值對)遠程字典服務的Redis以彌補MemCache等系統在key-value形式的存儲應用中的不足。
因此,合理並有效地使用緩存技術能夠優化軟體應用系統中的數據訪問性能,這特別是在基於Web方式的應用系統中由於要支持大並發的訪問量,更應該要應用相關的緩存技術——有效地應用緩存技術可以減少Web伺服器與資料庫伺服器之間的網絡交互的次數,從而提高應用系統數據訪問速度並減少等待時間。
作者在下文為讀者介紹在J2EE應用系統中廣泛應用的兩個較流行的Java對象緩存框架Whirlycache和EhCache,考慮到本文的篇幅關係,作者重點介紹EhCache緩存框架。
2、在Web應用系統中應用whirlycache緩存框架
(1)Whirlycache是一個快速的、可配置的、存在於內存中的對象緩存
該緩存框架為開源項目,能夠通過緩存對象來加快Web應用系統的請求響應的速度。讀者可以在Whirlycache的官方網站(參看下圖瀏覽器URL地址欄中所示的下載地址)下載Whirlycache有關的系統包文件。請見下圖所示的系統包下載的頁面內容的局部截圖。
(2)熟悉和應用Whirlycache開源緩存項目
Whirlycache開源緩存項目需要開發人員在系統的Classpath路徑中添加一個名稱為whirlycache.xml的配置文件——如果開發人員沒有提供該配置文件,Whirlycache系統將自動地應用whirlycache jar包文件中的whirlycache-default.xml文件中的預設的配置項目。
另外,為了能夠簡化開發人員對使用Whirlycache開源緩存項目的配置工作,在Whirlycache開源緩存項目中為開發人員提供了一個模板的配置文件,只需要在該模板配置文件中進行局部地調整有關的配置項目就可以應用Whirlycache開源緩存系統。
如果讀者需要了解和學習如何應用Whirlycache開源緩存系統,可以瀏覽Whirlycache的官方網站上提供的在線幫助文檔說明。下圖所示為Whirlycache的官方網站上提供的「Quick Start」的幫助內容的局部截圖,從該頁面中可以了解如何通過編程方式緩存應用系統中的對象的程序代碼。
3、在Web應用系統中應用EhCache緩存框架
(1)Ehcache開源緩存系統
EhCache緩存具有運行速度快、結構簡單、佔用內存小以及很小的依賴性、並支持多CPU伺服器等技術特性。在J2EE 平臺中的O/R Mapping類型框架——Hibernate框架中將EhCache緩存作為一個插件被引入,並作為Hibernate框架的查詢緩存的實現插件。
讀者可以通過EhCache官方網站(參看如下示圖所示的瀏覽器URL地址欄中的地址)獲得EhCache相關的系統包文件及技術幫助文檔。
(2)在Hibernate框架中使用EhCache開源緩存系統
在Hibernate框架中如果需要使用EhCache開源緩存項目,首先需要在hibernate.cfg.xml的配置文件中添加如下的設置項目:
<property name=」 hibernate.cache.provider_class」>
org.hibernate.cache.EhCacheProvider</property>
其次,EhCache緩存系統有它自己的配置文件——文件名稱為ehcache.xml,在Hibernate框架的系統庫中的etc目錄下有一個ehcache.xml的模板配置文件,讀者只需要將其複製到Web應用程式的WEB-INF/classes目錄下、並對其中的相關項目進行更改以匹配自己的Web應用程式。如下示圖為某個項目中的ehcache.xml模板配置文件代碼示例。
4、在Hibernate框架的系統包中已經包含有Ehcache的系統庫文件
讀者可以按照如下示圖所示的官方網站的網址進入Hibernate框架的官方網頁,點擊頁面中的「Hibernate ORM」連結(參看如下示圖所示的連結)。
然後將進入Hibernate框架的系統庫下載的頁面,參看如下示圖所示。讀者可以根據待開發的項目需要下載對應版本的Hibernate框架的系統庫文件(一般是下載最新版本)。
5、在Web項目中應用Hibernate框架中的查詢緩存
很多Hibernate框架的使用者在調用其相應方法時都迷信地相信「Hibernate框架會自行為我們處理性能的問題」,或者「Hibernate會自動為我們的所有操作調用緩存」。實際的情況是Hibernate雖然為我們提供了很好的緩存機制和擴展緩存框架的支持,但是必須經過正確的調用,它才有可能發揮作用。
所以造成很多應用系統中使用Hibernate框架後出現了系統的性能問題,這實際上並不是Hibernate框架不行或者不好,而是因為使用者沒有正確的了解其使用方法而造成的。因此,為了能夠在Hibernate框架中正確地應用EhCache緩存系統從而實現Hibernate框架中的查詢緩存,需要完成如下的系統配置定義。
(1)在hibernate.cfg.xml系統配置文件中進行相關的配置
為了啟用查詢緩存(Query Cache),開發人員需要在hibernate.cfg.xml文件中進行如下的配置,參考配置請參看如下代碼示例中的黑體標識的代碼或者參看如下示例圖中的配置結果。
<hibernate-configuration>
<session-factory>
…………
<property name="cache.use_query_cache">true </property>
<property
name="cache.provider_class">org.hibernate.cache.EhCacheProvider
</property>
…………
</session-factory>
</hibernate-configuration>
該設置將會創建兩個緩存區域:一個用於保存Hibernate返回的查詢結果集(org.hibernate.cache.StandardQueryCache); 另一個則用於保存最近查詢的一系列表的時間戳(org.hibernate.cache.UpdateTimestampsCache)。
但要注意的是,在查詢緩存中,它並不緩存結果集中所包含的實體的確切狀態;它只緩存這些實體的標識符屬性的值、以及各值類型的結果。所以查詢緩存通常會和二級緩存一起使用。如下示例圖顯示某個項目中啟用了Hibernate框架的查詢緩存後,在控制臺中輸出的狀態提示信息。
但要注意的是,如果在Web應用系統項目中是使用Spring框架調用Hibernate框架的sessionFactory(會話工廠對象)方式時,則需要進行如下的設置定義(注意其中黑體標識的代碼)。
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"> <ref bean="datasource" /> </property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="connection.provider_class">
org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider</prop>
</props>
</property>
<property name="mappingDirectoryLocations">
</list><value>/WEB-INF/classes/cn/rmic/manager/hibernate/<value> </list>
</property>
</bean>
很多的Hibernate框架的使用者在配置到這一步就以為完事了,其實光這樣配置,根本就沒有使用Hibernate框架的二級緩存。同時因為在使用Hibernate框架時大多時候是馬上關閉會話session。所以,Hibernate框架中的一級緩存也沒有起到任何作用。結果就是沒有使用任何的緩存,所有的Hibernate框架的操作都是直接操作物理資料庫系統。
因此,正確的辦法是除了以上的配置外,還應該配置每一個PO持久對象的具體緩存策略,在影射文件中增加配置對應的項目。
(2)在Hibernate框架的對象/關係映射文件中配置出對持久對象的具體緩存的應用策略
<class name="example.UserInfo" table=」userInfo」>
<cache usage="read-only"/>
....
</class>
在上面的配置項目中的關鍵就是這個<cache usage="read-only"/>項目,其中的usage屬性可以有如下的幾個選擇:read-only、read-write和transactional等。此外,在程序代碼中只有通過調用query.iterate()方法時,Hibernate框架系統程序才會調用緩存中保存的數據。同時 get 和 load方法也都會查詢在緩存中保存的數據。
(3)在Web項目中還需要配置與EhCache緩存系統相關的配置
為此,需要在Web項目中系統根目錄中添加一個文件名稱為ehcache.xml的XML格式的配置文件,操作過程可以參考如下示例圖。
本示例所涉及的ehcache.xml配置文件的示例代碼請參看如下代碼示例,並注意其中黑體標識的代碼或者參看如下示例圖中的最終配置結果。
<?xml version="1.0" encoding="UTF-8" ?>
<ehcache>
<diskStorepath="java.io.tmpdir"/>
<defaultCachemaxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
timeToLiveSeconds="7200" overflowToDisk="true"/>
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
<cache name="myCacheRegion" maxElementsInMemory="10" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" />
</ehcache>
(4)在Web項目的DAO組件中將Query.Cacheable設置為true
絕大多數的查詢並不能從查詢緩存中受益,所以Hibernate框架默認是不進行查詢緩存的。如果在Web應用系統項目中需要啟用查詢緩存,請調用 Query.setCacheable(true)方法。這個調用會讓查詢在執行過程中先從緩存中查找結果,並將自己的結果集放到緩存中以更新緩存。
因此,在Web應用系統程序中必須在查詢執行之前,將Query.Cacheable屬性設置為true,而且每次都應該要進行這樣的設置。參看如下的代碼示例或者參看如下示例圖所示的代碼:
Query oneQuery =session.createQuery(hql).setInteger(0.15);
oneQuery.setCacheable(true);
當然,也可以採用如下形式的代碼:
oneQuery.setCacheable(true); //激活查詢緩存
oneQuery.setCacheRegion("myCacheRegion"); //指定要使用的cacheRegion,可選
上面代碼示例中的第二行指定要使用的cacheRegion是名稱為myCacheRegion的配置定義(參看如下示例圖所示),即開發人員可以給每個查詢緩存做一個單獨的配置——這樣開發人員能夠實現對查詢緩存的失效策略進行精確的控制,通過調用Query.setCacheRegion()方法, 為每個查詢指定其命名的緩存區域。
如果使用setCacheRegion方法來做這個指定,則需要在ehcache.xml文件中配置它(請見前面的配置示例)。如果省略第二行,不設置cacheRegion的話,那麼會使用上面提到的標準查詢緩存的配置,也就是org.hibernate.cache.StandardQueryCache;如果不存在與類名匹配的cache名稱,則用defaultCache名稱。
但要注意的問題是:當Hibernate框架更新資料庫中的數據時,它怎麼知道更新哪些查詢緩存呢?
Hibernate框架會維護對每個資料庫表的最後更新時間,這些更新時間其實也就是放在上面org.hibernate.cache.UpdateTimestampsCache所指定的緩存配置裡面。
當通過Hibernate框架更新時,Hibernate框架會知道這次更新影響了哪些資料庫表。然後它更新這些資料庫表的最後更新時間。每個緩存都有一個生成時間和這個緩存所查詢的資料庫表,當Hibernate框架查詢一個緩存是否存在時,如果此緩存存在,它還要取出緩存的生成時間和這個緩存所查詢的資料庫表,然後去查找這些資料庫表的最後更新時間,如果有一個資料庫表在生成時間後更新過了,那麼這個緩存將是無效的。
因此,可以看出,Web應用系統只要更新過一個資料庫表,那麼凡是涉及到這個資料庫表的查詢緩存就失效了,因此查詢緩存的命中率可能會比較低。
(5)在Hibernate框架的hibernate.cfg.xml系統配置文件中添加如下配置:<property name="log4j.logger.org.hibernate.cache">debug</property>
該配置項目的主要目的是在調試Web應用系統中的相關程序時能夠使用Log4j日誌處理系統輸出調試相關的信息(等同於log4j.logger.org.hibernate.cache=debug),從而能夠更方便地了解EhCache緩存系統的工作過程。
但這個配置定義項目主要用於對Web應用項目程序調試的過程,在Web應用系統正式發布時候,需要通過注釋的方式除掉該配置項目,以免影響Web應用系統的性能。
課程設計指導——如何應用OSCache緩存框架提高Web頁面響應性能
課程設計指導—如何在Struts框架中應用FreeMarker模板技術的實例
如何應用Web頁面靜態化技術以提高J2EE Web應用系統的響應性能
如何應用XML+XSLT+AJAX組合技術實現無刷新的數據查詢的應用實例
課程設計指導——應用AJAX技術提高Web應用系統的整體響應性能