咱们都知道对于一些大型的web2.0的网站,在正式部署时通常是部署在不一样故障域的多台应用服务器上,以j2ee应用为例,通常咱们都会部署在tomcat下,假如咱们部署了10台tomcat服务器,那这10台tomcat多是部署在不一样的机器上,而后将应用程序copy到这10台tomcat下,而后启动全部tomcat,通常来讲这样作的目的是为了达到负载均衡以及避免单点故障,另外也考虑到国内网络环境的缘由,避免跨网络运营商访问而致使访问速度低下的问题,固然不要忘了坐镇这10台tomcat前端的还有咱们的反向代理服务器,好比nginx,这个就是另外一个话题了,我今天主要讲的是,对于这种分布式tomcat环境,咱们如何保证session 的惟一性(我假定你知道session是什么)。这也是在日期公司的一个项目中负责解决的一个问题,固然实际上这并非什么新的议题,以前就有不少解决方案,可是通常来讲的大致的解决方案是本身经过编写一段代码或者经过配置tomcat的filter,将产生的session放到同一个内存数据库中,事实上这确实可行的,只不过我比较懒,我老是以为这种问题应该有更省事更成熟的解决方案,那确实是有的,也就是我立刻介绍的 Memcached_Session_Manager,简称msm,这就是一个用于解决分布式tomcat环境下session共享的问题的开源解决方案。css
(如下内容由我的根据msm官网大意翻译,原文地址:http://code.google.com/p/memcached-session-manager/)html
引言前端
MSM--memcached session manager是一个高可用的Tomcat session共享解决方案,除了能够从本机内存快速读取Session信息(仅针对黏性Session)外,同时可以使用memcached存取Session,以实现高可用。java
对于非黏性Session,memcached直接存储session。nginx
除memcached外,还能够其余缓存组件如memcachedb, membase等。web
特性数据库
支持Tomcat六、Tomcat7浏览器
支持黏性、非黏性Session缓存
无单一故障点tomcat
可处理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
环境
Linux 环境
Tomcat7.X (3台),在同一台机器上启动三台Tomcat须要修改conf/server.xml中的三个端口:8080,8005,8009
MemBase (1台),也可采用memcached,使用方法同样,只是在java客户端链接时有不一样。
nginx
准备的jar包
注意:不一样的tomcat版本(tomcat6,tomcat7)所需的包不同,须要针对tomcat版本下载对应的包.
这是采用的最新稳定版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>
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>
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>
当使用javolution序列化方式时将:
Ja transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory” 替换为: 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; }这是负载切换使用的服务器网站
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秒转发到另一台服务器) }
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模式的响应流程图:(图片来源网络)。