ehcache 頁面緩存

 

關於緩存的話題,在罈子裏已經有很多討論,簡單的來說,如果一個應用中80% 的時間內都在訪問20% 的數據,那麼,這時候就應該使用緩存了。這個和長尾理論正好相悖,其實也不是相悖,只是不同的理論使用的場景不同。在80/20 原則生效的地方,我們都應該考慮是否可以使用緩存。但即使是這樣,緩存也有不同的用法,舉個例子,一個網站的首頁估計是被訪問的次數最多的,我們可以考慮給首頁做一個頁面緩存,而如果在某個頁面上,比如說javaeyejava 版區只有前幾個頁面是訪問最頻繁的,(假設javaeye 是使用hibernate ,當然這只是假設,我們都知道javaeye 是使用ror 開發的)那麼我們就可以考慮給java 版區的record 做二級緩存了,因爲二級緩存中是按照對象的id 來保存的,所以應該來說這前面幾頁使用的對象會一直存在於緩存之中(如何使用hibernate 的二級緩存罈子上也有介紹)。由此可見不同的頁面的緩存策略有可能有天壤之別。

本文的目的就是上面所講的兩種情況之一,頁面緩存。毫無疑問,幾乎所有的網站的首頁都是訪問率最高的,而首頁上的數據來源又是非常廣泛的,大多數來自不同的對象,而且有可能來自不同的db ,所以給首頁做緩存是一個不錯的主意,那麼主頁的緩存策略是什麼樣子的呢,我認爲應該是某個固定時間之內不變的,比如說2 分鐘更新一次。那麼這個緩存應該做在什麼地方呢,讓我們來看一下,假設您的應用的結構是page-filter-action-service-dao-db ,這個過程中的- 的地方都是可以做緩存的地方,根據頁面緩存的特徵,應該把頁面緩存做到儘量靠近客戶的地方,就是在pagefilter 之間,這樣的優點就是第一個用戶請求之後,頁面被緩存,第二個用戶再來請求的時候,走到filter 這個請求就結束了,無需再走後面的action-service-dao-db 。帶來的好處是服務器壓力的減低和客戶段頁面響應速度的加快。

 

那麼我們來看一下如何使用ehcache 做到這一點。

 

在使用ehcache 的頁面緩存之前,我們必須要了解ehcache 的幾個概念,

1 timeToIdleSeconds ,多長時間不訪問該緩存,那麼ehcache 就會清除該緩存。

2 timeToLiveSeconds ,緩存的存活時間,從開始創建的時間算起。

 

看到這裏,我們知道,首頁的頁面緩存的存活時間,我們定的是2 分鐘,那麼也就是說我們的timeToLiveSeconds 應該設置爲120 ,同時我們的timeToIdleSeconds 最好也設置爲2 分鐘,或者小於2 分鐘。我們來看一下下面這個配置,這個配置片段應該放到ehcache.xml 中:

 

< cache name = "SimplePageCachingFilter"

           maxElementsInMemory = "10"

           maxElementsOnDisk = "10"

           eternal = "false"

            overflowToDisk = "true"

           diskSpoolBufferSizeMB = "20"

           timeToIdleSeconds = "10"

           timeToLiveSeconds = "10"

           memoryStoreEvictionPolicy = "LFU"

            />

 

SimplePageCachingFilter 是緩存的名字,maxElementsInMemory 表示內存中SimplePageCachingFilter 緩存中元素的最大數量爲10maxElementsOnDisk 是指持久化該緩存的元素到硬盤上的最大數量也爲10 (),eternal=false 意味着該緩存會死亡。overflowToDisk=true 意思是表示當緩存中元素的數量超過限制時,就把這些元素持久化到硬盤,如果overflowToDiskfalse ,那麼maxElementsOnDisk 的設置就沒有什麼意義了。memoryStoreEvictionPolicy=LFU 是指按照緩存的hit 值來清除,也就是說緩存滿了之後,新的對象需要緩存時,將會將緩存中hit 值最小的對象清除出緩存,給新的對象騰出地方來了(文章最後有ehcache 中自帶的3 種緩存清空策略的介紹)。

 

接着我們來看一下SimplePageCachingFilter 的配置,

< filter >

        < filter-name > indexCacheFilter filter-name >

        < filter-class >

            net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter

        filter-class >

filter >

 

    < filter-mapping >

        < filter-name > indexCacheFilter filter-name >

        < url-pattern > *index.action url-pattern >

filter-mapping >

就只需要這麼多步驟,我們就可以給某個頁面做一個緩存的,把上面這段配置放到你的web.xml 中,那麼當你打開首頁的時候,你會發現,2 分鐘纔會有一堆sql 語句出現在控制檯上。當然你也可以調成5 分鐘,總之一切都在控制中。

 

好了,緩存整個頁面看上去是非常的簡單,甚至都不需要寫一行代碼,只需要幾行配置就行了,夠簡單吧,雖然看上去簡單,但是事實上內部實現卻不簡單哦,有興趣的話,大家可以看看SimplePageCachingFilter 繼承體系的源代碼。

 

上面的配置針對的情況是緩存首頁的全部,如果你只想緩存首頁的部分內容時,你需要使用SimplePageFragmentCachingFilter 這個filter 。我們看一下如下片斷:

 

< filter >

        < filter-name > indexCacheFilter filter-name >

        < filter-class >

            net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter

        filter-class >

filter >

 

    < filter-mapping >

        < filter-name > indexCacheFilter filter-name >

        < url-pattern > */index_right.jsp url-pattern >

filter-mapping >

 

這個jsp 需要被jsp:include 到其他頁面,這樣就做到的局部頁面的緩存。這一點貌似沒有oscachetag 好用。

 

事實上在cachefilter 中還有一個特性,就是gzip ,也就是說緩存中的元素是被壓縮過的,如果客戶瀏覽器支持壓縮的話,filter 會直接返回壓縮過的流,這樣節省了帶寬,把解壓的工作交給了客戶瀏覽器,如果客戶的瀏覽器不支持gzip ,那麼filter 會把緩存的元素拿出來解壓後再返回給客戶瀏覽器(大多數爬蟲是不支持gzip 的,所以filter 也會解壓後再返回流),這樣做的優點是節省帶寬,缺點就是增加了客戶瀏覽器的負擔(但是我覺得對當代的計算機而言,這個負擔微乎其微)。

 

好了,如果你的頁面正好也需要用到頁面緩存,不防可以考慮一下ehcache ,因爲它實在是非常簡單,而且易用。

 

總結:ehcache 是一個非常輕量級的緩存實現,而且從1.2 之後就支持了集羣,目前的最新版本是1.3 ,而且是hibernate 默認的緩存provider 。雖然本文是介紹的是ehcache 對頁面緩存的支持,但是ehcache 的功能遠不止如此,當然要使用好緩存,對JEE 中緩存的原理,使用範圍,適用場景等等都需要有比較深刻的理解,這樣才能用好緩存,用對緩存。

 

最後複習一下ehcache 中緩存的3 種清空策略:

1 FIFO ,first in first out ,這個是大家最熟的,先進先出,不多講了

2 LFU , Less Frequently Used ,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的。如上面所講,緩存的元素有一個hit 屬性,hit 值最小的將會被清出緩存。

2 LRU ,Least Recently Used ,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存。

發佈了27 篇原創文章 · 獲贊 12 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章