轉自:http://blog.csdn.net/catoop/article/details/48603891
目前,為了使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塊中添加):
- <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
- <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
- host="localhost" <!-- 可選,默認是"localhost" -->
- port="6379" <!-- 可選,默認是 "6379" -->
- database="0" <!-- 可選,默認是 "0" -->
- maxInactiveInterval="60" <!-- 可選,默認是 "60" (單位:秒)--> />
3、重啟Tomcat7,到redis 中查看session_id,如下:
- 127.0.0.1:6379> keys WJ*
- 1) "WJSESSIONID:6D5B0E0FD89E3A170B8BC5B8C112D3FD"
- 2) "WJSESSIONID:9546B26D78C99E8F0BF785535E319271"
- 3) "WJSESSIONID:839A35CFE17E900A81F50D629C104D2F"
- 4) "WJSESSIONID:1C287C797CF00C82BBBF37A617A3B55C"
- 5) "WJSESSIONID:FA2822C5021139641760754242F73393"
- 6) "WJSESSIONID:E904369E5B24D39B4E25515D50650EA6"
- 127.0.0.1:6379>
這里進行一下特殊說明:
git 開源項目是直接將SESSIONID作為key存儲到redis中的,如下所示:
- 1) "6D5B0E0FD89E3A170B8BC5B8C112D3FD"
- 2) "9546B26D78C99E8F0BF785535E319271"
- 3) "839A35CFE17E900A81F50D629C104D2F"
- 4) "1C287C797CF00C82BBBF37A617A3B55C"
- 5) "FA2822C5021139641760754242F73393"
- 6) "E904369E5B24D39B4E25515D50650EA6"
我對該項目做了一點修改。
修改原因包括幾點:
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 配置即可:
- <Context docBase="F:\workspace\web" path="" reloadable="false" sessionCookieName="WJSESSIONID" />
我修改后的項目已經共享到:http://download.csdn.NET/detail/catoop/9122857 (項目是一個maven項目)
其中 tomcat-redis-session-manager\target\tomcat-redis-session-manager-1.2.jar 可以直接使用。
-----------------------------
(完)