一、配置环境:
1、Centos 6.3 32位Linux系统;
2、Apache版本:httpd-2.2.9.tar.gz;
3、Tomcat版本:apache-tomcat-6.0.35.tar.gz;
4、apr、apr-util、pcre依赖包版本:直接利用httpd下自带的版本即可;
5、zlib、zlib-devel、autoconf、libtool依赖包版本:直接采用yum命令安装即可;
6、JK版本:tomcat-connectors-1.2.37-src.tar.gz;
二、安装过程:
1、安装Apache:
A、解压httpd-2.29.tar.gz并移动到/usr/local目录下:
[root@localhost soft]# tar -zxvf httpd-2.29.tar.gz
[root@localhost soft]# mv httpd-2.29 /usr/local/httpd-2.2.9
B、分别进入httpd-2.2.9/srclib目录下apr、apr-util、pace目录,先行安装apr、apr-util、pace等依赖包:
安装apr:
[root@localhost apr]# ./configure --prefix=/usr/local/apr
[root@localhost apr]# make
[root@localhost apr]# make install
注:不安装apr一般会出现如下错误:
checking for APR... no
configure: error: APR not found . Please read the documentation
安装apr-util:
[root@localhost apr-util]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
[root@localhost apr-util]# make
[root@localhost apr-util]# make install
注:不安装apr-util一般会出现如下错误:
checking for APR-util... no
configure: error: APR-util not found . Please read the documentation
安装pcre:
[root@localhost pcre]# ./configure --prefix=/usr/local/pcre
[root@localhost pcre]# make
[root@localhost pcre]# make install
注:--prefix=/usr/local/apr、--prefix=/usr/local/apr-util、--prefix=/usr/local/pcre分别指apr、apr-util、pace的安装目录。
安装Apache所需的zlib与zlib-devel依赖包:
[root@localhost soft]# yum install zlib
[root@localhost soft]# yum install zlib-devel
注:不安装zlib与zlib-devel一般会出现如下错误:
checking for zlib location... not found
checking whether to enable mod_deflate... configure: error: mod_deflate has been requested but can not be built due to prerequisite failures
进入httpd-2.29目录安装Apache:
[root@localhost httpd-2.29]# ./configure --prefix=/usr/local/apache --enable-modules=so --enable-mods-shared=all --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util/bin
[root@localhost httpd-2.29]# make
[root@localhost httpd-2.29]# make install
注:--prefix=/usr/local/apache指apache的安装目录,针对不同的系统版本或软件版本,可能会出现其他问题,请查阅其他相关资料。
C、进入/usr/local,并查看是否安装成功:
[root@localhost local]# ls -ls
显示结果如图:
从图中可以看到,apr、apr-util、apache已经安装完成。
D、验证Apache是否安装成功,可以执行如下命令:
启动apache命令:
[root@localhost local]# /usr/local/apache/bin/apachectl -k start
关闭防火墙:
[root@localhost local]# service iptables stop
在浏览器中输入:http://192.168.31.132/,如果显示“It works!”结果,就表示Aapche安装成功,否则安装失败。
关闭apache命令:
[root@localhost local]# /usr/local/apache/bin/apachectl -k stop
2、JK的配置:
A、解压tomcat-connectors-1.2.37-src.tar.gz并移动到/usr/local目录下:
[root@localhost soft]# tar -zxvf tomcat-connectors-1.2.37-src.tar.gz
[root@localhost soft]# mv tomcat-connectors-1.2.37-src /usr/local/jk
B、安装MOD_JK所需的autoconf与libtool依赖包:
[root@localhost soft]# yum install autoconf
[root@localhost soft]# yum install libtool
注:不安装autoconf与libtool一般会出现如下错误:
autoconf: command not found
libtoo: command not found
C、进入/usr/local/jk目录,进行安装MOD_Jk:
[root@localhost jk]# ./buildconf.sh
[root@localhost jk]# ./configure --with-apxs=/usr/local/apache/bin/apxs --with-java-home=$JAVA_HOME --with-java-platform=2 --enable-jni
[root@localhost jk]# make
[root@localhost jk]# make install
3、TOMCAT的配置:
A、解压apache-tomcat-6.0.35.tar.gz并复制到/usr/local目录下:
[root@localhost soft]# tar -zxvf apache-tomcat-6.0.35.tar.gz
[root@localhost soft]# cp -ri apache-tomcat-6.0.35 /usr/local/tomcat1
[root@localhost soft]# cp -ri apache-tomcat-6.0.35 /usr/local/tomcat2
B、配置Tomcat环境变量,在“Centos系统之(一)关于JDK、TOMCAT、ANT、SVN等配置文档”博客中已经进行了详细的介绍,不再赘述:
C、修改Tomcat服务器的网络端口:
分别进入tomcat1和tomcat2目录的conf目录server.xml,采用vi编辑器修改相关的网络端口:
[root@localhost conf]# vi server.xml
C1、 分别将<Server port="8005" shutdown="SHUTDOWN">修改成:
<Server port="10005" shutdown="SHUTDOWN">
<Server port="20005" shutdown="SHUTDOWN">
注:为了在配置过程中方便记忆和区分,tomcat1的端口采用1****或****1,tomcat2的端口采用2****或****2的方式配置。
C2、 分别将<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />修改成:
<Connector port="10009" protocol="AJP/1.3" redirectPort="10043" />
<Connector port="20009" protocol="AJP/1.3" redirectPort="20043" />
C3、 分别将<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />修改成:
<Connector port="10001" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="10043" />
<Connector port="20001" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="20043" />
D、设置Tomcat服务器的<Engine>标签jvmRoute选项:
在server.xml里带jvmRoute的<Engine>配置,可参考这段配置为<Engine/>加个jvmRoute就可以了,对于jvmRoute的取值必须与后面提到的mod_jk的workers.properties文件中结点名相一致!前面配置tomcat服务器的时候,我们采用的是tomcat1和tomcat2的方式,此处设定jvmRoute的值为这两个值之一。
分别将<Engine name="Standalone" defaultHost="localhost">修改成:
<Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat1">
<Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat2">
E、设置Tomcat服务器的<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="auto" 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.JvmRouteSessionIDBinderListener" />
- <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
- </Cluster>
<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="auto" 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.JvmRouteSessionIDBinderListener" />
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>
注:这是从Tomcat官方文档http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html中截取的默认配置。
注:如果两个tomcat是部署在同一台机器上的话要注意修改Receiver标签的端口号,4000不能重复。
F、测试Tomcat1和Tomcat2是否可以正常访问:
[root@localhost bin]# sh startup.sh
分别在浏览器中输入:http://192.168.31.132:10001或者http://192.168.31.132:20001,如果显示出Tomcat,则配置成功,否则配置失败。
4、Apache服务器与Tomcat集群配置:
A、进入Apache的安装目录配置文件httpd.conf:
[root@localhost conf]# vi httpd.conf
在文件的最后加入以下代码:
- # Load mod_jk module
- LoadModule jk_module modules/mod_jk.so
- # Specify jk log file.
- JkLogFile /var/log/mod_jk.log
- # Specify jk log level [debug/error/info]
- JkLogLevel info
- # Specify workers.properties, this file tell jk:
- # how many nodes and where they are.
- JkWorkersFile conf/workers.properties
- # Specify which requests should handled by which node.
- JkMount /* controller
# Load mod_jk module
LoadModule jk_module modules/mod_jk.so
# Specify jk log file.
JkLogFile /var/log/mod_jk.log
# Specify jk log level [debug/error/info]
JkLogLevel info
# Specify workers.properties, this file tell jk:
# how many nodes and where they are.
JkWorkersFile conf/workers.properties
# Specify which requests should handled by which node.
JkMount /* controller
注: 关于mod_jk配置项的详细内容,可参考:http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html。
B、从上述文件中的JkWorkersFile conf/workers.properties配置可以知道,我们需要在conf目录下新建workers.properties文件描述集群结点的情况,其内容如下:
- #所有节点列表,其中controller是一个逻辑结点,负责负载均衡控制,
- #如果JkMount中的URL指定给了controller就表示这个请求会被自动散列到某个物理节点上。
- #注意:真正负责处理请求的tomcat的名称(这里就是tomcat1,tomcat2)必须于它们在conf/server.xml
- #文件中配置的jvmRout的属性值是一致的!
- worker.list = controller,tomcat1,tomcat2
- #========tomcat1========
- worker.tomcat1.port=10009 #ajp13 端口号,在tomcat下server.xml配置,默认8009
- worker.tomcat1.host=192.168.31.132 #tomcat的主机地址,如不为本机,请填写ip地址
- worker.tomcat1.type=ajp13
- worker.tomcat1.lbfactor = 1 #server的加权比重,值越高,分得的请求越多
- #========tomcat2========
- worker.tomcat2.port=20009 #ajp13 端口号,在tomcat下server.xml配置,默认8009
- worker.tomcat2.host=192.168.31.132 #tomcat的主机地址,如不为本机,请填写ip地址
- worker.tomcat2.type=ajp13
- worker.tomcat2.lbfactor = 1 #server的加权比重,值越高,分得的请求越多
- #========controller,负载均衡控制器========
- worker.controller.type=lb
- worker.controller.balance_workers=tomcat1,tomcat2 #指定分担请求的tomcat,旧版本中的balanced_workers,已不再推荐使用!
- worker.controller.sticky_session=1 #sticky_session为1表示,
- #当某client的session创建之后,后续由该客户端发起的请求,即session的所有请求都始终由第一次处理该请求的结点负责处理(除非该结点挂掉)
#所有节点列表,其中controller是一个逻辑结点,负责负载均衡控制,
#如果JkMount中的URL指定给了controller就表示这个请求会被自动散列到某个物理节点上。
#注意:真正负责处理请求的tomcat的名称(这里就是tomcat1,tomcat2)必须于它们在conf/server.xml
#文件中配置的jvmRout的属性值是一致的!
worker.list = controller,tomcat1,tomcat2
#========tomcat1========
worker.tomcat1.port=10009 #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat1.host=192.168.31.132 #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor = 1 #server的加权比重,值越高,分得的请求越多
#========tomcat2========
worker.tomcat2.port=20009 #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat2.host=192.168.31.132 #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor = 1 #server的加权比重,值越高,分得的请求越多
#========controller,负载均衡控制器========
worker.controller.type=lb
worker.controller.balance_workers=tomcat1,tomcat2 #指定分担请求的tomcat,旧版本中的balanced_workers,已不再推荐使用!
worker.controller.sticky_session=1 #sticky_session为1表示,
#当某client的session创建之后,后续由该客户端发起的请求,即session的所有请求都始终由第一次处理该请求的结点负责处理(除非该结点挂掉)
所有配置均已完成,启动两个tomcat和apache后,部署相关的java工程到两个tomcat中,如果配置正确,通过apache访问日志会发现,请求被随机分配。
5、如果是发布应用,在发布的应用中web.xml文件中,加入<distributable/>元素。
三、负载均衡与集群服务器验证:
1、验证目标:
A、测试session信息是否丢失,即同一个请求在不同刷新过程中是否改变,如果改变则配置失败,反之配置成功;
B、测试session是否在集群中的各个节点中成功复制,复制成功则才能实现集群的目的:负载均衡;
2、在此引用一个网络上的测试session的例子,在Tomcat1与Tomcat2的webapps下建立test目录,并且建立测试文件hello.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");
- if (dataName != null && dataName.length() > 0) {
- String dataValue = request.getParameter("dataValue");
- session.setAttribute(dataName, dataValue);
- }
- out.print("<b>Session 列表</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="Hello.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>
<%@ 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");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session 列表</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="Hello.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>
3、在test目录下新建WEB-INF目录和web.xml,在<web-app>节点下加入<distributable />,通知Tomcat在当前应用集群中的所有节点间实现Session共享:
4、启动两个Tomcat节点和Apache服务,进行测试,在浏览器中输入:http://192.168.31.132/test/hello.jsp:
结果如下:
1、ID A13F7FD30C2ACA712BDF6EFAF9B7FD38.tomcat2
Session 列表1 = 1
2、ID A13F7FD30C2ACA712BDF6EFAF9B7FD38.tomcat1
Session 列表1 = 1
3、ID A13F7FD30C2ACA712BDF6EFAF9B7FD38.tomcat2
Session 列表1 = 1
2 = 5
4、ID A13F7FD30C2ACA712BDF6EFAF9B7FD38.tomcat1
Session 列表1 = 1
3 = 4
2 = 5
注: 1、通过这些数据可以知道,前面的sessionId是固定没变得,当我们不停的点击提交时,小数点后面的内容变了,实际上可以知道是哪个节点处理了当次请求,说明sessionId在各个节点的复制成功了,达到了我们预想的测试目的B;
2、通过每条数据下得Session 列表可知:当我们增加新的数据的时候,前面存入session里面的数据并没有丢失,说明我们预想测试目的A成功了;
3、其实我们从两个Tomcat的控制台也可以看得出来,sessionId在不同节点是相同的;
4、关闭掉任何一个节点,请求都可以执行,而且sessionId是不变的。
四、负载均衡与集群项目热部署:
对于Java应用程序来说,热部署就是在运行时更新Java类文件。在基于Java的应用服务器实现热部署的过程中,类装入器扮演着重要的角色。大多数基于Java的应用服务器,包括EJB服务器和Servlet容器,都支持热部署。类装入器不能重新装入一个已经装入的类,但只要使用一个新的类装入器实例,就可以将类再次装入一个正在运行的应用程序。
在/usr/local/tomcat1/conf目录下的server.xml文件中的<Host></Host>中加入如下配置:
<!-- host publish of project -->
<Context path="/mvc" docBase="mvc" debug="99" reloadable="true"/>
注:本人也是第一次采用热部署的配置来处理相关问题。根据从网上查询到的资料了解,关于项目的热部署一直都在争论之中,有的人说高效率,有的人说不安全,总之一句话,仁者见仁智者见智。根据网上的一些IT同仁总结的优点缺点,我个人没有什么经验,所以我个人建议,除非是项目不得已而采取,还是采用冷部署为好吧,即手动上传或者采用SHELL脚本的形式,就当为了项目安全多考虑一点而已吧。
http://blog.youkuaiyun.com/limingzhong198/article/details/19401443