天天看點

分布式叢集環境下Session共享的簡單解決方案

關于Cookie和Session的功能與工作原理,在這裡我就不再叙述了,大家想要了解可以看一下我的上一篇部落格,講的還是很細緻的。

但是之前講的Session是運作在一台伺服器上的,所有的通路都會到達我們的唯一伺服器上,這樣我們可以根據用戶端傳來的sessionID,來擷取session,或在對應Session不存在的情況下(session 生命周期到了/使用者第一次登入),建立一個新的Session;但是,如果我們在叢集環境下,假設我們有兩台伺服器A,B,使用者的請求會由Nginx伺服器進行轉發(别的方案也是同理),使用者登入時,Nginx将請求轉發至伺服器A上,A建立了新的session,并将SessionID傳回給用戶端,使用者在浏覽其他頁面時,用戶端驗證登入狀态,Nginx将請求轉發至伺服器B,由于B上并沒有對應用戶端發來sessionId的session,是以會重新建立一個新的session,并且再将這個新的sessionID傳回給用戶端,這樣,我們可以想象一下,使用者每一次操作都有1/2的機率進行再次的登入,這樣不僅對使用者體驗特别差,還會讓伺服器上的session激增,加大伺服器的運作壓力。

為了解決叢集環境下的seesion共享問題,共有4種解決方案:

1.粘性session

粘性session是指Ngnix每次都将同一使用者的所有請求轉發至同一台伺服器上,即将使用者與伺服器綁定。

2.伺服器session複制

即每次session發生變化時,建立或者修改,就廣播給所有叢集中的伺服器,使所有的伺服器上的session相同。

3.session共享

緩存session,使用redis, memcached。

4.session持久化

将session存儲至資料庫中,像操作資料一樣才做session。

其實,最簡單的兩種方案,就是方案一和方案三,都不需要對session進行任何操作,隻需要将Nginx和Tomcat上的配置檔案修改一下即可。由于我們做叢集,通路量一定是比較大的了,對于第一種方案,如果某台伺服器發生故障,此伺服器上的所有使用者的session都會丢失,是以今天我們采用第三種解決方案。

感謝開源項目tomcat-redis-session-manager,感謝項目的發起者jcoleman。

此方案最簡單之處就在于我們無需修改項目,隻需要修改Tomcat的context.xml配置檔案即可,并且,redis伺服器同樣可以做分布式。

接下來,我們來講解一下如何配置tomcat,首先,講解一下注意事項,因為項目的原因,并沒能用maven來管理依賴的包,而在我配置的時候,很正常的發生了包版本間的沖突,從redis中取出的序列化後的session無法轉換為HttpSession,是以,大家做的時候一定要注意版本間的相容問題。

把我使用的版本給大家做個參考吧,tomcat-redis-session-manager-1.1.jar,jedis-2.1.0.jar,commons-pool-1.6.jar

這三個包需放入 tomcat的安裝目錄下的lib檔案夾下,IDE自帶的tomcat可以在配置中檢視。

分布式叢集環境下Session共享的簡單解決方案

需注意的是,當redis的版本‘過高’時,需要依賴commons-pool2.jar,(具體版本不寫)。

接下來,我們就講一下最核心的配置,配置context.xml檔案(檔案路徑workspace\.metadata\.me_tcat7\conf,此處僅是myeclipse編輯器的路徑)

<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />        
    <Manager className="com.radiadesign.catalina.session.RedisSessionManager" 
        host="127.0.0.1" 
        port="9313" 
        database="0" 
        maxInactiveInterval="60"/>           

這個裡的class路徑具體看tomcat-redis-session-manager裡的路徑。

可能你會遇到重新開機tomcat配置檔案會被還原的問題,那麼你還需要修改另一處的context.xml檔案,workspace\Servers\MyEclipse Tomcat v7.0-config檔案夾中的,修改内容同上。

接下來,給大家看一下配置完成後的結果:

分布式叢集環境下Session共享的簡單解決方案