目录
1、环境概述
2、时间同步
3、实现过程
4、测试
5、讨论及总结
1、环境概述
测试环境拓扑如下:
clients
|
httpd
/ \
tomcat1 tomcat2
tomcat、httpd的安装已不再重复,但版本在这里说明:
httpd服务器(以负载均衡方式工作)
[[email protected] conf.d]# cat /etc/issue CentOS release 6.4 (Final) Kernel \r on an \m [[email protected] conf.d]# uname -r 2.6.32-358.el6.x86_64 [[email protected] conf.d]# ifconfig | grep Bcast: inet addr:192.168.0.200 Bcast:192.168.0.255 Mask:255.255.255.0 [[email protected] conf.d]# rpm -q httpd httpd-2.2.15-39.el6.centos.x86_64
后端tomcat服务器环境,操作系统版本与httpd服务器相同
[[email protected] ~]# catalina.sh version Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/java/latest Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Server version: Apache Tomcat/8.0.21 Server built: Mar 23 2015 14:11:21 UTC Server number: 8.0.21.0 OS Name: Linux OS Version: 2.6.32-358.el6.x86_64 Architecture: amd64 JVM Version: 1.8.0_45-b14 JVM Vendor: Oracle Corporation
2、时间同步
请参照此博文的相关部份配置http://zhaochj.blog.51cto.com/368705/1635982
3、实现过程
在之前的博文中已实现了apache以mod_jk和mod_proxy两种类型实现对后端tomcat进行负载均衡的部署,但都有一个缺陷,在不启用sticky session时,客户端访问前端apache后被调度到后端的tomcat节点,当访问节点发生改变时此负载均衡系统不能保证用户session信息不变;如果启用sticky session,在一定程度上解决了用户session信息的丢失问题,但是当用户所访问的节点宕机时,用户的session信息依然会丢失,那是否有方法解决这个问题?
当然,常用有两种方案,方案一:采用节点间session复制技术,当用户被调度到一tomcat节点时,用户的session信息会被同步到其他节点,一般采用组播的方式传递session信息,只要在同一个组播里的成员都会有一份session复制器,这样不管是哪个tomcat节点宕机,其他节点上也有一份接近(如果session信息变化又没来得及同步就宕机,那其他节点的session就不完整)完整的session信息,对用户来说是透明的;方案二就是单独部署session服务器,利用google的MSM(Memcached Session Manager)项目来实现,这个此博文不讨论,将在后边博文中来呈现。
前提:此次环境是在上次博文“apache以mod_proxy实现负载均衡集群”的基础上来实现集群的session复制机制。
因tomcat的版本不同,在实现集群session复制时有些细微的区别,所以根据官方文档来配置,我的环境是tomcat是8.0.21的版本,官方文档这里http://tomcat.apache.org/tomcat-8.0-doc/cluster-howto.html#Bind_session_after_crash_to_failover_node
配置tomcat,实现集群的session复制:
[[email protected] ~]# vim /usr/local/tomcat/conf/server.xml #以下代码加入到Engine容器中 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="192.168.0.201" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
注:以上内容定义在Engine容器中,则表示对所有主机均启动用集群功能。如果定义在某Host容器中,则表示仅对此主机启用集群功能。此外,需要注意的是,Receiver中的address="auto"一项的值最好改为当前主机集群服务所对应的网络接口的IP地址。
接下来更改web应用程序根目录下“WEB-INF”目录下的web.xml文件,必须添加<distributable/>这个元素,如果web应用程序没有这个目录及文件,则可复制默认站点的web.xml文件。
[[email protected] ~]# vim /tomcat/webapps/test/WEB-INF/web.xml <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> <distributable/> </web-app> #在web-app容器中加入<distributable/>元素即可。
到此,tomcat1配置完成,在tomcat2上也作上边的这些修改后重新启动tomcat服务,重启后注意观察服务器的监听端口,会有server.xml配置文件中配置的端口出现,如下:
[[email protected] ~]# netstat -tnlup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1100/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1184/master tcp 0 0 :::8080 :::* LISTEN 3422/java tcp 0 0 :::22 :::* LISTEN 1100/sshd tcp 0 0 ::1:25 :::* LISTEN 1184/master tcp 0 0 ::ffff:192.168.0.201:4000 :::* LISTEN 3422/java tcp 0 0 ::ffff:127.0.0.1:8005 :::* LISTEN 3422/java tcp 0 0 :::8009 :::* LISTEN 3422/java udp 0 0 192.168.0.201:123 0.0.0.0:* 1108/ntpd udp 0 0 127.0.0.1:123 0.0.0.0:* 1108/ntpd udp 0 0 0.0.0.0:123 0.0.0.0:* 1108/ntpd udp 0 0 fe80::20c:29ff:fec6:f77a:123 :::* 1108/ntpd udp 0 0 ::1:123 :::* 1108/ntpd udp 0 0 :::123 :::* 1108/ntpd udp 0 0 :::45564 :::* 3422/java
4、测试
打开浏览器访问前端的httpd监听的地址,得到的结果如下图:
看两次访问到的页面,第一次访问到了tomcat1节点上的测试页面,第二访问到了tomcat2上的测试页面,但两次访问的session信息是保持不变的。测试说明两个节点间的session已完成了复制。
5、讨论及总结
官方建议此Clustering/Session Replication技术只能用在小规模的集群环境中,有网友做过测试,当后端的tomcat节点数大于5个时,整个集群的性能不会再上升。
这里还有一个问题值得讨论,在生产环境下实现了session在各节点间的复制,在httpd上的配置中是否要启用session粘性或绑定呢,即使不启用绑定session,mod_proxy或mod_jk会根据配置的调度算法来把客户端的请求分发到后端的tomcat节点上,如果启用session的绑定功能,那客户端在一段时间内会被分发到同一个tomcat节点上,如果是以mod_proxy方式实现负载集群时要记得启用故障转移选项(nofailover=Off),不然,客户端之前问题的tomcat节点发生故障,那客户端将无法实现故障转移,不过这好像是默认选项。
在集群session复制的负载均衡环境中是否启用session粘性功能我个人认为需要不断的监控调度节点、后端的tomcat各节点的负载情况来再做调整。