Roller如何緩存頁面

前面的文章已經談了roller是如何生成頁面的,其實頁面就是一些HTML代碼。在roller中,使用一個類CachedContent對象來包裝這些HTML代碼,然後才把CachedContent對象放到緩存中以便以後使用。

 

談到緩存,roller的開發者們絕不會放過任何一個提高性能的機會。首先利用瀏覽器的緩存功能,見如下代碼:

            if (ModDateHeaderUtil.respondIfNotModified(request, response, lastModified)) {
                return;
            } else {
                // set last-modified date
                ModDateHeaderUtil.setLastModifiedHeader(response, lastModified);
            }

 

 

接下來談談roller如何爲了提高性能如何利用內存來實現緩存的。這裏說的主要針對博客頁面的緩存處理。爲了敘述方便,下面的是筆者根據源代碼整理的類圖:

 

 

在圖中,有兩個單例類,分別是CacheManagerWeblogPageCache。其中WeblogPageCache有一個Cache屬性,在實例化時通過CacheManager實例獲取一個Cache對象。

 

CacheManager實例化時要通過讀取屬性文件來初始化cacheFactory屬性,默認情況下cacheFactory是一個ExpiringLRUCacheFactoryImpl對象。這裏應用了工廠模式。

 

通過圖中我們可以知道WeblogPageCachecontentCache屬性實際是一個ExpiringLRUCacheImpl對象。

 

我們知道緩存很好用,put進去get出來。看起來簡單,但真正的緩存系統要做很多工作,比如是否過期了,如何清理緩存等等。

 

Roller中定義了一個Cache接口,代表一個緩存。有兩個實現類,分別是LRUCacheImplExpiringLRUCacheImpl,他們是父子關係。實現了LRU算法的緩存策略。作爲緩存接口自然少不了這幾個重要的方法:putgetremoveclear

 

WeblogPageCache類爲我們屏蔽了很多實現細節,如果是作爲緩存的使用者,只要瞭解WeblogPageCacheAPI就可以了。WeblogPageCache同樣也有和Cache類似的方法,這些對應的方法其實是把請求委派給Cache來處理。WeblogPageCache還有一個重要的方法generateKey,生產key很重要,但筆者不打算在這裏講。

 

通過類圖和前面的文字介紹,我們可以知道系統是如何準備好緩存等待我們使用的了。

 

前面提到html被包裝到CachedContent對象中,當頁面需要緩存時,WeblogPageCacheput方法被調用,傳入一個keyCachedContent對象。同時new一個LazyExpiringCacheEntry對象來包裝CachedContent。爲什麼這樣做呢?目的是爲了在get時判斷數據是否有效。

 

先說說本人對緩存的兩個概念(有效和過期)的理解。有效是指被緩存的數據已經被修改過了;過期是指當被緩存的數據超過了緩存系統設定的時間長度。

 

WeblogPageCacheput時,其實是把請求委派給Cache對象的,而這個Cache就是一個ExpiringLRUCacheImpl對象。ExpiringLRUCacheImplput方法被調用時,又new了一個ExpiringCacheEntry對象來包裝LazyExpiringCacheEntry對象。這樣做的目的是爲了在get時判斷被緩存數據是否過期。

 

緩存的put過程就是這樣的,下面說說如何從緩存中取出數據,取出數據是通過調用get方法。

 

 

當想獲取一個緩存數據時需要調用WeblogPageCacheget方法,此方法需要傳入一個key和一個博客最近修改時間。Get的過程不是很好描述。WeblogPageCache把請求傳給Cache對象上的get方法。在Cacheget方法中通過keyMap中取出value,這個value先是一個ExpiringCacheEntry對象,因爲此對象被new時初始化了超時時間和緩存時間。所以通過

    public boolean hasExpired() {
        
        long now = System.currentTimeMillis();
        
        return ((this.timeCached + this.timeout) < now);
    }

 

可以判斷一個數據是否過期。如果過期就被從緩存中刪除了,否則就從ExpiringCacheEntry中取出value(也就是LazyExpiringCacheEntry)返回。

 

一個數據不過期並不代表能使用,還要判斷他是否有效。程序控制權回到WeblogPageCacheget方法。如果Cacheget方法不是null,就要判斷是否有效。LazyExpiringCacheEntry對象被new出來時,它的被緩存時間也同時被初始化。由於它是包裝CachedContent對象的,因此它也有個get方法,參數是最近修改時間。在此方法中,通過判斷最近時間是否大於緩存時間來確定數據是否有效。

 

如果數據是有效的就把CachedContent返回,否則就返回null。整個緩存的get過程就這樣結束了。

 

體會:roller的緩存用了工廠模式,這樣的好處是:當我們的站點規模變大時,roller緩存可能滿足不了要求,這時如果使用優秀的緩存系統(比如memcached)是比較容易集成到roller中的。

 

歡迎大家一起討論roller。。。。。。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章