嘿,大家好,今天我要更新的內容是session共享。。。
開發背景
由於是比較老的項目(struts2+spring2.5+ibatis),且沒有使用redis進行緩存,項目中需要緩存的東西通通都放到了session中,我們想要達到這樣一個目的,使用Nginx來負載兩個tomcat,這樣我們在更新或者升級代碼的時候,可以保證另外一個項目還可以繼續運行,用戶還可以繼續訪問。那么問題來了,當tomcat-A停止運行的時候,另一個tomcat-B中的session中並沒有tomcat-A中的我們緩存的數據,則不能保證服務正常運行。
所以呢,這里有兩個解決方案,方案A:將所有存取session的操作改到存取redis中,但是由於存取session的地方太多了,工作量過大,而且麻煩,所以這種方案就被pass了,然后我們采取方案B:實現session的共享的方式,使用這種方式的好處就是,不改變原來的代碼邏輯,而且簡單。
順着這條路我開始研究session共享,最終找到兩種可行的方法:
一:tomcat-session-redis
使用tomcat+redis實現session共享,下面是操作步驟以及在配置tomcat-session-redis的時候遇到的一些坑
1.引入三個jar包:commons-pool2-2.2.jar、jedis-2.6.0.jar和tomcat-redis-session-manager-1.2-tomcat-7.jar放在tomcat的 lib下面。(這里博主的jdk和tomcat的版本都是7,大家有興趣可以嘗試下別的版本,點擊鏈接可以下載不同版本的tomcat-redis-session的jar包)
2.然后tomcat的context.xml配置里增加如下配置,不要加錯了哦,博主蠢蠢的把這面這段配置加到了server.xml中導致報錯,好久才發現。。。
其中sessionPersistPolicies有三種策略,上文中的是默認策略,還有另外兩種保存策略,大家可以根據需要選擇配置即可
- SAVE_ON_CHANGE:每次session.setAttribute()或被session.removeAttribute()稱為會話都將被保存。注意:此功能無法檢測對已存儲在特定會話屬性中的對象所做的更改。權衡:此選項會稍微降低性能,因為會話的任何更改都會將會話同步保存到Redis。
- ALWAYS_SAVE_AFTER_REQUEST:每次請求后強制保存,無論管理器是否檢測到會話更改。如果對已存儲在特定會話屬性中的對象進行更改,則此選項特別有用。權衡:如果並非所有請求都改變了會話,則此選項實際上會增加競爭條件的可能性。
配置完成后我們分別啟動Nginx(Nginx.conf配置在文章底部),redis,tomcat-A,tomcat-B,此時查看兩個tomcat服務的sessionId是否一致,如果一致,則說明我們配置成功了。。。
遇到的問題
下面是我在配置時遇到的幾個問題,大家如果在配置的時候,有遇到和我相同問題的可以參考一下:
1.配置要放在context.xml中,而不是server.xml。估計只有我會犯這種錯誤吧,哈哈哈哈~~~
2.保證tomcat配置session交由redis。
2.應用的session管理交由tomcat管理,如果應用針對session做了個性化管理,session 共享會失效,博主就是沒有發現項目中的web.xml對session做了過期時間的設置,導致session 共享會失效。
3.session里不能存入null,因為不能getByte(null),這也是我遇到的一個坑,明明都是配置好了,sessionId也已經相同了,后來查看tomcat-redis-session.jar的源碼發現,將數據通過getByte()的方式序列化到了redis中,但是項目中存在set一個null到session中,導致一直報錯,在相應位置位置做了非空判斷之后,session共享正常。。。
至此Nginx+tomcat+redis配置session共享測試成功!
二:spring-session
注意,spring-session這種方式對spring的版本有一定的要求,由於公司項目使用的spring版本較老,不支持spring-session,所以將spring版本升級到4.3。ps:spring session支持的spring版本最低為spring 4.2以上
具體操作步驟如下:
1.確保spring的版本在4.2之上,如為滿足條件需先升級spring的版本
2.引入spring session與redis相關的jar包,分別為:commons-pool2-2.4.2.jar,jedis-2.9.0.jar,spring-data-redis-1.7.3.RELEASE.jar,spring-session-1.2.2.RELEASE.jar,由於博主項目較老,而且還不是maven管理的,所以這里直接引入相關jar包,如果是maven項目的小伙伴在pom中直接引入相關jar包即可
3. 在web.xml添加過濾器:(放在所有過濾器配置之前)
4.applicationContext.xml文件配置相關redis會話連接管理
遇到的問題
5.至此其實配置已經結束了,但是其實還沒完,這樣配置完成之后會存在List、Map、TreeMap等集合不能序列化,不能存入redis的問題,spring-session默認使用的序列化方式是JdkSerializationRedisSerializer,所以我們要修改spring-session默認的序列化方式,使用我們自定義的序列化方式SessionSerializer,另外我們要把需要存取redis的實體類實現序列化接口~~~
RedisHttpSessionConfig :
SessionSerializer :
配置完成后我們分別啟動Nginx(Nginx.conf配置在文章底部),redis,tomcat-A,tomcat-B,此時查看兩個tomcat服務的sessionId是否一致,如果一致,則說明我們配置成功了。。。
以上就是實現session共享的的兩種方式。。。
Nginx.conf配置文件
使用Nginx負載均配兩個tomcat配置如下:
今天的更新到這里就結束了,拜拜!!!
感謝一路支持我的人,您的關注是我堅持更新的動力,有問題可以在下面評論留言或隨時與我聯系。。。。。。
QQ:850434439
微信:w850434439
EMAIL:gathub@qq.com
如果有興趣和本博客交換友鏈的話,請按照下面的格式在評論區進行評論,我會盡快添加上你的鏈接。
網站名稱:GatHub-HongHui'S Blog
網站地址:https://www.gathub.cn/
網站描述:不習慣的事越來越多,但我仍在前進…就算步伐很小,我也在一步一步的前進。
網站Logo/頭像:[頭像地址]