目前,為了使web能适應大規模的通路,需要實作應用的叢集部署。叢集最有效的方案就是負載均衡,而實作負載均衡使用者沒一個請求都有可能被配置設定到不固定的伺服器上,這樣我們首先要解決session的統一來保證無論使用者的請求被轉發到哪個伺服器上都能保證使用者的正常使用,即需要實作session的共享機制。
在叢集系統下實作session統一的有如下幾種方案:
(1) 應用伺服器間的session複制共享(如tomcat自帶session共享)
(2) 基于cache db緩存的session共享
應用伺服器間的session複制共享(tomcat自帶的功能)
session複制共享,主要是指叢集環境下,多台應用伺服器之間同步session,使session保持一緻,對外透明。 如果其中一台伺服器發生故障,根據負載均衡的原理,web伺服器(apache/nginx)會周遊尋找可用節點,分發請求,由于session已同步,故能保證使用者的session資訊不會丢失。
此方案的不足之處:
技術複雜,必須在同一種中間件之間完成(如:tomcat-tomcat之間).
session複制帶來的性能損失會快速增加.特别是當session中儲存了較大的對象,而且對象變化較快時, 性能下降更加顯著. 這種特性使得web應用的水準擴充受到了限制。
session内容序列化(serialize),會消耗系統性能。
session内容通過廣播同步給成員,會造成網絡流量瓶頸,即便是内網瓶頸。
基于 memcached 緩存的 session 共享
即使用cachedb存取session資訊,應用伺服器接受新請求将session資訊儲存在cache db中,當應用伺服器發生故障時,web伺服器(apache/nginx)會周遊尋找可用節點,分發請求,當應用伺服器發現session不在本機記憶體時,則去cache db中查找,如果找到則複制到本機,這樣實作session共享和高可用。
目前有開源的msm用于解決tomcat之間的session共享:memcached_session_manager(msm)
http://code.google.com/p/memcached-session-manager/
一個高可用的tomcat session共享解決方案,除了可以從本機記憶體快速讀取session資訊(僅針對黏性session)外,同時可使用memcached存取session,以實作高可用。
支援tomcat6、tomcat7支援黏性、非黏性session
無單一故障點
可處理tomcat故障轉移
可處理memcached故障轉移
插件式session序列化
允許異步儲存session,以提升響應速度
隻有當session有修改時,才會将session寫回memcached
jmx管理&監控
該方案的不足之處:
memcache支援的資料結構比較單一
memcache的記憶體必須足夠大,否則會出現使用者session從cache中被清除
需要定期的重新整理緩存
伺服器故障時,存在于記憶體的memcache資料将會丢失
為了解決基于memcache中存在的不足,故提出了下面的一種解決方案:
基于redis緩存的session共享
結合上面的分析後,由 redis 負責 session 資料的存儲,而我們自己實作的 session manager 将負責 session 生命周期的管理。利用 redis 自身的key過期時間機智,我們不再需要定期重新整理和做其他額外的處理。
截止到2015-09-20 前是不支援tomcat8的,開源git 位址:https://github.com/jcoleman/tomcat-redis-session-manager
因為我們使用redis 來存儲session,是以前提是redis已經安裝和配置完成。(本文不進行redis 的安裝配置說明)
使用步驟:
1、将 tomcat-redis-session-manager-1.2.jar 、jedis-2.6.1.jar、commons-pool2-2.2.jar 三個jar包拷貝到tomcat7/lib中。
2、在tomcat 的conf/context.xml 檔案裡增加如下内容(或者在server.xml的context塊中添加):
3、重新開機tomcat7,到redis 中檢視session_id,如下:
這裡進行一下特殊說明:
git 開源項目是直接将sessionid作為key存儲到redis中的,如下所示:
我對該項目做了一點修改。
修改原因包括幾點:
1、項目也有使用redis 做其他資料存儲,直接使用這樣的key存儲到redis中,直覺上無法區分哪些key是用來做session共享用的。
2、項目包括好幾個服務(web、wap、cms),每個服務都需要做負載均衡session共享,這樣以來無法區分哪些session是屬于哪個服務的。
3、很難統計每個服務的線上使用者數。
我在叢集部署中我的每個服務都有不同的sessioncookiename(web = wjsessionid、wap = mjsessionid、cms = cmsjsessionid)
不知道怎麼配置的,這裡簡單說一下,直接在tomcat7/conf/server.xml 的最下面的context中增加 sessioncookiename 配置即可:
我修改後的項目已經共享到:http://download.csdn.net/detail/catoop/9122857 (項目是一個maven項目)
其中 tomcat-redis-session-manager\target\tomcat-redis-session-manager-1.2.jar 可以直接使用。
-----------------------------
(完)