天天看點

tomcat叢集擴充session集中管理,Memcached-session-manager使用總結

最近在研究tomcat做負載均衡的時候如何實作ha,還有就是不采用session複制的方法做叢集。

想到的是将session全部存儲在後端的緩存伺服器中。

正好網上有這麼一個工具Memcached-session-manager(後面簡稱msm),是以直接扒下來用了。

位址如下:

[url]http://code.google.com/p/memcached-session-manager/[/url]

[b]msm支援 stickty(沾粘會話)和non-sticky(非沾粘會話)兩種叢集方式。[/b]

sticky就是前端的loadbanlence能保證每個使用者的請求都路由到了同一個tomcat上。

non-sticky則每一次請求都可能路由到了不同的tomcat中。

至于msm在這兩種方式是怎麼處理的看下圖:

下圖來自javaeye的xxtianxiaxing的部落格,我這裡引用一下,原文位址為[url]http://xxtianxiaxing.iteye.com/blog/1269704[/url]

1. [b]sticky[/b]

[img]http://dl.iteye.com/upload/picture/pic/102960/e1fd2d95-609a-37b7-a814-05621194d388.jpg[/img]

2. [b]non-sticky[/b]

[img]http://dl.iteye.com/upload/picture/pic/102962/31e3ccfc-8053-3d77-8fad-0452d8b7abf8.jpg[/img]

用msm的session管理manager替代tomcat自身的standardManager。

可以配置在虛拟伺服器的context标簽中,也可以在context.xml裡面全局配置。

<!--sticky

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"

memcachedNodes="n1:localhost:11211"

requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"

transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"

copyCollectionsForSerialization="false"

<!--下面這個是可選的,自己定義特殊的類注冊到kryo自定義轉換器中,實作序列化-->

customConverter="com.test.serializer.CustomKryoRegistration"

/>

-->

<!--non sticky

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"

memcachedNodes="n1:localhost:11211"

sticky="false"

sessionBackupAsync="false"

lockingMode="auto"

requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"

transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"

/>

上面采用的序列化方式是kryo,根據官方提供的資料,這個的序列化效率是最好的,我下面有一些簡單的測試。

感覺kryo的效率主要展現在高并發下面。如果非高并發感覺跟java的自帶io差不多。如果不使用kryo進行序列化,采用java預設方式的話,請将transcoderFactoryClass改為:de.javakaffee.web.msm.JavaSerializationTranscoderFactory

另外在使用kryo進行序列話的時候,有時候會報序列話錯誤。我開始就報ConcrrentHashMap這個類不能序列化的錯誤。tomcat在的session的Atrribute使用了這個資料結構來儲存。要解決這個問題,需要自己寫一個類,将這些特殊的類注冊進去。然後打個jar包放tomcat的lib下。就ok了。

下面是例子:

package com.test.serializer;

import java.util.concurrent.ConcurrentHashMap;

import com.esotericsoftware.kryo.Kryo;

import com.esotericsoftware.kryo.serialize.MapSerializer;

import de.javakaffee.web.msm.serializer.kryo.KryoCustomization;

public class CustomKryoRegistration implements KryoCustomization {

public void customize(Kryo kryo) {

kryo.register(ConcurrentHashMap.class, new MapSerializer(kryo));

}

}

把這個類打好jar包放tomcat的lib目錄下。然後還需要在context中配置customConverter="com.test.serializer.CustomKryoRegistration",這樣就OK了。

另外內建kryo序列化的環境需要以下jar包。剛開始googleCode的官方網站上沒寫。搞了半天,後來提醒原作者加上了:

kryo-serializer: msm-kryo-serializer, kryo-serializers, kryo, minlog, reflectasm, asm-3.2

其他序列化方式(java自帶的序列化方式外的3方序列化方式)需要的jar:

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

可以檢視官方網站的文檔:[url]http://code.google.com/p/memcached-session-manager/wiki/SetupAndConfiguration[/url]

搭建好所有環境之後,采用1 nginx(ip_hash)+2 tomcat6.0.35+sticky(最好用6.0.2以上版本,因為新的msm包裡面使用了6.0.2才有的新方法,不然會報NoSuchMethod-changeSessionId()的錯誤)

[b]驗證是否成功[/b]:

登入釋出的系統(發現這個時候請求全部路由到tomcat1),之後,關閉tomcat1,繼續在裡面做有關session的操作。發現這個時候請求被tomcat2接管,而且session依然保持(從memcached中拿出)。ok,這樣就說明成功了。

non_sticky的配置一樣按上面的方法來驗證是否成功。

*********[b]最後是我在搭建好msm環境後做的一些簡單測試[/b]:***************

測試環境:T5870 2.0G cpu,記憶體2G小本本,win7系統。tomcat,memcache全部裝win7上。啟動一個memcahed服務給了32m記憶體。tmcat52m記憶體。

ok,首先是前面沒有負載均衡,單個tomcat的情況,請求一個sevlet連結,連結就是從session取個值出來的操作。

用apache ab,-C 參數帶上cookie參數模拟有session的請求,100人,共5000次請求是下面的結果:

不用msm: 1000req/s

msm-sticky kryo: 850req/s

msm-sticky java标準序列化: 830req/s

msm-nonsticky kryo : 440/s(50人并發) 430/s(100人并發)

msm-nosticky java标準序列化 : 480/s(50人并發) 270/s(100人并發)

[b]在sticky的情況下[/b],因為在本地有session的情況下,省略了從memcached取session緩存的情況,序列化次數不多,是以性能隻有大概1/10的損耗。

[b]在non-stikcy的情況下[/b],集中的每次從memcached取session,性能損失了大概一半。

而可以看出,在高并發的情況下,kryo序列化比java标準序列化要好。并發性能大概在java标準序列化一倍以上。而且在搞并發的non-sticky的情況下,session中的多線程并行操作沖突嚴重。lock很多(當然這個lock模式可以設定,甚至可以完全不要鎖)。這也嚴重降低了速度。

[b]又測試了1台nginx(ip_hash做負載均衡)+2tomcat的情況[/b]。

因為暫時沒法模拟多ip的請求,是以所有請求都隻路由到了tomcat1上。采用kryo序列化的政策依然保持了高并發下處理速度不下降的優勢。

還是400多r/s,而java标準序列化還是要低一半多。

[b]

最後推薦采用sticky+kryo的政策來實作msm~![/b]