Tomcat集群配置
集群结构
负载均衡服务器
在一些大公司采用F5负载均衡交换机作为负载均衡服务器,然后将请求转发给tomcat,但是F5设备动辄几十万,所以一些小公司采用采用开源的apache或Nginx来实现负载均衡,本文采用Apache + mod_jk + tomcat来实现tomcat集群的负载均衡的
软件
Apache是apache的http服务器,用于消息转发
mod_jk也叫 JK,这是一款 Apache/IIS 用来连接后台Tomcat的连接器,支持集群和负载均衡。
环境
本教程为了方便教学,仅在一台windows系统下安装这个集群.详情是:安装一个apache的http程序,两个tomcat程序
安装步骤
1. 安装Apache服务器
版本:2.2.25
下载地址:
http://archive.apache.org/dist/httpd/binaries/win32/httpd-2.2.25-win32-x86-no_ssl.msi
需要注意的是:
当安装到出现上面的信息时,可随意添加合法的域名和邮箱地址
之后选择安装路径,这里是安装在C:\cluster\httpd目录下
Apache安装完成后在浏览器中输入http://localhost/ ,如果出现下图说明安装成功
2. 安装tomcat
版本:7.0.8
下载地址:http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.zip
将tomcat解压到C:\cluster\目录下,然后重命名为tomcat1,再复制粘贴一份重命名为tomcat2
效果如下图:
3.下载mod_jk
mod_jk版本: jk-1.2.31
4.配置mod_jk和apache
将下载后的mod_jk-1.2.31-httpd-2.2.3.so放到C:\cluster\httpd\modules目录下
然后在C:\cluster\httpd\conf目录下创建一个mod_jk.conf
在mod_jk.conf中添加如下内容:
#加载mod_jk Module
LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so
#指定workers.properties文件路径
JkWorkersFile conf/workers.properties
#指定那些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器名
JkMount /* controller
然后在C:\cluster\httpd\conf创建一个workers.properties的文件,添加如下内容
#server
worker.list = controller
#========tomcat1========
#ajp13端口号,在tomcat下server.xml配置,默认8009
worker.tomcat1.port=8009
#tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat1.host=localhost
#协议类型
worker.tomcat1.type=ajp13
#server的加权比重,值越高,分得的请求越多。lbfactor是负载平衡因数(Load Balance Factor)
worker.tomcat1.lbfactor=1
#========tomcat2========
worker.tomcat2.port=9009
worker.tomcat2.host= localhost
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor=1
#========controller,负载均衡控制器========
#负载均衡控制器类型,lbfactor是负载平衡因数(Load Balance Factor)
worker.controller.type=lb
#指定分担请求的tomcat列表
worker.controller.balanced_workers=tomcat1,tomcat2
#粘性session(默认是打开的) 当该属性值=true(或1)时,代表session是粘性的,即同一session在集群中的同一个节点上处理,session不跨越节点。在集群环境中,一般将该值设置为false
worker.controller.sticky_session=false
#设置用于负载均衡的server的session可否共享
worker.controller.sticky_session_force=1
最后在修改C:\cluster\httpd\conf\httpd.conf,在其最后添加如下内容:
Include conf/mod_jk.conf
到此负载均衡服务器配置完成!
4.配置tomcat
修改C:\cluster\tomcat1\conf\server.xml,在配置<Engine>中添加jvmRoute="tomcat1",名称与worker.controller.balanced_workers=tomcat1,tomcat2对应
然后再<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>
第一个tomcat配置完成
然后再修改第二个tomcat.
修改C:\cluster\tomcat2\conf\server.xml,在配置<Engine>中添加jvmRoute="tomcat2",名称与worker.controller.balanced_workers=tomcat1,tomcat2对应
然后再<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>
注意:因为在一台机器上部署两台tomcat,所以需要修改第二个tomcat的端口,不然会产生冲突
<Server port="9005" shutdown="SHUTDOWN"> 默认为:8005
然后修改http1.1的端口,默认是8080
<Connector port="9080" protocol="HTTP/1.1" connectionTimeout="20000"redirectPort="8443" />
最后修改AJP1.3端口,默认是8009
<Connector port="9009" protocol="AJP/1.3" redirectPort="8443" />
这个AJP1.3的端口必须与C:\cluster\httpd\conf\ workers.properties文件中的配置保持一下
如图:
测试
重启apache
启动tomcat1和tomcat2
在浏览器中访问http://localhost/会出现
然后再在各个tomcat的节点上部署测试项目:
测试项目非常简单,在index.jsp仅有如下内容
<body>
server info : ${pageContext.request.localAddr}:${pageContext.request.localPort} <br>
<br>
session ID : ${pageContext.session.id} <br>
<br>
session属性列表
<table border="1" width="450px">
<tr>
<th>key</th><th>value</th>
</tr>
<c:forEach items="${pageContext.session.attributeNames}" var="attr">
<tr>
<td align="center">${attr}</td><td align="center">${sessionScope[attr]}</td>
</tr>
</c:forEach>
</table>
<br>
添加:
<form action="${pageContext.request.contextPath}/servlet/TestServlet?method=add" method="post">
key:<input type="text" name="key">value:<input type="text" name="value"><input type="submit" value="添加">
</form>
移除:
<form action="${pageContext.request.contextPath}/servlet/TestServlet?method=del" method="post">
key:<input type="text" name="key"><input type="submit" value="移除">
</form>
</body>
还有一个servlet用于添加和移除session中的内容
package cn.itcast.cluster.test;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = -4508299817031218675L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String method = request.getParameter("method");
String key = request.getParameter("key");
if(!"".equals(key)){
if("add".equals(method)){
String value = request.getParameter("value");
request.getSession().setAttribute(key, value);
} else {
request.getSession().removeAttribute(key);
}
}
response.sendRedirect(request.getContextPath());
}
}
注意:在项目WEB-INF /web.xml中需要添加<distributable/>效果如下图
将项目打完war包后分别放入到各个tomcat的webapps但中
之后在浏览器中访问:http://localhost/test/ 结果为:
之后按F5刷新,结果为:
我们发现现在的session ID 是由“sessionid” + “.” + “jvmRoute的值”组成,每次刷新sessionid不变,而jvmRoute的值发生变化,这说明session已经同步且轮询访问所有的tomcat
在session中添加属性和值:
再在session中添加属性和值:
然后再移除222
结果:再session中添加和删除属性,所有节点的session都可以同步
节点插拔测试:
停掉tomcat1,刷新多次后发现就剩一个tomcat2后仍然可以继续运行
之后在session中添加一些属性和值,然后再开启tomcat1