Apache2+tomcat6集群+session同步
说明:借前人之鉴,写一篇关于
tomcat集群及session同步的问题,首先介绍tomcat集群及做集群的原因和必要性;session同步的作用;各软件的安装配置及测试。
原理:
Apache是
httpd服务器,负责接收http请求,如何将请求分发给后台tomcat,这就需要mod_jk了,mod_jk是apache用来连接tomcat的模块,它需要配置在apache中。下面描述的是他们各自的分工情况。
Apache要做的是:
apache默认处理接收到的所有http请求,但可通过配置将请求转发给某个模块处理,并且将模块处理结果返回,在这里我们将所有请求都转发给mod_jk这个模块去处理。
Mod_jk要做的是:
a. 登记所有的
tomcat服务器,并针对不同功能划分tomcat做不同的配置。
b. 将从
apache接收到的请求按策略分配给tomcat,分配策略如下:
i. 对于新的会话按配置比例分发给
tomcat
ii. 对于已有会话(
http中包含session信息)的请求会发送给创建该会话的tomcat
iii. 当创建会话的
tomcat无法响应时,发送给该tomcat指定的备份tomcat。如果没有指定,则视为新会话处理。
Tomcat要做的是:处理
mod_jk发送过来的请求并返回结果。如果某一tomcat无法响应应转由其他tomcat处理时,原有的session信息将会丢失。为解决此问题,于是就有了session同步的概念,即多个服务器之间共享session,当某一服务器不能提供服务时不会导致用户session丢失。Tomcat 的session共享是基于ip组播协议实现的。这里只需要知道session同步是可以通过配置实现的,并且是由tomcat实现的并非mod_jk。了解了原理之后,配置起来就水到渠成了。
.需求
用两台服务器搭建
apache+tomcat测试开发环境,tomcat具有负载均衡能力,并实现session同步。
.环境
OS:
CentOS 5.6
httpd-2.2.17.tar.gz
jdk-6u20-linux-i586-rpm.bin
apache-tomcat-6.0.33.tar.gz
jakarta-tomcat-connectors-1.2.15-src.tar.gz
tomcat-connectors-1.2.32-src.tar.gz
.规划安装
192.168.2.4---------apache+tomcat+jdk
192.168.2.5---------tomcat+jdk
.部署
Apache
安装:
#tar httpd-2.2.17.tar.gz
#cd httpd-2.2.17
#./configure –-prefix=/usr/local/apache2 –-enable-modules=so –-enable-so
#make && make install
/usr/local/apache2/bin/apachectl start
看到
apache就配置成功了。
JDK
的安装
#chmod +x jdk-6u20-linux-i586-rpm.bin
#./ jdk-6u20-linux-i586-rpm.bin
一路空格键,然后输入
yes,回车默认就安装到/usr/java/下了。
设置环境变量:
#vim /etc/profile添加如下内容:
#set java environment
export JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_BIN=/usr/java/jdk1.6.0_20/bin
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JAVA_BIN PATH CLASSPATH
运行,使环境生效
;
#source /etc/profile
[root@Client ~]# java -version
java version "1.4.2"
gij (GNU libgcj) version 4.1.2 20080704 (Red Hat 4.1.2-52)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
安装tomcat
#tar –zxvf apache-tomcat-6.0.33.tar.gz
#mv apache-tomcat-6.0.33 /usr/local/tomcat
启动一个
tomcat实例
#/usr/local/tomcat/bin/startup.sh
在浏览器中输入
http://192.168.2.4:8080看到猫头,就代表成功安装了!
在另一台服务器(
192.168.2.5)上也同样安装jdk+tomcat。启动即可
安装tomcat-connectors-1.2.32-src.tar.gz
JK安装(整合
apache tomcat)
#tar –zxvf tomcat-connectors-1.2.32-src.tar.gz
#cd tomcat-connectors-1.2.32-src/native
#./configure –with-apxs=/usr/local/apache2/bin/apxs –with-java-home= /usr/java/jdk1.6.0_20
#make && make install
在
/usr/local/apache2/modules目录下会产生mod_jk.so
Apache+tomcat
整合
修改
apache配置文件,添加如下内容:
JkWorkersFile /usr/local/tomcat/conf/jk/workers.properties
//JK的配置文件,负载的配置
JkShmFile logs/mod_jk.shm
JkLogFile /usr/local/tomcat/logs/mod_jk.log
//jk的日志文件
JkLogLevel info
//日志级别
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JkMount /*.jsp controller
//将所有
jsp的请求转发给controller(负载均衡控制器)
修改
apache的配置文件httpd.conf
i. 在
DirectoryIndex中添加index.jsp
ii. 修改
DocumentRoot目录与tomcat目录一致。为:/usr/local/tomcat/webapps
保存退出!重启
apache服务。
调度器JK的配置:
#vim /usr/local/tomcat/conf/jk/workers.properties
\\整合配置文件
workers.tomcat_home=/usr/local/tomcat
workers.java_home=/usr/java/jdk1.6.0_20
ps=/
worker.list=controller
#指定负载名,这个名字可自定义,但要与下面的
work.controller.type=lb对应
#---------tomcat1--------------- 第一台
tomcat的配置
worker.tomcat1.port=8009
worker.tomcat1.host=localhost
//此处可以写本机
IP(192.168.2.4)
worker.tomcat1.type=ajp13
//使用的协议
ajp13
worker.tomcat1.lbfactor=1
//权量,数值越大,分配的几率越小
#worker.tomcat1.redirect=tomcat2
//定义
tomcat1实例如果挂掉,由tomcat2实例接替tomcat1
#---------tomcat2---------------
worker.tomcat2.port=8009
worker.tomcat2.host=192.168.2.5
//另一台
tomcat的IP地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor=1
#woker.tomcat2.local_worker=0
#worker.tomcat2.activation=disabled
#以上注释掉的两行如果开启,则
tomcat2成为tomcat1的备用,在tomcat1不可用的情况下才会向tomcat2请求。
#--------controller------------- 负载均衡器
worker.controller.type=lb
worker.controller.balance_workers=tomcat1,tomcat2
#各
tomcat配置文件server.xml里的jvmRoute="tomcat1"等指定的名字,需要各自修改一下。
worker.controller.sticky_session=1
到此处,已可实现
tomcat的负载均衡!可以将tomcat的主页文件index.jsp稍作修改,然后在浏览器中输入http://192.168.2.4进行测试,可以很清晰的看到,每次刷新后的页面都不一样,1,2交替出现。
Tomcat
集群配置(session同步):
i. 修改
192.168.2.4中tomcat的配置文件server.xml
#vim /usr/local/tomcat/conf/server.xml
ii. 修改
192.168.2.5中tomcat的配置文件server.xml
注,内容信息是:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
<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"
mcastBindAddress="192.168.2.4"
mcastAddr="224.0.0.1"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
tcpListenAddress="192.168.2.4"
port="4001"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/> <!-- timeout="60000"-->
<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"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/> </Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
保存退出!
注意事项:mcastAddr="224.0.0.1"需要开启网卡组播功能
route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0(可以添加至开机启动)
Session复制配置
Tomcat集群中的
session管理,主要有两种方式:
1. 粘性
session
表示从同一窗口发来的请求都将有集群集群中同一
tomcat进行处理。配置方式是在上面worker.properties文件中代码worker.controller.sticky_session=1
粘性
session的好处是不会在不同的tomcat上来回跳动处理请求,但是坏处是如果该session的tomcat崩溃,那么之后的请求将由其他tomcat处理,原有session失效而重新建一个新的session,这样如果继续从session取值,会抛出nullpointer的访问异常。
2. session复制
session复制是指
tomcat彼此之间通过组播方式将session发送各个tomcat实例上,如果其中一个访问出错,则另外tomcat仍然具有有效的session内容,从而能正常接管其session。坏处是tomcat实例很多或者用户在session中有大量操作时,组播发送的信息量十分惊人。Session复制配置则是在发布的WEB应用程序中的web.xml中添加xml代码<distributable/>
3.查看
[root@Client apache_tomcat]# netstat -tnlp
tcp 0 0 192.168.2.4:4001
0.0.0.0:* LISTEN 1990/java
4.修改应用程序的
web.xml文件
Web.xml配置文件加上<distributable/>节点,此配置说明当前
web工程处于分布式部署环境,如果不进行这个配置,每次访问页面tomcat都会产生一个新的sessionid。
在
</web-app>之前加上<distributable/>用于session复制。
#vim /usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml
<description>
Welcome to Tomcat
</description>
<distributable/>
</web-app>
5.在
webapps目录下创建目录test、在test中创建print.jsp与test.jsp
#vim /usr/local/tomcat/webapps/test/print.jsp
<%
System.out.println(wjpinrain.blog.51cto.com);
%>
#vim /usr/local/tomcat/webapps/test/test.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
String dataName = request.getParameter("dataName");
session.setAttribute("myname","session?");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session P±
?b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form action="index.jsp" method="POST">
û³
?<input type=text size=20 name="dataName">
<br>
?:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
注:在两台服务器上均做此两个文件,修改
web.xml。
重启所有服务。
访问:
http://192.168.2.4/test/test.jsp
Server Info: 192.168.2.4 : 80
ID 58EDB92B320CFFD0DDE8EE948CB22DC8.tomcat1
此时我将tomcat1停止服务再刷新网页
Server Info: 192.168.2.4 : 80
ID 58EDB92B320CFFD0DDE8EE948CB22DC8.tomcat2
可以看出当其中一台tomcat停止运行后,刷新后session值不变,但提供该服务的服务器已更换为tomcat2.
到此session同步已完成!