Session共享有多種解決方法,常用的有四種:
1)客戶端Cookie儲存
2)伺服器間Session同步
3)使用叢集管理Session(如MSM)
4)把Session持久化到資料庫
針對上面Session共享四種方法的詳解:
1)客戶端Cookie儲存以cookie加密的方式儲存在客戶端.優點是減輕伺服器端的壓力,每次session資訊被寫在客服端,然後經瀏覽器再次提交到伺服器。即使兩次請求在叢集中的兩臺伺服器上完成,也可以到達session共享。
2)將session持久化到資料中這種共享session的方式即將session資訊存入資料庫中,其它應用可以從資料庫中查出session資訊。目前採用這種方案時所使用的資料庫一般為mysql。 利用資料庫共享 session 的方案有一定的實用性,但也有如下缺點:首先 session 的併發讀寫在資料庫中完成,對 mysql 的效能要求比較高;其次,我們需要額外地實現 session 淘汰(超時)邏輯程式碼,即定時從資料庫表中更新和刪除 session 資訊,增加了工作量。
3)使用伺服器間session同步使用主-從伺服器的架構,當使用者在主伺服器上登入後,通過指令碼或者守護程式的方式,將session資訊傳遞到各個從伺服器中,這樣使用者訪問其它的從伺服器時,就可以讀到session資訊。 缺點:比如速度慢、不穩定等,另外,如果 session 資訊傳遞是主->從單向的,會有一些風險,比如主伺服器down了,其它伺服器無法獲得 session 資訊
4)使用叢集統一管理Session提供一個叢集儲存session共享資訊.其他應用統統把自己的session資訊存放到session叢集伺服器組。當應用系統需要session資訊的時候直接到 session 叢集伺服器上讀取。目前大多都是使用 Memcache 來對 Session 進行儲存。
以Memcache來實現Session共享的方式目前比較流行的有兩種實現方案:
a)使用Filter方式:此方式使用過濾器的方式重新對httpRequest 物件進行了包裝,並加入memcached客戶端,此方式的優點是:使用簡單,把過濾器配置進去即可,另外比較靈活,因為它是在客戶端實現的,配置比較靈活,而且伺服器無關,你可以在任何支援servlet的容器上部署。
b)使用Memcached-Session-Manager,俗稱MSM,是一個用於解決分散式 tomcat 環境下 session 共享的問題的開源解決方案。它的實現原理為以tomcat外掛的方式部署在伺服器,修改了 servlet 容器程式碼中的 session 相關程式碼,使其連線 memcached ,在 memcached 中建立和更新session。
MSM為什麼要產生?
通常來說,對於一些大型的web2.0的網站,在正式部署時一般是部署在不同故障域的多臺應用伺服器上,以j2ee應用為例,一般都會部署在tomcat下。假如部署了10臺tomcat伺服器,那這10臺tomcat可能是部署在不同的機器上,然後將應用程式copy到這10臺tomcat下,然後啟動所有tomcat。一般來說這樣做的目的是為了達到負載均衡以及避免單點故障,另外也考慮到國內網路環境的原因,避免跨網路運營商訪問而導致訪問速度低下的問題,當然不要忘了坐鎮這10臺tomcat前端的還有我們的反向代理伺服器。比如nginx,這個就是另一個話題了,下面主要講的是,對於這種分散式tomcat環境,如何保證session 的唯一性??
一般來說,大體的解決方案是通過編寫一段程式碼或者通過配置tomcat的filter,將產生的session放到同一個記憶體資料庫中,事實上這確實可行的。然而這種問題應該有更省事更成熟的解決方案,也就是將要說的Memcached_Session_Manager,簡稱msm,這就是一個用於解決分散式tomcat環境下session共享的問題的開源解決方案。
MSM(即memcached session manager)是一個高可用Tomcat session共享解決方案,除了可以從本機記憶體快速讀取Session資訊(僅針對黏性Session)外,還可使用memcached存取Session,以實現高可用。
對於非黏性Session,memcached直接儲存session。除memcached外,還可以其他快取元件如memcachedb, membase等。
MSM特性:
. 支援黏性、非黏性Session
. 無單一故障點
. 可處理tomcat故障轉移
. 可處理memcached故障轉移
. 外掛式session序列化
. 允許非同步儲存session,以提升響應速度
. 只有當session有修改時,才會將session寫回memcached
. JMX管理&監控
MSM解決的問題:假設有一個Tomcat叢集,使用黏性session,如何應對單點故障問題?
為了應對更多的併發量和可用性,可以不斷的增加Tomcat節點,但是單點故障仍舊會是個問題:
如果使用黏性Session,一個Tomcat故障時,其他Tomcat並不能接管故障Tomcat節點的Session。
解決此問題的思路就是將黏性Session同時儲存在Memcached中,如果單個Tomcat發生故障,叢集中的其他Tomcat可以從Memcached中得到Session資訊。
注意:對於非黏性Session,MSM V1.4.0及以後版本已經支援。
--------------------------------------------------------------------------------------------------------------------------------------------
黏性Session和非粘性Session,一般用於tomcat服務叢集,二者的區別是:
1)黏性Session(即sessionsticky,不復制Session會話):
此模式下同一會話中的請求都被派送到同一個tomcat例項上,這樣就無須在多臺伺服器之間實現session共享了,這是其好處。
不好的地方就是不能實現failureover(故障切換)了,一但使用者訪問的機器掛掉,那麼其session就會丟失。
也就是說當使用者發出第一個request後,負載均衡器動態的把該使用者分配到某個節點,並記錄該節點的路由,以後該使用者的所有request都繫結到這個路由,
使用者只會與該server發生互動,這種策略被稱為粘性session。
這種方式將同一使用者的請求轉發到特定的Tomcat伺服器上,避免了叢集中Session的複製,缺點是使用者只跟一種的一臺伺服器通訊,如果此伺服器down掉,那就廢了。
2)非黏性Session(即sessionreplication,複製Session會話)此模式下同一會話中的請求可以被分配到不同的tomcat例項上進行處理,此時就需要在不
同伺服器之間同步、複製session,這樣一來即使一臺伺服器掛掉了,請求在其它伺服器上照樣可以訪問到session資訊,其缺
點在於Session複製需要系統資源和網路開銷。
-------------------------------------------------------------------------------------------------------------------------------------------------
MSM如何工作?
首先談下tomcat故障轉移
msm安裝在tomcat裡,tomcat會在本地保留所有會話資訊就像StandardManager一樣。此外,一個請求完成後,session會被備份到memcached節點。 當服務同一會話的下一次請求時,tomcat可以在本地找到這個會話資料,同一會話的第二次請求 處理完後,會話資料會更新到memcached節點。 假設處理某個會話的tomcat掛了。 那麼下次請求會被路由到另一個tomcat。而這個tomcat沒有在本地儲存該會話的資料。因此它會去相應的memcached(根據請求頭中sessionid的字尾,後面配置$CATALINA_HOME/conf/context.xml時,memcachedNodes="n1:localhost:11211,n2:localhost:11212",就是n1,n2)中查詢此次請求的會話資料並儲存到本地。 這樣這個tomcat就可以處理此次會話了。當這個tomcat處理完此次會話,它會將更新相應memcached節點儲存的session資訊。
如下圖tomcat1故障,路由到tomcat2由負載均衡完成(如nginx)。
再說下memcahced故障轉移
msm也實現了memcached的故障轉移。當一個memcached節點不可用時,session資訊就會被轉移到其他memcached節點。 與此同時,sessionid會被修改,一個新的JESESSIONID(響應頭會有Set-Cookie:JESSIONID;XXXXXXXXXXXXX)會被髮送 到瀏覽器端。當使用粘性session(sticky session)時,確保你的負載均衡不會給sessionid新增字尾。
SESSIONID的格式
MSM知道Memcached節點列表,這些節點標識會儲存在SESSIONID中,SESSIONID值類似:602F7397FBE4D9932E59A9D0E52FE178-n1 【其中n1為Memcached節點標識】
MSM原理
MSM利用Value(Tomcat 閥)對Request進行跟蹤。Request請求到來時,從memcached載入session,Request請求結束時,將tomcat session更新至memcached,以達到session共享之目的,支援sticky(粘性)和non-sticky(非粘性)模式。需要注意的是使用sticky模式時需要配置jvmroute引數,配置方式如下:
配置$CATALINA_HOME/conf/server.xml
<Engine name="Catalina"defaultHost="localhost"jvmRoute="tomcat2">
注意每臺tomcat的jvmroute引數都不能一樣。
Sticky 模式:
tomcat session為主session,memcached為備session。Request請求到來時,從memcached載入備session到tomcat (僅當tomcat jvmroute發生變化時,否則直接取tomcat session);Request請求結束時,將tomcat session更新至memcached,以達到主備同步之目的。
下面是sticky模式時響應的流程圖:
Non-Sticky模式:
tomcat session為中轉session,memcached1為主session,memcached2為備session。Request請求到來時,從memcached2載入備session到tomcat,(當容器中還是沒有session,則從memcached1載入主session到tomcat,這種情況是隻有一個memcached節點,或者有memcached1出錯時),Request請求結束時,將tomcat session更新至主memcached1和備memcached2,並且清除tomcat session,以達到主備同步之目的。
如下是non-sticky模式的響應流程圖: