基于mod_proxy+Apache 2.2.16+Tomcat 7的负载均衡与集群配置
基于mod_proxy+Apache 2.2.16+Tomcat 7的负载均衡与集群配置
周日晚和GF的老乡们喝了五粮液,导致周一起不了床,只好请假在家睡觉。白天睡了半天,晚上自然睡不着觉。正好现在的项目中也用到了负载均衡和集群的东西,虽然有新手贴的危险,但还是手痒,决定写点东西,以备不时之需。也希望能对大家有所帮助。
第一章.背景简介
对于大多数企业应用,都希望能做到7*24小时不间断运行。要保持如此高的可用性并非易事,比较常见的做法是将系统部署到多台机器上,每台机器都对外提供同样的功能,这就是集群。系统变为集群时,除了要求系统能够支持水平伸缩外,还要解决两个问题:
1,如何均衡地访问到提供业务功能的机器。
2,如何保证当机器出现问题时,用户能自动跳转到另外的机器,不影响使用。
常用的负载均衡技术有硬件和软件两种,本示例常用软件的技术实现。软件也有很多实现技术,如基于apache的mod_jk以及mod_proxy等。基于mod_jk的文章有不少,本文演示一下用mod_proxy的方式。
实现集群的应用最重要的是处理用户Session的问题,一般有三种策略:
1,Session复制
2,SessionSticky
3,基于Cache的集中式Session
本文使用的是Tomcat7.0.2应用服务器,用的方法是Session复制。
第二章.配置环境
1,JDK1.6,请自行下载安装,搞Java的一般都装有的吧,哈哈。
2,Apache2.2.16,(released2010-07-25),现在为止应该是最新的稳定版本,下载地址:http://httpd.apache.org/download.cgi
3,Tomcat7.0.2,目前也是最新的版本。MinimumJavaVersion1.6.下载地址:http://tomcat.apache.org/download-70.cgi
4,安装过程略
第三章.部署图
第四章.Tomcat7集群配置
一、就地取材,复制tomcat7/webapps下的examples,重命名为cluster应用,以后就用cluster做测试。
二、详细配置参照tomcat7\webapps\docs\cluster-howto.html或者http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
三、为了在Tomcat7中实现session复制,以下必需完成:
•所有session属性必需实现java.io.Serializable
•UncommenttheClusterelementinserver.xml。把Cluster元素的注释去掉。参照四
•Ifyouhavedefinedcustomclustervalves,makesureyouhavetheReplicationValvedefinedaswellundertheClusterelementinserver.xml。参照四
•IfyourTomcatinstancesarerunningonthesamemachine,makesurethetcpListenPortattributeisuniqueforeachinstance,inmostcasesTomcatissmartenoughtoresolvethisonit'sownbyautodetectingavailableportsintherange4000-4100。参照四<Receiver>中的注释
•Makesureyourweb.xmlhasthe<distributable/>elementorsetatyour<Contextdistributable="true"/>参照四
•Ifyouareusingmod_jk,makesurethatjvmRouteattributeissetatyourEngine<Enginename="Catalina"jvmRoute="node01">andthatthejvmRouteattributevaluematchesyourworkernameinworkers.properties.用mod_jk的情况,我们可以不管。
•MakesurethatallnodeshavethesametimeandsyncwithNTPservice!当使用多台机器时,要保证不同机器时间的同步。原因为tomcatsession复制的一些机制。具体原因看文档。
•Makesurethatyourloadbalancerisconfiguredforstickysessionmode.保证负载均衡软件设置为sessionsticky模式。
四、详细配置:
1.修改tomcat7_a/conf/server.xml,我们采用的是默认的配置,在<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" <!—tcpListenPort如果是同一机器部署两个tomcat7应用,则修改tomcat7_b为4001,以免冲突. 不同机器下,不用更改此项。—> [color=red]port="4000"[/color] 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>
2.<Connectorport="8081"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"/>修改,仅为了调试方便。
3.tomcat7_a\webapps\cluster\WEB-INF\web.xml中加入<distributable/>
4.<Enginename="Catalina"defaultHost="localhost"jvmRoute="tomcat7_a">,添加jvmRoute属性,此项为后面apache负载均衡用到。
五、复制一份tomcat7_a应用,改名为tomcat7_b.只是为了图方便,实际应该复制的是前面的cluster工程。注意以下几点配置就ok.
1.修改tomcat7_a/conf/server.xml中的Serverport属性<Serverport="8006"shutdown="SHUTDOWN">,因为是同一台机器两个tomcat应用,所以改一下。
2.修改<connectorport="8082"protocol="HTTP/1.1"onnectionTimeout="20000"edirectPort="8443"/>,同理,为了避免同一台机器端口号冲突。部置在不同的机器是不用管的。
3.修改<Enginename="Catalina"defaultHost="localhost"jvmRoute="tomcat7_b">,此项为后面apache负载均衡用到。
4.修改<Receiverclassname="org.apache.catalina.tribes.transport.nio.NioReceiver"address="auto"port="4001"autoBind="100"selectorTimeout="5000"maxThreads="6"/>
5.tomcat7_b\ebapps\cluster\WEB-INF\web.xml中加入<distributable/>
到此集群配置完成.
第五章.集群测试
1.tomcat7_a和tomcat7_b的cluster工程中分别添加测试文件:testCluster.jsp
<%@ page contentType="text/html; charset=GBK" %> <%@ page import="java.util.*" %> <html><head><title>Cluster Test</title></head> <body> <% //HttpSession session = request.getSession(true); System.out.println(session.getId()); out.println("<br> SESSION ID:" + session.getId()+"<br>"); // 如果有新的请求,则添加session属性 String name = request.getParameter("name"); if (name != null && name.length() > 0) { String value = request.getParameter("value"); session.setAttribute(name, value); } out.print("<b>Session List:</b>"); Enumeration<String> names = session.getAttributeNames(); while (names.hasMoreElements()) { String sname = names.nextElement(); String value = session.getAttribute(sname).toString(); out.println( sname + " = " + value+"<br>"); System.out.println( sname + " = " + value); } %> <form action="testCluster.jsp" method="post"> 名称:<input type=text size=20 name="name"> <br> 值:<input type=text size=20 name="value"> <br> <input type=submit value="提交"> </form> </body> </html>
2.启动tomcat7_a,启动完毕后,启动tomcat7_b
3.进入http://localhost:8081/cluster/testCluster.jsp对应tomcat7_a(8081),登录几次,可看到
4.另外打开一个浏览器,进入http://localhost:8082/cluster/testCluster.jsp对应tomcat7_b(8082),登录name:tomcat_b,value:bvalue可看到
5.刷新tomcat7_a(8081)相关页面,可以看到从tomcat7_b提交的值session同步过来了,说明集群成功。
第六章.Session集群工作步骤
参照tomcat7doc:
Tomakeiteasytounderstandhowclusteringworks,Wearegonnatakeyouthroughaseriesofscenarios.InthescenarioweonlyplantousetwotomcatinstancesTomcatAandTomcatB.Wewillcoverthefollowingsequenceofevents:
1.TomcatAstartsup
2.TomcatBstartsup(WaitthatTomcatAstartiscomplete)
3.TomcatAreceivesarequest,asessionS1iscreated.
4.TomcatAcrashes
5.TomcatBreceivesarequestforsessionS1
6.TomcatAstartsup
7.TomcatAreceivesarequest,invalidateiscalledonthesession(S1)
8.TomcatBreceivesarequest,foranewsession(S2)
9.TomcatAThesessionS2expiresduetoinactivity.
第七章.负载均衡配置
Tomcat有两种负载均衡的方式:
1.使用JK1.2.xnativeconnector
2.使用ApacheHTTPServer2.xwithmod_proxy
我们使用的是mod_proxy,在ApacheHttpServer2.2以上版本已经自动带有:
Mod_proxysupportseitherHTTPorAJPloadbalancing.我们通过ajp方式。
详细查看:tomcat7\webapps\docs\balancer-howto.html
1.首先,监听8000端口,在Apache安装目录下找到conf/httpd.conf文件
稍前面加上
# 监听端口和监听地址 Listen 8000
2.conf/httpd.conf,去掉以下文本前的注释符(#)以便让Apache在启动时自动加载代理(proxy)模块。
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
3.conf/httpd.conf文件最后加上:
#虚拟机配置,负载均衡配置 <VirtualHost *:8000> ServerAdmin [email protected] ServerName localhost ServerAlias localhost #小心,有些地方要有空格,要不然会出错哈哈。 ProxyPass / balancer://cluster/ stickysession=JSESSIONID|jsessionid nofailover=On ProxyPassReverse / balancer://cluster/ #ErrorLog "logs/error.log" #CustomLog "logs/access.log" common </VirtualHost> #The ProxyRequests directive should usually be set off when using ProxyPass. ProxyRequests Off <proxy balancer://cluster> BalancerMember ajp://localhost:8009 loadfactor=1 route=tomcat7_a smax=5 max=20 ttl=120 retry=300 timeout=15 BalancerMember ajp://localhost:9009 loadfactor=1 route=tomcat7_b smax=5 max=20 ttl=120 retry=300 timeout=15 # status=+H为配置热备,当所有机器都over时,才会请求该机器 #BalancerMember http://192.168.1.218:8009 status=+H ProxySet lbmethod=bytraffic </proxy>4. Tomcat7配置(server.xml):
因为是同一机器,两个应用,所以配不同的端口,不同机器则不用配,要和前面的ajp对应上。
<Connectorport="8009"protocol="AJP/1.3"redirectPort="8443"/>
<Connectorport="9009"protocol="AJP/1.3"redirectPort="8443"/>
第八章.负载均衡测试
Tomcat7_a的cluster工程的测试文件:testCluster.jsp加上html代码:
<b>负载均衡测试:此为:Tomcat7_a上的文件,<fontcolor=red>aaaaaaaaaaaaaaaaaa</font><b>
Tomcat7_b的cluster工程的测试文件:testCluster.jsp加上html代码
<b>负载均衡测试:此为:Tomcat7_b上的文件,<fontcolor=red>bbbbbbbbbbbbbbbbbb</font><b>
打开浏览器,进入地址:http://localhost:8000/cluster/testCluster.jsp
多刷新几次,会看到页面值会在aaaaa和bbbbb间切换,说明负载均衡配置成功。如图:
第九章.Mod_proxy负载均衡算法
目前mod_proxy有3种负载均衡算法:
1.RequestCounting(我猜是Round-robin),lbmethod=byrequests
2.WeightedTrafficCounting(这个是按权重,此例也是用此算法),lbmethod=bytraffic
3.PendingRequestCounting(从apche文档来看,应该是按负载量,也就是往负载少的派发新请求).lbmethod=bybusyness
它们通过lbmethod值设置。
第十章.参考文档:
Tomcat7doc文档
http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
第十一章.补充内容:负载均衡管理器
负载均衡管理器可以动态更新负载均衡的应用,你可以用管理器更改负载因子或者特定的应用,还可以把应用设为off模式。
为了使用balancermanagement,mod_status和mod_proxy_balancer必需要加载到apache.
设置:
#此项为mod_proxy_balancer管理器需要
LoadModulestatus_modulemodules/mod_status.so
在负载均衡项前加上:
#mod_balancer管理应用
<Location/balancer-manager>
SetHandlerbalancer-manager
OrderAllow,Deny
Allowfromall
</Location>
可以通过以下地址访问:http://localhost:8000/balancer-manager
附件中是一些相关的配置文件,大家可以参考: