天天看點

使用memcached實作tomcat叢集中Session共享業務場景

業務場景描述:

有這樣的業務架構,一台nginx将用戶端請求分發到2台tomcat中,現在的問題是當tomcat1挂掉之後,nginx将請求轉發到tomcat2中,此時tomcat2會要求使用者重新登入,造成使用者感覺不好(實際使用者已經登入成功過了)。

現在想做到tomcat1挂掉之後,當nginx将請求分發到tomcat2的時候,不讓使用者再次登入,即完成兩個tomcat的Session共享功能

解決方案:

1:安裝并啟動Memcached

Memcached的安裝和服務啟動,請參考本人編寫的博文《MemCached的安裝和JAVA用戶端連接配接Memcached示例代碼》,記得一定要保證Memcached能連接配接,用Java用戶端緩存資料後在取出來試一下。

2:下載下傳需要的包,tomcat7版本,這裡面坑很多,切記版本一緻一緻一緻,不然啟動報錯,把你繞死

asm-3.2.jar

couchbase-client-1.4.8.jar:msm依賴這個包

kryo-1.04.jar

kryo-serializers-0.9.jar

memcached-session-manager-1.6.5.jar

memcached-session-manager-tc7-1.6.5.jar:不同版本Tomcat需要使用不同的Jar包,tc7代表tomcat7版本

minlog-1.2.jar

msm-kryo-serializer-1.6.0.jar

reflectasm-1.01.jar

spymemcached-2.10.3.jar:Jave用戶端連接配接memcached的jar包,這個包可以選擇安裝memcached安裝版本對應的jar包

    将上面這些包放到tomcat的lib目錄下面,記得是tomcat的lib目錄,不是web應用的lib目錄

3:配置web應用

這裡有兩種方式修改web應用,讓應用在啟動的時候連接配接memcached服務,并同步tomcat Session。

第一種方式,修改tomcat的server.xml

<Context docBase="webApp" path="/" reloadable="false" source="org.eclipse.jst.jee.server:webApp">
       		<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"  
    			memcachedNodes= "n1:111.111.111.1:11211"
    			requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"  
    			transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"  />
      	</Context>
           

第二種方式,在webApp應用的webApp\WebRoot\META-INF\目錄下面增加context.xml,内容如下

<?xml version="1.0" encoding="UTF-8"?>
	<Context>
       		<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"  
    			memcachedNodes= "n1:111.111.111.1:11211"
    			requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"  
    			transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"  />
	</Context>
           

測試驗證:

1:隻啟動一台經過配置的tomcat

浏覽器中登入系統,請求一個接口,可以看到接口請求中的Request Header中帶了JSESSION屬性,背景日志列印也有JSESSION屬性,

這時關閉tomcat伺服器,然後在重新開機伺服器完成之後,還是在上面開啟的浏覽器中請求另外一個接口,可以看到請求中的Request Header中帶了JSESSION屬性沒變,背景日志中JSESSION屬性也沒變,memcached中管理的session同步過來了,不需要再次登入了。

2:啟動兩台tomcat,nginx配置分發到這兩台伺服器,兩台伺服器互為主備

浏覽器中登入系統,請求一個接口,可以看到接口請求中的Request Header中帶了JSESSION屬性,背景日志列印也有JSESSION屬性,

這時關閉tomcat1伺服器, 同浏覽器中繼續請求接口,可以看到請求中的Request Header中JSESSION屬性沒變,tomcat2中背景日志JSESSION屬性沒變,不要再次登入系統驗證。

這時啟動tomcat1,關閉tomcat2, 同浏覽器中繼續請求接口,可以看到請求中的Request Header中JSESSION屬性沒變,tomcat1中背景日志JSESSION屬性也沒變,業務場景功能實作啦。

走過的坑:

1:確定memcached能通,能緩存資源

2:下載下傳的Jar包放到tomcat的lib目錄中,不是web應用的lib目錄

3:切記下載下傳的jar包的版本一緻,不然各種缺少列

4:注意選擇合适的修改應用的配置方式

5:配置檔案中的标簽都是大寫字母打頭,如:是<Context>而不是<context>,是<Manager>而不是<manager>

6:更新生産環境的時候,一般生産環境都有端口和防火牆隔離的,記得需要将和memcached互動的端口打開

如上配置的不足點與解決方法:

如上的配合會導緻A機器session變動,不同同步到B機器同session,可以有如下兩種方式解決此問題:

一:修改tomcat的server.xml(這種方式會偶爾出現session變動的情況,不太穩定)

這個時候需要如下配置不同tomcat的server.xml,修改<Engine屬性,最後加上jvmRoute屬性,這樣就可以強制session變化後備份到memcached,并且另外一台機器要使用session的時候從memcached中獲得,詳細配置如下

<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
           

二:修改memcached-session-manage的同步方式,在webApp應用的webApp\WebRoot\META-INF\目錄下面增加context.xml,内容如下

<?xml version="1.0" encoding="UTF-8"?>
	<Context>
       		<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"  
    			memcachedNodes= "n1:111.111.111.1:11211"
           
sessionBackupAsync="false"
    			requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"  
    			transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"  />
	</Context>
           

這種方式的參考文章: https://code.google.com/archive/p/memcached-session-manager/

繼續閱讀