一.简单说明
上次配置了基于tomcat自身的session复制集群,但是它只适用于节点较少的集群,此次配置的是session共享的集群,使用的是memcached-session-manager即MSM;
以下是个人翻译,水平有限难免出错。详情可查看官网介绍:
1.MSM简介
为了简单整合,你只需安装一个tomcat(6,7或8)和memcached(或支持memcached协议的),在不同硬件条件下的生产环境中,你可以有几个tomcat也可以有几个memcached节点。MSM支持sticky sessions粘性会话)和non-sticky sessions(非粘性会话);
sticky session:
tomcat session(即本地session)为主session,memcached为备session。Request请求到来时,直接取tomcat session,当tomcat jvmroute发生变化时,从memcached加载备session到tomcat,Request请求结束时,将tomcat session更新至memcached,以达到主备同步之目的。
non-sticky session:
tomcat session为中转session, 假设memcached1为主session ,memcached2 为备session。Request请求到来时,从memcached2加载备session到tomcat,如果memcached2没有就从memcached1上读取session,如果memcached1也没有就读取本地session,如果没有本地session就在本地创建,当请求结束时,将本地的session更新至memcached1和memcached2上,并且清除本地的session;
下面给出一个黏性session模式的设置示例,此例中安装了2个tomcat以及2个memcached,Tomcat-1(t1)首要的将其session存储在运行在另一台主机上的memcached-2(m2)上(m2是t1的一个普通节点),只有当m2不可用时,t1才会把其session存储到memcached-1(m1,m1是t1的故障转移节点)上。使用这种配置,即使主机1(运行着t1和m1)宕机了session也不会丢失。
具体如下图所示:
t1 t2
. \ / .
. X .
. / \ .
m1 m2
那么该如何实现呢?
2.选择使用哪种序列化策略
有几个通过SerializationStrategies描述的可用的session 序列化策略,默认策略使用java进行序列化,这种实现已经集成在memcached-session-manager.jar包中了,其它的策略则可以通过不同的jar包来提供实现,在下面的章节中,可以了解每种策略所需要的jar包具体有哪些;
3.配置tomcat
tomcat的配置主要包括两个方面:下载所需要的jar包放到$CATALINA_HOME/lib/和WEB-INF/lib/下(应用的WEB-INF/lib/),同时还需要配置memcached session manager关联Context组件(如应用所在的META-INF/context.xml);
3.1 Add memcached-session-manager jars to tomcat
不管选择哪种序列化策略,总是会需要memcached-session-manager-${version}.jar,并且如果是tomcat6则还要使用 memcached-session-manager-tc6-${version}.jar,tomcat7要使用memcached-session-manager-tc7-${version}.jar(注意:是tomcat7.0.23+的),tomcat8要使用memcached-session-manager-tc8-${version}.jar。
如果使用了memcached还需要使用spymemcached-2.11.1.jar
如果使用了couchbase另外还需要couchbase-client-1.4.0.jar jettison-1.3.jar commons-codec-1.5.jar httpcore-4.3.jar httpcore-nio-4.3.jar netty-3.5.5.Final.jar;
然后下载合适的jar并放到$CATALINA_HOME/lib/中即可;
3.2 Add custom serializers to your webapp (optional)
如果内置的JAVA序列化,那么需要的jar包就是以上所列出的那些了。如果想使用自定义的序列化策略(出于更好的性能缘故),我们还需要下载相应的jar包并放到webapp下的WEB-INF/lib/目录中。
如果你的应用使用了maven来进行jar包管理,那么你只需要在pom.xml中加入相应的序列化策略依赖定义就可以了,具体的maven依赖定义如下(任选一种就oK了):
kryo-serializer:
-
<dependency>
-
<groupId>de.javakaffee.msm</groupId>
-
<artifactId>msm-kryo-serializer</artifactId>
-
<version>1.9.1</version>
-
<scope>runtime</scope>
-
</dependency>
javolution:
-
<dependency>
-
<groupId>de.javakaffee.msm</groupId>
-
<artifactId>msm-javolution-serializer</artifactId>
-
<version>1.9.1</version>
-
<scope>runtime</scope>
-
</dependency>
xstream:
-
<dependency>
-
<groupId>de.javakaffee.msm</groupId>
-
<artifactId>msm-xstream-serializer</artifactId>
-
<version>1.9.1</version>
-
<scope>runtime</scope>
-
</dependency>
flexjson:
-
<dependency>
-
<groupId>de.javakaffee.msm</groupId>
-
<artifactId>msm-flexjson-serializer</artifactId>
-
<version>1.9.1</version>
-
<scope>runtime</scope>
-
</dependency>
如果使用的不是基于maven仓库的依赖关系管理,不同的序列化策略需要不同的jar,其对应关系如下:
kryo-serializer: msm-kryo-serializer, kryo-serializers-0.34, kryo-3.x, minlog, reflectasm, asm-5.x
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
3.3 Configure memcached-session-manager as Manager
处理完jar包之后,我们还需要修改META-INF/context.xml文件中Context节点下的内容,添加memcached-session-manager配置。
以下配置示例展示了使用memcached来管理黏性和非粘性会话以及使用membase来管理非粘性会话。memcached的示例假设有两个memcached实例,一个在host1上另一个在host2上,所有的配置示例假设使用的序列化为kryo;
sticky sessions + kryo :
下面的示例展示了第一个tomcat的配置,假设它和memcached节点n1运行在host1上,属性failoverNodes="n1"会告诉MSM最好存储session在memcached节点n2上且如果没有其他memcached节点(这里仅n2)可用时才仅存储session在n1上(运行在同一个主机上),即使host1完全宕机,仍然可以通过host2上的tomcat访问存放在memcached "n2" 节点中的session;对于host2上的tomcat配置只需将failoverNodes设为n2,其他一切不变;
-
<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>
non-sticky sessions + kryo:
下面的示例展示了非粘性session的配置,这种情况下不需要配置failoverNodes属性,因为session是被所有的tomcat轮询使用并非被限制到一个tomcat上,对于非粘性session来说,所有的tomcat配置如下:
-
<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>
non-sticky sessions with couchbase + kryo:
如果是使用membase来对session进行管理,那么则某一个节点的配置如下:
-
<Context>
-
...
-
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
-
memcachedNodes=""
-
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>
multiple contexts sharing the same session id:
如果运行多个webapps或contexts共享同一个session(例如tomcat6中通过设置sessionCookiePath="/"或emptySessionPath="true")你必须告诉memcached session manager给session id添加前缀当存储session到memcached中时。这样,你可以使用storageKeyPrefix属性如下例子展示:
-
<Context sessionCookiePath="/">
-
...
-
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
-
memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
-
failoverNodes="n1"
-
storageKeyPrefix="context"
-
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
-
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
-
/>
-
</Context>
你在Context/Manager组件中配置了MSM后,你可以启动你的应用并且session会被存储到memcached节点或者membase中,现在你可以做一些如模拟节点失效,重启节点等测试;
4.可用的memcached-session-manager配置属性
5.日志配置
补充:
MSM的特性:
支持tomcat6 tomcat7 tomcat8
支持黏性和非粘性会话
无单点故障
支持对tomcat故障转移的处理
支持对memcached故障转移的处理
支持可插拔的session序列化
支持异步session存储以达到更快的响应速度
只有当session修改时才写回到memcacehd上
支持JMX管理和监控
二.具体配置
配置环境:
192.168.85.128+Apache
192.168.85.129+tomcat1+memcached1
192.168.85.130+tomcat2+memcached2
1.安装memcached
可以源码安装,也可以直接yum install memcached,这里采用后者,而且这里的配置有些事继承上次的配置,部分配置过程没有写,详情可看一下上篇文章;
2.将所需要的jar包移动到$CATALINA_HOME/lib下
[root@localhost ~]# ls jars/
javolution-5.5.1.jar memcached-session-manager-tc7-1.6.5.jar spymemcached-2.11.1.jar
memcached-session-manager-1.6.5.jar msm-javolution-serializer-1.6.5.jar couchbase-client-1.2.3.jar(出错后补加的)
[root@localhost lib]# pwd
/etc/tomcat/lib
[root@localhost lib]# mv /root/jars/* ./
3.配置tomcat
在两个tomcat上的某个Host上定义一个Context:
tomcatA完整配置:
[root@localhost conf]# cat server.xml
-
<?xml version='1.0' encoding='utf-8'?>
-
<Server port="8005" shutdown="SHUTDOWN">
-
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
-
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
-
<Listener className="org.apache.catalina.core.JasperListener" />
-
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
-
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
-
-
<GlobalNamingResources>
-
<Resource name="UserDatabase" auth="Container"
-
type="org.apache.catalina.UserDatabase"
-
description="User database that can be updated and saved"
-
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
-
pathname="conf/tomcat-users.xml" />
-
</GlobalNamingResources>
-
-
<Service name="Catalina">
-
-
<Connector port="80" address="192.168.85.129" maxThreads="1024"
-
protocol="org.apache.coyote.http11.Http11AprProtocol"
-
connectionTimeout="60000"
-
redirectPort="443" />
-
-
<Connector port="8009" protocol="AJP/1.3" redirectPort="443" />
-
-
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">
-
<Realm className="org.apache.catalina.realm.LockOutRealm">
-
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
-
resourceName="UserDatabase"/>
-
</Realm>
-
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
-
<Context path="/test" docBase="/etc/tomcat/webapps/test" reloadable="true" >
-
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
-
memcachedNodes="memcached1:192.168.85.129:11211,memcached2:192.168.85.130:11211"
-
failoverNodes="memcached1"
-
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
-
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory" />
-
</Context>
-
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
-
prefix="localhost_access_log." suffix=".txt"
-
pattern="%h %l %u %t "%r" %s %b" />
-
</Host>
-
</Engine>
-
</Service>
-
</Server>
tomcatB完整配置:
[root@localhost conf]# cat server.xml
-
<?xml version='1.0' encoding='utf-8'?>
-
<Server port="8005" shutdown="SHUTDOWN">
-
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
-
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
-
<Listener className="org.apache.catalina.core.JasperListener" />
-
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
-
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
-
-
<GlobalNamingResources>
-
<Resource name="UserDatabase" auth="Container"
-
type="org.apache.catalina.UserDatabase"
-
description="User database that can be updated and saved"
-
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
-
pathname="conf/tomcat-users.xml" />
-
</GlobalNamingResources>
-
<Service name="Catalina">
-
<Connector port="80" address="192.168.85.130" protocol="HTTP/1.1"
-
connectionTimeout="20000"
-
redirectPort="8443" />
-
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatB">
-
<Realm className="org.apache.catalina.realm.LockOutRealm">
-
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
-
resourceName="UserDatabase"/>
-
</Realm>
-
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
-
<Context path="/test" docBase="/etc/tomcat/webapps/test" reloadable="true" >
-
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
-
memcachedNodes="memcached1:192.168.85.129:11211,memcached2:192.168.85.130:11211"
-
failoverNodes="memcached1"
-
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
-
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory" />
-
</Context>
-
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
-
prefix="localhost_access_log." suffix=".txt"
-
pattern="%h %l %u %t "%r" %s %b" />
-
</Host>
-
</Engine>
-
</Service>
-
</Server>
最后不要忘记创建Context的docBase并为其提供测试页面;
测试页面为:
[root@localhost test]# cat index.jsp
-
<%@ page language="java" %>
-
<html>
-
<head><title>TomcatB</title></head>
-
<body>
-
<h1><font color="blue">TomcatB</font></h1>
-
<table align="centre" border="1">
-
<tr>
-
<td>Session ID</td>
-
<% session.setAttribute("192.169.85.130","192.168.85.130"); %>
-
<td><%= session.getId() %></td>
-
</tr>
-
<tr>
-
<td>Created on</td>
-
<td><%= session.getCreationTime() %></td>
-
</tr>
-
</table>
-
</body>
-
</html>
附Apache配置文件:
[root@localhost extra]# cat proxy_mod.conf
-
ProxyRequests off
-
ProxyPreserveHost on
-
-
<Proxy balancer://cluster>
-
BalancerMember http://192.168.85.129 loadfactor=1 route=tomcatA
-
BalancerMember http://192.168.85.130 loadfactor=1 route=tomcatB
-
</Proxy>
-
-
<Location /status>
-
SetHandler balancer-manager
-
</Location>
-
-
ProxyPass /status !
-
ProxyPass / balancer://cluster/
-
ProxyPassReverse / balancer://cluster/
4.启动服务
[root@localhost conf]# service memcached start
Starting memcached: [ OK ]
[root@localhost conf]# catalina.sh start
此处我出现了一个错误:
java.lang.NoClassDefFoundError: com/couchbase/client/CouchbaseClient
原因:msm1.6.5依赖了Couchbase,需要添加couchbase-client的jar包,否则启动会报java.lang.NoClassDefFoundError:com/couchbase/client/CouchbaseClient错误;
解决办法:下载名为couchbase-client的jar包并放到$CATALINA_HOME/lib下即可;
5.测试
5.1浏览器地址栏输入显示
再次打开一个标签并输入地址时显示
5.2 停止memcached2服务,模拟故障情景
[root@localhost test]# service memcached stop
Stopping memcached: [ OK ]
测试:
这就实现了基于memcached的session共享集群,同时保证了session的主备同步的目的;
参考资料:
http://chenzhou123520.iteye.com/blog/1650212
MSM项目帮助文档:
jar包下载地址:
(不全)
(页面内能直接下载)
(自己搜索下载,很全)
couchbase-client-1.2.3另一个下载地址: