tomcat + memcached session manager共享session

    網上有很多關於通過MSM(memcached session manager)實現memcached共享session的文章,但是很多都是東拼西湊,誤導別人。正巧最近有一個地方用到,特此總結一下。

    MSM支持tomcat6,tomcat7,tomcat8,MSM支持兩種模式:sticky sessions(粘性session)和non-sticky sessions(非粘性session)。我用到的是sticky session,所以以下都按照sticky session

來介紹。集羣結構是2個tomcat實例節點,2個memcached實例節點

    <tomcat1>   <tomcat2>
           . \ / .
  machine1 .  X  . machine2
           . / \ .
<memcached1>   <memcached2>

簡單說明下:tomcat1爲主要把它的session存儲到memcached2上,而memcache2是運行在另一臺主機上的(一般情況下,memcached是存tomcat1的session),只有當memcached2不可用時,tomcat1纔會把session存在memcached1上,也就是說memcached1是爲了tomcat1做故障切換用的節點。這要的話,當machine1掛了的時候,session是不會丟失的。


接着我們考慮使用session的哪種序列化方式,默認的是使用java進行序列化,是由memcached-session-manager.jar這個jar包來提供的方法,而其它的序列化方式是由其它的jar包提供的。


首先是要安裝jdk和tomcat,這裏不再贅述,當然tomcat可以選擇支持native函數。在修改tomcat配置文件之前,先把一些jar包放在 $CATALINA_HOME/lib/( WEB-INF/lib)目錄裏,再修改$CATALINA_HOME/conf/ (META-INF/context.xml)配置文件。


我們使用的是memcached,所以需要 spymemcached-2.11.1.jar

補充:如果使用couchbase,需要添加以下jar包: couchbase-client-1.4.0.jar jettison-1.3.jarcommons-codec-1.5.jarhttpcore-4.3.jar,httpcore-nio-4.3.jarnetty-3.5.5.Final.jar


需要注意的是,如果你使用java內置的序列化方式,把jar放在$CATALINA_HOME/lib/裏即可。如果爲了更好的性能,使用自定義的序列化方式,就要把其它jar包部署在具體java項目工程下的WEB-INF/lib裏。以下是四種session序列化方式對應需要的jar包


  • kryo-serializer: msm-kryo-serializer, kryo-serializers-0.11 (0.11 is needed, as 0.20+ is for kryo2), kryo, minlog, reflectasm, asm-3.2

  • javolution-serializer: msm-javolution-serializer, javolution-5.4.3.1

  • xstream-serializer: msm-xstream-serializer, xstream, xmlpull, xpp3_min

  • flexjson-serializer: msm-flexjson-serializer, flexjson


所以非粘性sessions 使用kryo序列化所需要增加的jar包如下:

wKiom1RHEauzhcQnAAC2YW9b-dM187.jpg


雖然我使用的是kryo序列化方式 + 非粘性session,但是還是把粘性session一起介紹一下。

 sticky sessions粘性session + kryo序列化

在machine1上有tomcat1和memcached1,tomcat的$CATALINA_HOME/conf/context.xml增加如下配置

<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:host1.example.com:11211,n2:host2.example.com:11211"
    failoverNodes="n1"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>


參數failoverNodes="n1" 是用來告訴 MSM 把session優先存儲在 memcached2上,只有當memcached2掛了的時候纔會把session存在memcache1也就是配置文件的n1裏。

假如整個machine1掛了,session還是可用,因爲session是存在machine2的memcache2上,可以通過tomcat2對外提供服務。

machine2上的tomcat2的配置文件只要改成failoverNodes="n2"即可。


 non-sticky sessions 非粘性session + kryo序列化

非粘性session是不需要配置failoverNodes,也就是故障切換節點的,因此session是由所有tomcat節點通過輪訓(round-robin )來提供服務的,session是不和某單個tomcat節點綁定,所以tomcat所有節點的都是一樣的,如下:

<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:host1.example.com:11211,n2:host2.example.com:11211"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>

配置完成後重新啓動兩個節點上的不同tomcat服務。

tail -f /usr/local/tomcat/logs/catalina.out

wKiom1RGYIKACNTdAAo-3_MzksQ616.jpg

兩個節點tomcat的啓動日誌都正常。


測試的session.jsp頁面內容如下

SessionID:<%=session.getId()%> <BR>
SessionIP:<%=request.getServerName()%> <BR>
SessionPort:<%=request.getServerPort()%>

瀏覽器訪問測試頁面

wKiom1RGaHSy14-BAALVRBJmvwE682.jpg

頁面獲取的和我chrome瀏覽器截獲的cookie裏session id是一樣的,這裏補充下session id是保存在cookie裏的。

多次刷新頁面session.jsp,發現session id不變化,再查看訪問tomcat的訪問日誌,出現多條訪問記錄(這裏補充說明,tomcat默認是關閉訪問日誌的,需要開啓,然後自定義日誌格式。)但是session保持不變。

wKioL1RGZcCTUVAqAAU_FvVswHg499.jpg

由於session默認是存在tomcat的jvm裏的,我們驗證一下memcached裏是不是真的存了這個session記錄,查詢memcached存的內容然後導出到文件裏

 echo "stats cachedump 3 0" | nc 192.168.203.167 11211 > session.txt
 grep '6EDE9D610F85926D0A5AD01A991DC84C-n1 ' session.txt

wKioL1RGZ8-QnpF9AACI_MweLhM965.jpg

確認存在。

至此tomcat的MSM,共享session的工作就做完了,good luck!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章