`
zhyxfancy
  • 浏览: 53147 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多
基于mod_proxy+Apache 2.2.16+Tomcat 7的负载均衡与集群配置
Peter Wei


周日晚和GF的老乡们喝了五粮液,导致周一起不了床,只好请假在家睡觉。白天睡了半天,晚上自然睡不着觉。正好现在的项目中也用到了负载均衡和集群的东西,虽然有新手贴的危险,但还是手痒,决定写点东西,以备不时之需。也希望能对大家有所帮助。

第一章. 背景简介
对于大多数企业应用,都希望能做到7*24小时不间断运行。要保持如此高的可用性并非易事,比较常见的做法是将系统部署到多台机器上,每台机器都对外提供同样的功能,这就是集群。系统变为集群时,除了要求系统能够支持水平伸缩外,还要解决两个问题:
1, 如何均衡地访问到提供业务功能的机器。
2, 如何保证当机器出现问题时,用户能自动跳转到另外的机器,不影响使用。
常用的负载均衡技术有硬件和软件两种,本示例常用软件的技术实现。软件也有很多实现技术,如基于apache的mod_jk以及mod_proxy等。基于mod_jk的文章有不少,本文演示一下用mod_proxy的方式。
实现集群的应用最重要的是处理用户Session的问题,一般有三种策略:
1, Session复制
2, Session Sticky
3, 基于Cache的集中式Session
本文使用的是Tomcat 7.0.2应用服务器,用的方法是Session复制。

第二章. 配置环境
1, JDK1.6,请自行下载安装,搞Java的一般都装有的吧,哈哈。
2, Apache 2.2.16, (released 2010-07-25),现在为止应该是最新的稳定版本,下载地址: http://httpd.apache.org/download.cgi
3, Tomcat 7.0.2,目前也是最新的版本。Minimum Java Version1.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
• Uncomment the Cluster element in server.xml。把Cluster元素的注释去掉。参照四
• If you have defined custom cluster valves, make sure you have the ReplicationValve defined as well under the Cluster element in server.xml 。参照四
• If your Tomcat instances are running on the same machine, make sure the tcpListenPort attribute is unique for each instance, in most cases Tomcat is smart enough to resolve this on it's own by autodetecting available ports in the range 4000-4100。参照四< Receiver>中的注释
• Make sure your web.xml has the <distributable/> element or set at your <Context distributable="true" /> 参照四
• If you are using mod_jk, make sure that jvmRoute attribute is set at your Engine <Engine name="Catalina" jvmRoute="node01" > and that the jvmRoute attribute value matches your worker name in workers.properties .用mod_jk的情况,我们可以不管。
• Make sure that all nodes have the same time and sync with NTP service! 当使用多台机器时,要保证不同机器时间的同步。原因为tomcat session复制的一些机制。具体原因看文档。
• Make sure that your loadbalancer is configured for sticky session mode. 保证负载均衡软件设置为session sticky模式。
四、 详细配置:
1. 修改tomcat7_a/conf/server.xml, 我们采用的是默认的配置,在<Engine>节点下添加:

Java代码

   1. <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" 
   2.                  channelSendOptions="8"> 
   3.  
   4.           <Manager className="org.apache.catalina.ha.session.DeltaManager" 
   5.                    expireSessionsOnShutdown="false" 
   6.                    notifyListenersOnReplication="true"/> 
   7.  
   8.           <Channel className="org.apache.catalina.tribes.group.GroupChannel"> 
   9.             <Membership className="org.apache.catalina.tribes.membership.McastService" 
  10.                         address="228.0.0.4" 
  11.                         port="45564" 
  12.                         frequency="500" 
  13.                         dropTime="3000"/> 
  14.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
  15.                       address="auto" 
  16. <!—tcpListenPort如果是同一机器部署两个tomcat7应用,则修改tomcat7_b为4001,以免冲突. 不同机器下,不用更改此项。—> 
  17.                       port="4000" 
  18.                       autoBind="100" 
  19.                       selectorTimeout="5000" 
  20.                       maxThreads="6"/> 
  21.  
  22.             <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> 
  23.               <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> 
  24.             </Sender> 
  25.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> 
  26.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> 
  27.           </Channel> 
  28.  
  29.           <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" 
  30.                  filter=""/> 
  31.           <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> 
  32.  
  33.           <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" 
  34.                     tempDir="/tmp/war-temp/" 
  35.                     deployDir="/tmp/war-deploy/" 
  36.                     watchDir="/tmp/war-listen/" 
  37.                     watchEnabled="false"/> 
  38.  
  39.           <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> 
  40.           <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> 
  41.         </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"
<!—tcpListenPort如果是同一机器部署两个tomcat7应用,则修改tomcat7_b为4001,以免冲突. 不同机器下,不用更改此项。—>
                      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>


2. <Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 修改,仅为了调试方便。
3. tomcat7_a\webapps\cluster\WEB-INF\web.xml中加入<distributable/>
4. <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat7_a">,添加jvmRoute属性,此项为后面apache负载均衡用到。

五、 复制一份tomcat7_a应用,改名为tomcat7_b.只是为了图方便,实际应该复制的是前面的cluster工程。注意以下几点配置就ok.
1. 修改tomcat7_a/conf/server.xml 中的Server port属性<Server port="8006" shutdown="SHUTDOWN">,因为是同一台机器两个tomcat应用,所以改一下。
2. 修改<connector port="8082" protocol="HTTP/1.1" onnectionTimeout="20000" edirectPort="8443" />,同理,为了避免同一台机器端口号冲突。部置在不同的机器是不用管的。
3. 修改<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat7_b">,此项为后面apache负载均衡用到。
4. 修改<Receiver className="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
Java代码

   1. <%@ page contentType="text/html; charset=GBK" %> 
   2. <%@ page import="java.util.*" %> 
   3. <html><head><title>Cluster Test</title></head> 
   4. <body> 
   5. <% 
   6.   //HttpSession session = request.getSession(true); 
   7.   System.out.println(session.getId()); 
   8.   out.println("<br> SESSION ID:" + session.getId()+"<br>");   
   9.   // 如果有新的请求,则添加session属性 
  10.   String name = request.getParameter("name"); 
  11.   if (name != null && name.length() > 0) { 
  12.      String value = request.getParameter("value"); 
  13.      session.setAttribute(name, value); 
  14.   }   
  15.     out.print("<b>Session List:</b>");   
  16.     Enumeration<String> names = session.getAttributeNames(); 
  17.     while (names.hasMoreElements()) { 
  18.         String sname = names.nextElement();  
  19.         String value = session.getAttribute(sname).toString(); 
  20.         out.println( sname + " = " + value+"<br>"); 
  21.         System.out.println( sname + " = " + value); 
  22.    } 
  23. %> 
  24.   <form action="testCluster.jsp" method="post"> 
  25.     名称:<input type=text size=20 name="name"> 
  26.      <br> 
  27.     值:<input type=text size=20 name="value"> 
  28.      <br> 
  29.     <input type=submit value="提交"> 
  30.    </form> 
  31. </body> 
  32. </html> 

<%@ 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:b value可看到




5. 刷新tomcat7_a(8081)相关页面,可以看到从tomcat7_b提交的值session同步过来了,说明集群成功。








第六章. Session集群工作步骤
参照tomcat7 doc:
To make it easy to understand how clustering works, We are gonna take you through a series of scenarios. In the scenario we only plan to use two tomcat instances TomcatA and TomcatB. We will cover the following sequence of events:
1. TomcatA starts up
2. TomcatB starts up (Wait that TomcatA start is complete)
3. TomcatA receives a request, a session S1 is created.
4. TomcatA crashes
5. TomcatB receives a request for session S1
6. TomcatA starts up
7. TomcatA receives a request, invalidate is called on the session (S1)
8. TomcatB receives a request, for a new session (S2)
9. TomcatA The session S2 expires due to inactivity.

第七章. 负载均衡配置
Tomcat有两种负载均衡的方式:
1. 使用 JK1.2.x native connector
2. 使用Apache HTTP Server 2.x with mod_proxy
我们使用的是mod_proxy,在Apache Http Server2.2以上版本已经自动带有:
Mod_proxy supports either HTTP or AJP load balancing. 我们通过ajp方式。

详细查看:tomcat7\webapps\docs\balancer-howto.html
1. 首先,监听8000端口, 在Apache安装目录下找到conf/httpd.conf文件
稍前面加上
Java代码

   1. # 监听端口和监听地址 
   2. Listen 8000 

# 监听端口和监听地址
Listen 8000


2. conf/httpd.conf,去掉以下文本前的注释符(#)以便让Apache在启动时自动加载代理(proxy)模块。
Java代码

   1. LoadModule proxy_module modules/mod_proxy.so   
   2. LoadModule proxy_ajp_module modules/mod_proxy_ajp.so   
   3. LoadModule proxy_balancer_module modules/mod_proxy_balancer.so   
   4. LoadModule proxy_connect_module modules/mod_proxy_connect.so   
   5. LoadModule proxy_ftp_module modules/mod_proxy_ftp.so   
   6. LoadModule proxy_http_module modules/mod_proxy_http.so  

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文件最后加上:
Java代码

   1. #虚拟机配置,负载均衡配置 
   2. <VirtualHost *:8000> 
   3.     ServerAdmin weigbo@163.com 
   4.     ServerName localhost 
   5.     ServerAlias localhost 
   6.     #小心,有些地方要有空格,要不然会出错哈哈。 
   7.     ProxyPass / balancer://cluster/ stickysession=JSESSIONID|jsessionid nofailover=On 
   8.     ProxyPassReverse / balancer://cluster/ 
   9.     #ErrorLog "logs/error.log" 
  10.     #CustomLog "logs/access.log" common 
  11. </VirtualHost>  
  12.  
  13. #The ProxyRequests directive should usually be set off when using ProxyPass. 
  14. ProxyRequests Off 
  15. <proxy balancer://cluster> 
  16.     BalancerMember ajp://localhost:8009 loadfactor=1 route=tomcat7_a  smax=5 max=20 ttl=120 retry=300 timeout=15 
  17.     BalancerMember ajp://localhost:9009 loadfactor=1 route=tomcat7_b  smax=5 max=20 ttl=120 retry=300 timeout=15 
  18.     # status=+H为配置热备,当所有机器都over时,才会请求该机器 
  19.     #BalancerMember http://192.168.1.218:8009 status=+H 
  20.     ProxySet lbmethod=bytraffic 
  21. </proxy> 

#虚拟机配置,负载均衡配置
<VirtualHost *:8000>
ServerAdmin weigbo@163.com
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对应上。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Connector port="9009" protocol="AJP/1.3" redirectPort="8443" />

第八章. 负载均衡测试
Tomcat7_a的cluster工程的测试文件:testCluster.jsp加上html代码:
<b>负载均衡测试:此为:Tomcat7_a上的文件,<font color=red>aaaaaaaaaaaaaaaaaa</font><b>

Tomcat7_b的cluster工程的测试文件:testCluster.jsp加上html代码
<b>负载均衡测试:此为:Tomcat7_b上的文件,<font color=red>bbbbbbbbbbbbbbbbbb</font><b>

打开浏览器,进入地址:http://localhost:8000/cluster/testCluster.jsp
多刷新几次,会看到页面值会在aaaaa和bbbbb间切换,说明负载均衡配置成功。如图:

[点击查看原始大小图片]


[点击查看原始大小图片]



第九章. Mod_proxy负载均衡算法
目前mod_proxy有3种负载均衡算法:
1. Request Counting(我猜是Round-robin), lbmethod=byrequests
2. Weighted Traffic Counting(这个是按权重,此例也是用此算法), lbmethod=bytraffic
3. Pending Request Counting(从apche文档来看,应该是按负载量,也就是往负载少的派发新请求). lbmethod=bybusyness
它们通过lbmethod值设置。
第十章. 参考文档:
Tomcat 7 doc文档
http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html

第十一章. 补充内容:负载均衡管理器
负载均衡管理器可以动态更新负载均衡的应用,你可以用管理器更改负载因子或者特定的应用,还可以把应用设为off模式。
为了使用balancer management, mod_status和mod_proxy_balancer 必需要加载到apache.
设置:
#此项为mod_proxy_balancer管理器需要
LoadModule status_module modules/mod_status.so

在负载均衡项前加上:
#mod_balancer管理应用
<Location /balancer-manager> 
     SetHandler balancer-manager
     Order Allow,Deny
     Allow from all
</Location>

可以通过以下地址访问:http://localhost:8000/balancer-manager

[点击查看原始大小图片]


附件中是一些相关的配置文件,大家可以参考:
分享到:
评论

相关推荐

    天融信负载均衡配置手册

    天融信负载均衡配置手册 一、负载均衡的概念 在讨论天融信负载均衡系统之前,我们需要了解什么是负载均衡。负载均衡是指将incoming网络流量分布到多个服务器上,以提高服务器的可用性、可靠性和灵活性。负载均衡...

    深信服负载均衡AD5.3用户手册

    ### 深信服负载均衡AD5.3用户手册知识点概览 #### 一、负载均衡基础概念 **1.1 负载均衡简介** 负载均衡(Load Balancing, LB)是一种网络技术,用于在多台服务器之间分配流量,以优化资源利用、最大化吞吐量、...

    Nginx实现负载均衡 web均衡负载 webservice负载均衡 Nginx实现负载均衡配制全说明

    Nginx实现负载均衡 web均衡负载 webservice负载均衡 Nginx实现负载均衡配制全说明 为了多台后台的web、webservice服务能均衡负载,可以使用nginx进行处理 1)配置文件全配制ok 2)有两个完整的web服务做例子,可以...

    c#源码 Socket 负载均衡 实例

    在IT行业中,Socket编程是网络通信的基础,而负载均衡则是优化系统性能、提高服务可用性的重要技术。本实例聚焦于C#语言中的Socket编程与负载均衡的结合,为开发者提供了一个实用的参考模板。 首先,我们需要理解...

    负载均衡器技术Nginx和F5的优缺点对比

     目前有许多不同的负载均衡技术用以满足不同的应用需求,如软/硬件负载均衡、本地/全局负载均衡、更高网络层负载均衡,以及链路聚合技术。  我们使用的是软负载均衡器Nginx,而农行用的是F5硬负载均衡器,这里...

    导致内部负载均衡器间歇性丢包或负载不均衡的常见因素-Bing1

    在IT领域,尤其是在云服务和网络架构中,负载均衡器是一个关键组件,它负责分散流入的网络流量到多个后端服务器,以确保高可用性和性能。然而,有时可能会遇到内部负载均衡器出现间歇性丢包或负载不均衡的问题。以下...

    a10负载均衡器简明运维操作手册.doc

    A10 负载均衡器运维操作手册 A10 负载均衡器是一种高性能的服务器负载均衡器,旨在提供高可用性和高性能的网络服务。为了确保 A10 负载均衡器的顺利运营,需要了解其基本硬件信息、登录方式、系统配置和维护等方面...

    win7 双网络负载均衡

    在Windows 7操作系统中,实现双网络负载均衡是一项高级网络配置技术,旨在提高网络连接的稳定性和效率。负载均衡可以通过将网络流量分散到多个网络接口上来优化带宽使用,提高系统的可用性,防止单个网络接口过载,...

    SAP 应用服务负载均衡的实现

    ### SAP应用服务负载均衡的实现 #### 一、概述 SAP系统因其强大的业务处理能力,在企业级应用中被广泛采用。随着业务量的增长及并发用户的增加,如何合理分配资源,提升系统的可用性和响应速度成为了关键问题之一...

    opensips与两台freeswitch负载均衡

    在构建大型VoIP系统时,负载均衡是至关重要的,它能确保服务的高可用性和可扩展性。"opensips与两台freeswitch负载均衡"的主题聚焦于如何使用OpenSIPS作为负载均衡器来管理两台Freeswitch服务器,以实现Freeswitch的...

    IIS负载均衡扩展插件ARR(Application Request Router)

    **IIS负载均衡扩展插件ARR(Application Request Router)** IIS(Internet Information Services)是微软提供的一个用于构建和管理Web应用程序的服务器平台。在大型网站或企业应用中,单一服务器可能无法满足高并发...

    H3C 负载均衡设备典型配置案例集手册.pdf

    《H3C 负载均衡设备典型配置案例集手册》是一本专为网络规划人员、现场技术支持与维护人员以及网络管理员设计的手册,旨在提供H3C负载均衡产品的典型配置案例。手册涵盖了多种型号的H3C负载均衡设备,如L5030、L5060...

    5G核心网的负载均衡策略.docx

    "5G核心网的负载均衡策略" 在 5G 核心网中,负载均衡策略是一个关键因素,可以提高网络运营效率和服务质量。基于服务化架构和接口的网元是 5G 核心网和 4G 的主要区别之一。因此,在分析 5G 核心网的负载均衡策略时...

    1. Camstar负载均衡配置.docx

    在IT行业中,负载均衡是一种关键的技术,用于优化资源利用、提高服务可用性和响应时间,同时也能增强系统的容错能力。本文件"1. Camstar负载均衡配置.docx"显然是关于如何在Camstar系统中实现多服务器与同数据库的...

Global site tag (gtag.js) - Google Analytics