為了使web應(yīng)用能使用saas模式的大規(guī)模訪問,必須實(shí)現(xiàn)應(yīng)用的集群部署.要實(shí)現(xiàn)集群部署主要需要實(shí)現(xiàn)session共享機(jī)制,使得多臺應(yīng)用服務(wù)器之間會話統(tǒng)一, tomcat等多數(shù)服務(wù)都采用了session復(fù)制技術(shù)實(shí)現(xiàn)session的共享.
session復(fù)制技術(shù)的問題:
(1)技術(shù)復(fù)雜,必須在同一種中間件之間完成(如:tomcat-tomcat之間).
(2)在節(jié)點(diǎn)持續(xù)增多的情況下,session復(fù)制帶來的性能損失會快速增加.特別是當(dāng)session中保存了較大的對象,而且對象變化較快時(shí),性能下降更加顯著.這種特性使得web應(yīng)用的水平擴(kuò)展受到了限制.
session共享的另一種思路就是把session集中起來管理,首先想到的是采用數(shù)據(jù)庫來集中存儲session,但數(shù)據(jù)庫是文件存儲相對內(nèi)存慢了一個(gè)數(shù)量級,同時(shí)這勢必加大數(shù)據(jù)庫系統(tǒng)的負(fù)擔(dān).所以需要一種既速度快又能遠(yuǎn)程集中存儲的服務(wù),所以就想到了memcached.
memcached是什么?
memcached是由Danga Interactive開發(fā)的,高性能的,分布式的內(nèi)存對象緩存系統(tǒng),用于在動態(tài)應(yīng)用中減少數(shù)據(jù)庫負(fù)載,提升訪問速度。
memcached能緩存什么?
通過在內(nèi)存里維護(hù)一個(gè)統(tǒng)一的巨大的hash表,Memcached能夠用來存儲各種格式的數(shù)據(jù),包括圖像、視頻、文件以及數(shù)據(jù)庫檢索的結(jié)果等。
memcached快么?
非???。memcached使用了libevent(如果可以的話,在linux下使用epoll)來均衡任何數(shù)量的打開鏈接,使用非阻塞的網(wǎng)絡(luò)I/O,對內(nèi)部對象實(shí)現(xiàn)引用計(jì)數(shù)(因此,針對多樣的客戶端,對象可以處在多樣的狀態(tài)), 使用自己的頁塊分配器和哈希表, 因此虛擬內(nèi)存不會產(chǎn)生碎片并且虛擬內(nèi)存分配的時(shí)間復(fù)雜度可以保證為O(1).。
Danga Interactive為提升Danga Interactive的速度研發(fā)了memcached。目前,LiveJournal.com每天已經(jīng)在向一百萬用戶提供多達(dá)兩千萬次的頁面訪問。而這些,是由一個(gè)由web服務(wù)器和數(shù)據(jù)庫服務(wù)器組成的集群完成的。memcached幾乎完全放棄了任何數(shù)據(jù)都從數(shù)據(jù)庫讀取的方式,同時(shí),它還縮短了用戶查看頁面的速度、更好的資源分配方式,以及memcache失效時(shí)對數(shù)據(jù)庫的訪問速度。
memcached的特點(diǎn)
memcached的緩存是一種分布式的,可以讓不同主機(jī)上的多個(gè)用戶同時(shí)訪問, 因此解決了共享內(nèi)存只能單機(jī)應(yīng)用的局限,更不會出現(xiàn)使用數(shù)據(jù)庫做類似事情的時(shí)候,磁盤開銷和阻塞的發(fā)生。
使用memcached來存儲session有兩種方案:
(1)直接通過tomcat6的擴(kuò)展機(jī)制實(shí)現(xiàn).
參考: http://www.javaeye.com/topic/81641
(2)通過自己編寫filter實(shí)現(xiàn).
考慮到系統(tǒng)的擴(kuò)展,我們采用這種方案.這樣可以使session共享機(jī)制和中間件脫鉤.
參考: http://www.javaeye.com/topic/82565
主要思路:
(1)繼承重構(gòu)HttpServletRequestWrapper,HttpSessionWrapper類,覆蓋原來和session存取相關(guān)的方法呢,都通過SessionService類來實(shí)現(xiàn).
(2)使用filter攔截cookie中的sessionId,通過sessionId構(gòu)造新的HttpServletRequestWrapper對象,傳給后面的應(yīng)用.
(3)SessionService連接memcached服務(wù),以sessionId作為key,存取的對象是一個(gè)map.map的內(nèi)容即為session的內(nèi)容.
使用過程注意幾個(gè)問題和改進(jìn)思路:
1、memcache的內(nèi)存應(yīng)該足夠大,這樣不會出現(xiàn)用戶session從Cache中被清除的問題(可以關(guān)閉memcached的對象退出機(jī)制)。
2、如果session的讀取比寫入要多很多,可以在memcache前再加一個(gè)Oscache等本地緩存,減少對memcache的讀操作,從而減小網(wǎng)絡(luò)開銷,提高性能。
3、如果用戶非常多,可以使用memcached組,通過set方法中帶hashCode,插入到某個(gè)memcached服務(wù)器
對于session的清除有幾種方案:
(1)可以在凌晨人最少的時(shí)候,對memcached做一次清空。(簡單)
(2)保存在緩存中的對象設(shè)置一個(gè)失效時(shí)間,通過過濾器獲取sessionId的值,定期刷新memcached中的對象.長時(shí)間沒有被刷新的對象自動被清除.(相對復(fù)雜,消耗資源)