本文转载自:
http://zyycaesar.iteye.com/blog/294089
http://zyycaesar.iteye.com/blog/295227
并根据自己的操作加上了图片等。在此非常感谢原作者提供了这么好的入门文章!
--------------以下为正文-------------------
一、软件准备
Apache 2.2.25: http://httpd.apache.org/download.cgi
下载msi安装程序,选择no ssl版本(httpd-2.2.25-win32-x86-no_ssl.msi)
Tomcat 6.0.39: http://tomcat.apache.org/download-60.cgi
下载 apache-tomcat-6.0.39-windows-x86.zip 文件
注意:由于Apache和Tomcat项目与集群相关的模块均处于持续发展和优化过程中,因此笔者不保证本文配置方法对所有Apache和Tomcat版本均适用。
二、软件安装
Windows下安装Apache(默认端口为80,可自行选择修改),并注册为Windows服务。服务启动后在浏览器中输入http://localhost测试,页面出现"It works!"表示Apache正常工作。
Linux下安装Apache Http Server ,可参考:
http://blog.csdn.net/wangjunjun2008/article/details/38314387
解压tomcat的zip文件分别到两个文件夹,命名为tomcat1和tomcat2。分别启动tomcat1和tomcat2,确保tomcat正常,然后关闭tomcat。
本文仅为讲解配置过程,Apache和tomcat均工作在同一台机器上;实际部署时没有任何限制,Apache和tomcat可部署在不同的服务器上。
三、Apache配置
Apache2.2集成了mod_jk功能,相对于1.3版本,不需要再进行繁琐的worker.properties配置,配置过程大幅简化。
(一)编辑conf/httpd.conf文件,去掉以下文本前的注释符,以便让Apache在启动时自动加载代理模块:
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
LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
(二)继续向下查找文档,找到<IfModule dir_module>节点(约243行),在DirectoryIndex index.html后加上index.jsp, 这一步只是为了配置完tomcat后能看到小猫首页,可以不做。
(三)继续向下查找文档,找到 #Include conf/extra/httpd-vhosts.conf(约473行),去掉前面的注释。
(四)编辑 ${Apache_Home}/conf/extra/httpd-vhosts.conf 文件,在最下面加上以下代码:
<VirtualHost *:80>
ServerAdmin test@163.com #管理员邮箱
ServerName 172.24.2.62 #域名(没有域名则用IP)
ServerAlias localhost
ProxyPass / balancer://modjk/ stickysession=jsessionid nofailover=On
ProxyPassReverse / balancer://modjk/
ErrorLog "logs/modjktest-error.log"
CustomLog "logs/modjktest-access.log" common
</VirtualHost>
[说明]
”balancer://” 是告诉Apache进行负载均衡的代理, ”modjk” 是集群名(可随意取);
日志引擎ErrorLog负责记录错误,日志文件名任意取;
日志引擎CustomLog负责记录所有的http访问以及返回状态,日志文件名任意取;
(五)修改 ${Apache_Home}/conf/httpd.conf 文件,在文档最下面追加以下代码:
ProxyRequests Off
<proxy balancer://modjk>
BalancerMember ajp://127.0.0.1:8090 loadfactor=1 route=jvm1
BalancerMember ajp://127.0.0.1:8091 loadfactor=1 route=jvm2
</proxy>
[说明]
ProxyRequests Off 是告诉Apache需要使用反向代理;(利用Apache进行负载均衡必须使用反向代理,关于更多负载均衡和反向代理详情可以参阅笔者另一篇博客http://zyycaesar.iteye.com/blog/293839);
<proxy balancer://modjk>配置tomcat集群的节点,其中"modjk"必须与上面的集群名保持一致;
Apache通过ajp协议与tomcat进行通信,IP地址和端口唯一确定了tomcat节点及其ajp端口;
loadfactor是负载因子,Apache会按负载因子的比例分发请求,取值范围是1~100,负载因子越大,对应的tomcat就会处理越多的请求;若两个tomcat都是1,Apache就按1:1的比例分发请求;若是2和1,则按2:1的比例分发请求;
route参数对应tomcat配置中的引擎路径(下面会说明)。
四、Tomcat配置
如果仅仅为了配置一个可用的集群,Tomcat的配置将会非常简单:
分别打开tomcat1和tomcat2的server.xml配置文件,修改如下标签的端口号(若tomcat1和tomcat2不在同一台服务器上运行,则无需修改端口):
tomcat1修改如下标签port属性值:
<Server port="8010" shutdown="SHUTDOWN">
<Connector port="8080" protocol="HTTP/1.1" ... redirectPort="8443" />
<Connector port="8090" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
tomcat2修改如下标签port属性值:
<Server port="8011" shutdown="SHUTDOWN">
<Connector port="8081" protocol="HTTP/1.1" ... redirectPort="8443" />
<Connector port="8091" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm2">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
[注意]
AJP协议端口对应${Apache_Home}/conf/httpd.conf中BalancerMember中配置的ajp连接端口!
Engine 标签增加jvmRoute属性,其值对应${Apache_Home}/conf/httpd.conf中BalancerMember中配置的route参数!
打开 <Cluster /> 标签的注释,该配置的作用是在集群中的所有tomcat节点间共享会话(Session),如果仅仅为了获得一个可用的tomcat集群,则无需打开<Cluster /> 标签。
server.xml修改完毕,下一步需要对具体的应用进行配置,用于测试。分别在tomcat1和tomcat2做如下操作:
在${Tomcat_Home}/webapps/下新建test目录,在test目录下新建test.jsp文件,文件内容为:
<%@ page contentType="text/html; charset=GBK" %> <%@ page import="java.util.*" %> <html> <head> </head> <body> <% out.println("Server IP = " + request.getLocalAddr() + "<br>"); out.println("Server Port = " + request.getLocalPort() + "<br>"); out.println("<br>"); out.println("SessionId = " + session.getId() + "<br>"); out.println("<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="test.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>
在test目录下新建WEB-INF目录,在WEB-INF目录下新建web.xml,web.xml文件内容为:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <description>test</description> </web-app>
[说明]
<distributable />标签的作用是:通知tomcat服务器,当前应用需要在集群中的所有节点间实现Session共享;(如果tomcat中的所有应用都需要Session共享,可以把${Tomcat_Home}/conf/context.xml中的<Context>改为<Context distributable="true">,这样就不需对该tomcat下的所有应用的web.xml再进行单独配置。
启动tomcat1,tomcat2;
访问http://localhost,可以看到小猫页面。
访问http://localhost/test/test.jsp,可以看到包括服务器地址、端口、SessionId等信息在内的页面,如下图:
[注意]
此处的SessionId与平常的SessionId相比多了”.jvm2”,这里的jvm2 为处理当前请求的tomcat服务器的jvmRoute值,通过该名称可知是集群中的哪个服务器处理了当前请求。
在文本框中输入名称和值,点击按钮,信息就保存到了Session中,并且显示到页面上;不断点击按钮,可以发现输入的信息并未丢失,而且SessionId小数点之前的部分保持不变,而小数点后面的字符不停的变化,表明是由不同的tomcat服务器处理了这些请求,这样就实现了负载均衡,并且集群中的不同节点间可以实现会话的共享。此时如果停止一个tomcat服务器(比如tomcat1),Apache将会自动把后续请求转发到集群中的其他服务器中,重启tomcat1后,Apache会自动侦测到tomcat1的状态为可用,然后会继续在tomcat1和tomcat2间进行负载均衡。
如果需要向集群中增加节点,首先需要对tomcat作类似配置,然后修改${Apache_Home}/conf/httpd.conf 文件,增加BalancerMember, 指向新增的tomcat即可。
--------------正文结束-------------------
按照作者的描述,一步一步配置,最终实现了负载均衡,但是Session共享却无法实现;其他读者也有遇到类似的问题,从评论中摘抄相关的部分如下:
2 楼 xiejin2008 2009-12-14 引用
我用的tomcat6版本,apache2.2 均衡负载可以实现,点击按钮,后面的jvm1,jvm2不停地的交换显示,但是前面的sessionID总是变化的,所以并没有成功设置成session共享,请求楼主,可能哪个地方存在问题呢?
3 楼 xiejin2008 2009-12-14 引用
楼主刚刚重新测试,下载tomcat5版本,发现tomcat5中是可以是实现session复制的.
tomcat1 和tomcat2是Apache Tomcat Version 6.0.20
在这样的集群条件下面,均衡负载时可以实现的,但是并没有实现session的共享.
tomcat3 和tomcat4是Apache Tomcat Version 5.5.28
在这样的集群条件下面,均衡负载时可以实现的,并且可以实现session的共享.
发现两个版本的tomcat中 conf/server.xml里面的文件内容不一样
主要是这段:
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver .....................
以上这段是tomcat5里面的;
以下这段是tomcat6里面的:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
仅仅就这一句话,没有那么多详细的配置内容.
我测试的结果是负载均衡可实现。session复制可实现。但现象和楼主描述的有点出入,
sessionid第一次进入页面后就不再变化,小数点前和小数点后都不会变化
我的是apache 2.2.16 tomcat 6.0.26按照Lz的配置完全通过,上面说没有配置通过的估计是有些地方配置错了所导致的,我之前也有session不能共享的情况,后来来回找了几遍终于通过了
9 楼 zenghong237 2011-01-11 引用
楼主啊。在一台机器上测试通过,可是当部署在两台机器上的时候session不会共享啊
为什么局域网内可以访问,放到服务器上,配置之后,本机没有问题,其他机器访问就无法访问了,为啥呢?
目前仍然未解决该问题.......
PS:有关 Apache和Tomcat集群中,cluster实现原理,可以参考原作者的另一篇博文(Tomcat集群Cluster实现原理剖析)