tomcat叢集擴充套件session集中管理,Memcached-session-manager使用總結
阿新 • • 發佈:2019-01-29
最近在研究tomcat做負載均衡的時候如何實現ha,還有就是不採用session複製的方法做叢集。
想到的是將session全部儲存在後端的快取伺服器中。
正好網上有這麼一個工具Memcached-session-manager(後面簡稱msm),所以直接扒下來用了。
地址如下:
http://code.google.com/p/memcached-session-manager/
msm支援 stickty(沾粘會話)和non-sticky(非沾粘會話)兩種叢集方式。
sticky就是前端的loadbanlence能保證每個使用者的請求都路由到了同一個tomcat上。
non-sticky則每一次請求都可能路由到了不同的tomcat中。
至於msm在這兩種方式是怎麼處理的看下圖:
下圖來自javaeye的xxtianxiaxing的部落格,我這裡引用一下,原文地址為 http://xxtianxiaxing.iteye.com/blog/1269704
1. sticky
2. non-sticky
用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
可以檢視官方網站的文件: http://code.google.com/p/memcached-session-manager/wiki/SetupAndConfiguration
搭建好所有環境之後,採用1 nginx(ip_hash)+2 tomcat6.0.35+sticky(最好用6.0.2以上版本,因為新的msm包裡面使用了6.0.2才有的新方法,不然會報NoSuchMethod-changeSessionId()的錯誤)
驗證是否成功:
登入釋出的系統(發現這個時候請求全部路由到tomcat1),之後,關閉tomcat1,繼續在裡面做有關session的操作。發現這個時候請求被tomcat2接管,而且session依然保持(從memcached中拿出)。ok,這樣就說明成功了。
non_sticky的配置一樣按上面的方法來驗證是否成功。
*********最後是我在搭建好msm環境後做的一些簡單測試 :***************
測試環境: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人併發)
在sticky的情況下,因為在本地有session的情況下,省略了從memcached取session快取的情況,序列化次數不多,因此效能只有大概1/10的損耗。
在non-stikcy的情況下,集中的每次從memcached取session,效能損失了大概一半。
而可以看出,在高併發的情況下,kryo序列化比java標準序列化要好。併發效能大概在java標準序列化一倍以上。而且在搞併發的non-sticky的情況下,session中的多執行緒並行操作衝突嚴重。lock很多(當然這個lock模式可以設定,甚至可以完全不要鎖)。這也嚴重降低了速度。
又測試了1臺nginx(ip_hash做負載均衡)+2tomcat的情況。
因為暫時沒法模擬多ip的請求,所以所有請求都只路由到了tomcat1上。採用kryo序列化的策略依然保持了高併發下處理速度不下降的優勢。
還是400多r/s,而java標準序列化還是要低一半多。
最後推薦採用sticky+kryo的策略來實現msm~!
想到的是將session全部儲存在後端的快取伺服器中。
正好網上有這麼一個工具Memcached-session-manager(後面簡稱msm),所以直接扒下來用了。
地址如下:
http://code.google.com/p/memcached-session-manager/
msm支援 stickty(沾粘會話)和non-sticky(非沾粘會話)兩種叢集方式。
sticky就是前端的loadbanlence能保證每個使用者的請求都路由到了同一個tomcat上。
non-sticky則每一次請求都可能路由到了不同的tomcat中。
至於msm在這兩種方式是怎麼處理的看下圖:
下圖來自javaeye的xxtianxiaxing的部落格,我這裡引用一下,原文地址為
1. sticky
2. non-sticky
用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
可以檢視官方網站的文件:
搭建好所有環境之後,採用1 nginx(ip_hash)+2 tomcat6.0.35+sticky(最好用6.0.2以上版本,因為新的msm包裡面使用了6.0.2才有的新方法,不然會報NoSuchMethod-changeSessionId()的錯誤)
驗證是否成功:
登入釋出的系統(發現這個時候請求全部路由到tomcat1),之後,關閉tomcat1,繼續在裡面做有關session的操作。發現這個時候請求被tomcat2接管,而且session依然保持(從memcached中拿出)。ok,這樣就說明成功了。
non_sticky的配置一樣按上面的方法來驗證是否成功。
*********最後是我在搭建好msm環境後做的一些簡單測試
測試環境: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人併發)
在sticky的情況下,因為在本地有session的情況下,省略了從memcached取session快取的情況,序列化次數不多,因此效能只有大概1/10的損耗。
在non-stikcy的情況下,集中的每次從memcached取session,效能損失了大概一半。
而可以看出,在高併發的情況下,kryo序列化比java標準序列化要好。併發效能大概在java標準序列化一倍以上。而且在搞併發的non-sticky的情況下,session中的多執行緒並行操作衝突嚴重。lock很多(當然這個lock模式可以設定,甚至可以完全不要鎖)。這也嚴重降低了速度。
又測試了1臺nginx(ip_hash做負載均衡)+2tomcat的情況。
因為暫時沒法模擬多ip的請求,所以所有請求都只路由到了tomcat1上。採用kryo序列化的策略依然保持了高併發下處理速度不下降的優勢。
還是400多r/s,而java標準序列化還是要低一半多。
最後推薦採用sticky+kryo的策略來實現msm~!