一 簡介
(以下內容由個人根據msm官網大意翻譯,原文地址:http://code.google.com/p/memcached-session-manager/)
引言
MSM--memcached session manager是一個高可用的Tomcat session共享解決方案,除了可以從本機內存快速讀取Session信息(僅針對黏性Session)外,同時可使用memcached存取Session,以實現高可用。
對於非黏性Session,memcached直接存儲session。
除memcached外,還可以其他緩存組件如memcachedb, membase等。
特性
支持Tomcat6、Tomcat7
支持黏性、非黏性Session
無單一故障點
可處理tomcat故障轉移
可處理memcached故障轉移
插件式session序列化
允許異步保存session,以提升響應速度
只有當session有修改時,纔會將session寫回memcached
JMX管理&監控
MSM解決的問題
假設你有一個Tomcat集羣,使用黏性session,如何應對單點故障問題?爲了應對更多的併發量和可用性,你可以不斷的增加Tomcat節點,但是單點故障仍舊會是個問題:如果使用黏性Session,一個Tomcat故障時,其他Tomcat並不能接管故障Tomcat節點的Session。
解決此問題的思路就是將黏性Session同時保存在Memcached中,如果單個Tomcat發生故障,集羣中的其他Tomcat可以從Memcached中得到Session信息。
【注】對於非黏性Session,MSM V1.4.0及以後版本已經支持。
MSM如何工作
【注】以下論述僅針對黏性Session
安裝在Tomcat上的MSM使用本機內存保存session,和StandardManager一樣。另外,當一個請求結束時,session會被送回Memcached進行備份。當下一次請求開始時,本地Session可用,直接服務,請求結束後,session又被送回Memcached備份。
當集羣中的一個Tomcat掛掉,下一次請求會被路由到其他Tomcat上。負責處理此此請求的Tomcat並不清楚Session的信息。此時它會從Memcached查找該Session,更新該Session並將其保存在本機內容。此次請求結束,session被修改,送回Memcached備份。
.
What else?
上邊介紹的是處理Tomcat故障轉移,MSM又是如何處理Memcached故障轉移呢?
如果一個Memcached故障,當前Memcached中的Session會轉移到其他Memcached節點,同時,JSESSIONID被修改並送回瀏覽器。
如果使用黏性Session,應確保loadbalancer中配置生成的JSESSIONID無任何後綴。
SESSIONID的格式
MSM知道Memcached節點列表,這些節點標識會存儲在SESSIONID中,SESSIONID值類似:602F7397FBE4D9932E59A9D0E52FE178-n1 【其中n1爲Memcached節點標識】
二 安裝
參考網站:http://code.google.com/p/memcached-session-manager/wiki/SetupAndConfiguration
環境
1. Linux 環境
2. Tomcat7.X (3臺),在同一臺機器上啓動三臺Tomcat需要修改conf/server.xml中的三個端口:8080,8005,8009
3. MemBase (1臺),也可採用memcached,使用方法一樣,只是在java客戶端連接時有不同。
4. nginx
準備的jar包
注意:不同的tomcat版本(tomcat6,tomcat7)所需的包不一樣,需要針對tomcat版本下載對應的包.
1.這是採用的最新穩定版1.6.1,序列化方式使用的是kryo,注意版本要求與msm版本基本一致,建議統一採用最新穩定版,如下。其中序列化方式是可選的。
2.這是採用的javolution的序列化方式所有需要的包
建議採用kryo序列化方式,效率更高。
配置
1. 將上面所提到的包全部拷貝到tomcat的lib下(三臺tomcat都需要)
2. 修改每臺tomcat的conf目錄下得context.xml文件或者server.xml文件,在其中加入如下任意一段代碼(注意:當使用多臺tomcat時,一定要使用non-sticky模式):
A:使用默認的sticky session,kryo序列化方式,memcached緩存
- <Context>
- ...
- <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
- memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
- failoverNodes="n1"
- requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
- transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
- />
- </Context>
<Context> ... <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211" failoverNodes="n1" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" /></Context>
B:使用non-sticky session
- <Context>
- ...
- <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
- memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.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>
<Context> ... <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.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>
C:使用membase
- <Context>
- ...
- <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
- memcachedNodes="http://host1.yourdomain.com:8091/pools"
- username="bucket1"
- password="topsecret"
- memcachedProtocol="binary"
- sticky="false"
- sessionBackupAsync="false"
- requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
- transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
- />
- </Context>
<Context> ... <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="http://host1.yourdomain.com:8091/pools" username="bucket1" password="topsecret" memcachedProtocol="binary" sticky="false" sessionBackupAsync="false" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" /></Context>
當使用javolution序列化方式時將:
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory”
替換爲:
- transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
配置完成後,分別啓動tomcat,正常啓動說明msm配置成功。
3. 最後附上nginx配置:
修改配置文件nginx\conf\nginx.conf
1. 找到內容server {
在它的上面加入如下內容:
- upstream 10.6.53.120 {
- ip_hash; ----#ip_hash策略將同一IP的所有請求都轉發到同一應用服務器
- server 10.6.53.120:8080;---------我的tomcat端口號
- server 10.6.53.120:7080;
- server 10.6.53.120:6080;
- }<span>(</span><span>這是負載切換使用的服務器網站</span><span>IP)</span>
upstream 10.6.53.120 {ip_hash; ----#ip_hash策略將同一IP的所有請求都轉發到同一應用服務器server 10.6.53.120:8080;---------我的tomcat端口號server 10.6.53.120:7080;server 10.6.53.120:6080;}(這是負載切換使用的服務器網站IP)
2. 找到
location / {root html;index index.html index.htm;}
把內容更改如下:
- location / {
- proxy_pass http://10.6.53.120
- proxy_redirect default;
- proxy_connect_timeout 10; added by me(跟代理服務器連接的超時時間,必須留意這個time out時間不能超過10秒.當一臺服務器當掉時,過10秒轉發到另外一臺服務器)
- }
location / {proxy_pass http://10.6.53.120proxy_redirect default;proxy_connect_timeout 10; added by me(跟代理服務器連接的超時時間,必須留意這個time out時間不能超過10秒.當一臺服務器當掉時,過10秒轉發到另外一臺服務器)}
3. 找到
server {listen 80;server_name localhost;
把內容改成如下:
server {listen 80;server_name 10.6.53.120;
(這是監聽訪問域名綁定那臺服務器80端口的請求)
到這裏所有的配置已經完成,現在準備一個簡單的web工程,並分別部署到三臺tomcat下。啓動memcached(membase),啓動三臺tomcat,啓動nginx,然後在地址欄輸入url地址,看能否成功訪問。關閉其中一臺tomcat,看是否仍然能夠正常訪問,能夠則說明配置nginx配置成功。
三 原理
MSM(memcached-session-manager) 支持tomcat6 和tomcat7 ,利用 Value(Tomcat 閥)對Request進行跟蹤。Request請求到來時,從memcached加載session,Request請求結束時,將tomcat session更新至memcached,以達到session共享之目的, 支持 sticky 和 non-sticky 模式。需要注意的是使用sticky模式時需要配置jvmroute參數,配置方式如下:
配置$CATALINA_HOME/conf/server.xml
<Engine name="Catalina"defaultHost="localhost"jvmRoute="tomcat2">
注意每臺tomcat的jvmroute參數都不能一樣
Sticky 模式:tomcat session 爲 主session, memcached 爲備 session。Request請求到來時, 從memcached加載備 session 到 tomcat (僅當tomcat jvmroute發生變化時,否則直接取tomcat session);Request請求結束時,將tomcat session更新至memcached,以達到主備同步之目的。下面是sticky模式時響應的流程圖(圖片來源網絡):
Non-Sticky模式:tomcat session 爲 中轉session, memcached1 爲主 sessionmemcached 2 爲備session。Request請求到來時,從memcached 2加載備 session 到 tomcat,(當 容器 中還是沒有session 則從memcached1加載主 session 到 tomcat, 這種情況是隻有一個memcached節點,或者有memcached1 出錯時),Request請求結束時,將tomcat session更新至 主memcached1和備memcached2,並且清除tomcat session 。以達到主備同步之目的,如下是non-sticky模式的響應流程圖:(圖片來源網絡)。