Windows下Apache+Tomcat实现应用集群
1 环境依赖:windows、jdk1.6、Apache2.2、tomcat6.0
2 Jdk1.6安装
2.1 略
3 安装Apache(2.2.27)
3.1 下载:从Apache官网http://httpd.apache.org/download.cgi下载httpd-2.2.25-win32-x86-openssl-0.9.8y.msi;
3.2 安装:双击上一步下载的安装程序,持续下一步直到完成;安装向导成功完成,左面右下角托盘中会出现Apache图标。
3.3 测试:打开浏览器,在其地址栏中输入http://localhost或者http://127.0.0.1,打开后可以看到“It works”字样,表示安装成功。
4 配置Apache
Apache2.2集成了mod_jk功能,相对于1.3版本,不再需要对worker.perproties进行进行配置,使其配置过程大幅度简化。
4.1 配置启动自动加载代理(proxy)模块(httpd.conf)
用文本编辑器打开${APACHE_HOME}/conf/http.conf文件,去掉一下文本前的注释符(#)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
4.2 配置首页
在上一步的基础上继续向下找到“DirectoryIndex index.html”字样,在其后追加index.jsp
4.3 开启虚拟节点
在上一步的基础上继续向下找到“Include conf/extra/httpd-vhosts.conf”字样,去掉前面的注释符
4.4 配置虚拟节点
用文本编辑器打开${APACHE_HOME}/conf/extra/httpd-vhosts.conf文件,在最后面追加如下内容
<VirtualHost *:80>
ServerAdmin username@domain.com # 管理员邮箱
ServerName www.domain.com # 默认域名,没有可以用IP代替
ServerAlias localhost # 别名,多个空格隔开
ProxyPass / balancer://cluster/ stickysession=jsessionid nofailover=On
ProxyPassReverse / balancer://cluster/
ErrorLog "logs/cluster_test-error.log"
CustomLog "logs/cluster_test-access.log" common
</VirtualHost>
上面的balancer://是告诉Apache需要进行负载均衡代理,后面的cluster是集群名,名字可自行定义,再后面*Log为日志引擎,负责日志记录。
4.5 配置代理
回到${APACHE_HOME}/conf/http.conf文件上,在其末尾追加如下格式内容
ProxyRequests Off # 使用反向代理
<proxy balancer://cluster>
BalancerMember ajp://127.0.0.1:18009 loadfactor=1 route=jvm1
BalancerMember ajp://127.0.0.1:28009 loadfactor=1 route=jvm2
</proxy>
上面的cluster需要与4.4中的集群名保持一致,Apache通过ajp协议与tomcat进行通信,ip地址与端口号确定了tomcat,loadfactor为负载因子,Apache按因子比例向tomcat转发请求,route为tomcat配置中的jvmRoute,见章节。
4.6 测试
重启Apache服务,此时访问http://localhost,将出现503错误,表示正常,因为此时tomcat尚未配置和启动。
5 安装Tomcat
5.1 下载
略
5.2 安装
略
6 配置Tomcat
因为是做tomcat集群,本篇以两个tomcat为例介绍,其分别命名为tomcat1、tomcat2。
6.1 配置Server port
用文本编辑器打开${TOMCAT_HOME_1}/conf/server.xml,
找到:<Server port="8005" shutdown="SHUTDOWN">
修改为:<Server port="18005" shutdown="SHUTDOWN">
6.2 配置Connector port
在上一步基础上,继续向下查找、
找到:<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
修改为:<Connector port="18080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="18443" URIEncoding="UTF-8"/>
继续向下搜索
找到:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
修改为:<Connector port="18009" protocol="AJP/1.3" redirectPort="18443" />
注:这里的port即为Apache通过apj协议与tomcat通信的端口,以实现负载均衡,故此处的端口18009应与4.5章节中端口号对应。
6.3 配置Engine
首先关闭<Engine name="Catalina" defaultHost="localhost">
然后开启<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
注:这里的jvmRoute的值jvm1应与4.5章节中的route相对应。
6.4 配置Cluster
在当前文件中继续向下查找,找到<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>,默认Cluster配置未被开启,这里我们取消注释,使其开启,主要作用是使各tomcat间共享session,据介绍在压力较大的情况下出现了session丢失情况,此段<Cluster />是一下代码的简写,其完整代码如下:
# 同步异步模式由channelSendOptions参数控制,默认值是8,为异步模式,4是同步模式。在异步模式下,可以通过加上拷贝确认(Acknowledge)来提高可靠性,此时channelSendOptions设为10。
<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="15900" 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> # filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/> <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>
上面代码中的<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>及<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>配置是在使用mod_jk并且没有使用sticky sessions或者sticky sessions无法正常工作时的解决方案,我们没有使用mod_jk,也就出现了压力较大session复制失败的情况,因此我们需要将上面的配置去掉这两行,然后替换<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
6.5 配置其他用于集群的tomcat,重复6.1~6.4的操作配置其他tomcat,主要是更改端口号(文中带有绿色标识的地方)
7 测试负载均衡
7.1 测试项目准备
新建一个web项目,取名为cluster_demo;
在项目中新建一个index.jsp页面,在页面body中加入如下内容:
<% String sessionid = session.getId(); System.out.println("当前sessionid = " + sessionid); %>
7.2 部署与启动
将上一步建立的测试项目部署到用于集群的tomcat中。
方式一:将项目放置到${TOMCAT_HOME_*}/webapps下;
方式二:在用于集群的tomcat的${TOMCAT_HOME_*}/conf/server.xml中的Host节点下添加
<Context path="/cluster_demo" docBase="D:/apache_tomcat/projects/cluster_demo" reloadable="true" crossContext="false" privileged="true"></Context>
然后分别启动集群中的tomcat,再启动Apache服务
7.3 并发访问
利用Apache中所带的ab来进行并发访问的模拟测试。
打开命令行窗口,切换至${APACHE_HOME}/bin下
cd ${APACHE_HOME}/bin
ab –n 20 –c 10 http://localhost/cluster_demo/index.jsp
可看到各tomcat控制台中的输出信息,是否分别平均接收了20个请求。
运行结果分别如下图所示,可见两个tomcat平均分担了20个请求:
8 测试session共享
8.1 共享配置
在测试项目的web.xml中,添加<distributable/>元素,这样可以通知tomcat服务器,当前应用需要在急群众的所有节点间实现session共享。
重要:所有session中的对象应是可序列化的,实现java.io.Serializable接口。
8.2 测试准备
在7.1章节基础上,修改index.jsp的内容为
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>cluster test - share session</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> </head> <body> <% String sessionid = session.getId(); System.out.println("当前sessionid = " + sessionid); // 如果有新的 Session 属性设置 String dataName = request.getParameter("dataName"); if (dataName != null && dataName.length() > 0) { String dataValue = request.getParameter("dataValue"); session.setAttribute(dataName, dataValue); } out.println("<b>Session 列表</b><br>"); System.out.println("============================"); 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" id="form_add" method="post"> Key:<input id="dataName" name="dataName" type="text"/> Value:<input id="dataValue" name="dataValue" type="text"/> <input id="subBtn" name="subBtn" type="submit" value="提交" /> </form> </body> </html>
8.3 验证测试
重新部署启动后,访问http://localhost/cluster_demo/index.jsp ,在页面上向session中添加一些信息,可看到如下效果,说明session共享咯,不解释。
至此,大功告成!