瞎 扯
磕磕碰碰一天,百度了好幾篇,終于搞定了Session共享的問題,以前只是聽說將Session存入第三方來解決Session共享問題,可一直沒有親自動手實作過,還記得以前面試時被一道怎么用Redis解決Session共享問題給懟得老慘,現在再問到,雖然可能還是會被懟,但多多少少能說上幾句了,此文純粹是記錄我這一天解決這問題的程序,要想面試打敗面試官,多去找找其他博文,
問題起源:服務器端Tomcat集群,負載策略采用的Ip-Hash方式,不存在Session共享問題,后因Jmeter壓測,在無權更改測驗機為多IP模擬IP欺騙的情況下,將負載策略更改為輪詢方式,然后,就有活干了,
參 考 致 謝
負載策略可參考:https://blog.csdn.net/qq_35119422/article/details/81505732
需要用到Redis Session Manager for Apache Tomcat專案,https://github.com/jcoleman/tomcat-redis-session-manager ,但是官方說的了,暫時不支持tomcat8,上Github上逛了一圈,無私奉獻的大神挺多的,因為我專案用到的是tomcat8.5,找了好幾個才找到個簡單可用的(沒有試是否支持其他版本),
原始碼我用的這哥們的:https://github.com/cc-chen/tomcat8.5-redis-session-manager.git,萬分感謝!
下 載 配 置
省事的朋友們,可跳過原始碼,所需jar包我打好了,需要的自行下載:
下載地址:https://pan.baidu.com/s/1DuY-S9GHCgvWmTn1DvvvOg
提取碼:cg6g
解壓后為這三個jar包,
jedis-2.5.2.jar,
commons-pool2-2.2.jar
tomcat8.5-redis-session-manager.jar
將這三個包放在tomcat的lib目錄下,然后修改config目錄下context.xml檔案,新增如下配置(大多數博主通用配置):
<Valve className="com.s.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.s.tomcat.redissessions.RedisSessionManager"
host="127.0.0.1"
port="6379"
database="0"
password="123456"
maxInactiveInterval="60" />
引數說明:
通用配置
className:tomcat8.5-redis-session-manager.jar中類全路徑,有木有發現,與網上其他大多數博客寫的名稱不一樣,是因為該jar包有修改原官網專案包名,
host:redis master Ip地址
port:redis master 埠
password:redis密碼
database:資料庫下標(redis默認從0到15 16個磁區)
maxInactiveInterval:session超時時間,單位min(測驗無效,該怎么設定和失效原因后續會說明)
測驗方法:
默認Redis主從集群已經配置好,測驗結果如下,(由于是本地,所以Tomcat,Redis均為偽集群,也就是IP一樣埠不一樣)
在各個tomcat/webapp/ROOT 目錄下的jsp頁面合適位置加上IP:Port-Session Id : <%= request.getSession().getId() %>(我選擇的第51行),啟動tomcat8086,8087,tomcat啟動前保證Redis主從集群運行正常,否則tomcat啟動會報錯,啟動成功后,訪問tomcat主頁,在同一瀏覽器輸入:127.0.0.1:8086,127.0.0.1:8087,查看頁面的sessionId以及reids中sessionId,如果如圖所示,恭喜你,成功一半了:

如果redis中存上了sessionId,且兩個tocat服務sessionId一樣,重復重繪,sessionId不變,驗證成功,
然后洗掉Redis中的sessionId,再次重繪,

此時sessionId變了,但是兩個服務的sessionId仍然一樣,驗證成功,
大多數博客到這就完了,但真的成功了么?NO!
哨兵集群配置
上面配置是大多數博客都寫到的配置,不知道大家發現個問題沒,上面host配置只有一個地址,既主節點地址,當redis為單機時,或者集群模式為主從模式時,這樣配置才好使,因為我們只需配置主節點連接資訊就可以了,但主節點宕了,不就崩了么?現在大多數用到redis的服務,為保證其高可用,幾乎都會選擇哨兵模式或者Redis-Cluster模式吧,那么問題來了,當主節點宕了后,當其他從節點升級為主節點后,節點連接資訊變了,那上面的配置是不是得改了?
不用驚訝,因為當初找到的幾篇博客都大同小異,沒有提到這種場景,官網看了下,奈何全是英文,就自個研究了下原始碼,這就是傳說中的自己坑自己吧!后來也有看到別的博文介紹哨兵集群時tomcat conf.xml的配置,去官網上也看到了相關的配置說明,不過我弄的時候沒看到啊,暈!塞翁失馬焉知非福,雖然也不知道研究了下原始碼得到了啥識訓,,,,
要了解多個的配置,首先看看原始碼中怎么讀取單個host,port等配置引數的,找找看:

719行,新建JedislPool用到了咱們組態檔里的引數,看看else另一個條件,那個sentinel單詞不就是哨兵么,看看里面相關的sentinelMaster,sentinelSet的get、set方法,

sentinelMaster需要傳個master,sentinelSet需要傳個sentinels,顧名思義,master是主節點名稱,sentinels是各個節點的連接資訊,抱著試一試的態度,在context.xml組態檔中又加上倆引數,
同樣:這里默認Redis集群模式已經更改為哨兵模式且正常運行(Redis哨兵集群這里就不贅述了),
sentinelMaster="mymaster"
sentinels="127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381"
新增引數說明:
sentinelMaster:master名稱
sentinels:哨兵集群時地址配置,IP:port,用英文逗號隔開
然后重啟兩個tomcat,接下來繼續驗證:驗證方式和上面一樣,當上面兩個步驟驗證完后,將當前主節點手工關掉,然后再次重繪瀏覽器驗證,發現sessionId依然有效,至此,已經成功百分之九十了,
過期時間
剩下的百分之十,就是session過期的問題了,在啟動tomcat時,會有個警告

說明那個maxInactiveInterval引數配置有點問題,出問題了,那就原始碼里看看啥情況,找到原始碼中設定session超時時間的地方,在RedisSessionManager類中,377和545行還有632行,這個時間值都用到的getMaxInactiveInterval()方法,如下

再看看getMaxInactiveInterval()方法

看到這兒似乎明白了,本專案中并不是根據我們的組態檔中引數賦值,這個時間設定的值取的是Tomcat容器的session-timeout 節點(單位min),更改tomcat conf/web.xml配置,約595行
<session-config>
<session-timeout>10</session-timeout>
</session-config>
去掉組態檔中的maxInactiveInterval引數,更改web.xml 中session-timeout時間為2分鐘,重啟Tomcat測驗session失效場景,驗證成功,至此Tomcat8.5集成Redis 解決Session會話共享問題算是大功告成!
謹記,官方檔案很重要!很重要!很重要!仔細看看會少走很多彎路!
以上內容均為個人對別人成果的學習和總結,有理解不到位的地方,還請各路大神指點!
原創不易,看了覺得有幫助的朋友們,記得點個贊喲,謝謝!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/140026.html
標籤:其他
下一篇:一個編程小白的開場白
