`

一个完整的负载均衡的例子 .

 
阅读更多
原理:tomcat 做个WEB服务器有它的局限性,处理能力低,效率低。承受并发小(1000左右)。但目前有不少网站或者页面是JSP的。并采用了tomcat做为WEB,因此只能在此基础上调优。
目前采取的办法是Apache + Mod_JK + tomcat 来解决一部分请求,用户访问的是apache,但有jsp页面的时候才会去请求tomcat。如果量一大,那么tomcat无法承受,那么只能做tomat集群,Apache + Mod_JK 就是负载均衡器了。
Mod_JK2负载均衡 可以把不同的jsp请求转发到不同的tomcat服务器,还可以侦测服务器存活。如果有条件可以给Mod_JK2做一个HA因为做完集群后压力就在JK上了。
      
简单拓仆图:
鎷撲粏鍥�

 

 

 

准备工作

Tomcat7 http://tomcat.apache.org/download-70.cgi

apache httpd server 2.2: http://httpd.apache.org/download.cgi

apache tomcat connector: http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.31/

 

相关文档:

web server how to:

http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html

 

安装路径:

httpd:             D:\Server\Apache httpd2_2

tomcat D:\Server\tomcat7-1 tomcat7-2 tomcat7-3

JK  D:\Server\Apache httpd2_2\modules\mod_jk-1.2.31-httpd-2.2.3.so

 

step 1: 添加并配置JK

D:\Server\Apache httpd2_2\conf\httpd.conf文件最后加上,意思是把这个配置加载进来

 

Xml代码  收藏代码
  1. include conf\mod_jk.conf  

 

新建mod_jk.conf文件,内容如下:

 

Java代码  收藏代码
  1. LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so  
  2. JkWorkersFile conf/workers.properties  
  3. #指定那些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器名  
  4. JkMount /*.jsp controller  
 

 

Step 2: 配置worker

 

新建并编辑workers.properties文件,内容如下

 

Java代码  收藏代码
  1. #server  
  2. worker.list = controller  
  3. #========tomcat1========  
  4. worker.tomcat1.port=11009  
  5. worker.tomcat1.host=localhost  
  6. worker.tomcat1.type=ajp13  
  7. worker.tomcat1.lbfactor = 1  
  8. #========tomcat2========  
  9. worker.tomcat2.port=12009  
  10. worker.tomcat2.host=localhost  
  11. worker.tomcat2.type=ajp13  
  12. worker.tomcat2.lbfactor = 1  
  13. #========tomcat3========  
  14. worker.tomcat3.port=13009  
  15. worker.tomcat3.host=192.168.0.80 //在我的虚拟机中的,可以算远程的吧  
  16. worker.tomcat3.type=ajp13  
  17. worker.tomcat3.lbfactor = 1  
  18.    
  19. #========controller,负载均衡控制器========  
  20. worker.controller.type=lb  
  21. worker.controller.balanced_workers=tomcat1,tomcat2,tomcat3  
  22. worker.controller.sticky_session=false  
  23. worker.controller.sticky_session_force=1  
  24. #worker.controller.sticky_session=1  

 

如果三个tomcat不在同一台机器上,那么下面改端口的事情就可以省很多力气,不过因为要单机做负载均衡,所以要更改三个tomcat的8005,8080的端口,确保都不一样,不然tomcat是没办法同时启动三个的。

 

测试的时候我三个tomcat都放在本地,因为要同时启动三个tomcat,所以需要更改三个tomcat中的Connector端口号,将三个tomcat的的protocol="HTTP/1.1" 的connector的port改为10080,11080,12080。(原来是8080)

 

同时讲原来8005的端口分别改成10005,11005,12005(这个是关闭tomcat的端口号)

 

tomcat7-1

 

 

Xml代码  收藏代码
  1. <Connector port="10080" protocol="HTTP/1.1" connectionTimeout="20000"   
  2.            redirectPort="8443" />  
 

 

tomcat7-2

 

Java代码  收藏代码
  1. <Connector port="11080" protocol="HTTP/1.1" connectionTimeout="20000"   
  2.            redirectPort="8443" />  
 

 

tomcat7-3

 

Java代码  收藏代码
  1. <Connector port="12080" protocol="HTTP/1.1" connectionTimeout="20000"   
  2.            redirectPort="8443" />  
 

除了更改server.xml中 原来的8080的端口(protocol="HTTP/1.1" 的端口号)

还需要配置AJP13的端口号,同时打开默认注释掉的<Cluster>标签,对应的<Engine>的jvmRoute改成workers.property里面对应的名字,配置如下(删除了注释)

tomcat7-1

 

Xml代码  收藏代码
  1. <Connector port="11009" protocol="AJP/1.3" redirectPort="8443" />  
  2.     <Engine name="Catalina" defaultHost="localhost"          
  3.            jvmRoute="tomcat1">    
  4.     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>  
 

tomcat7-2

 

Java代码  收藏代码
  1. <Connector port="12009" protocol="AJP/1.3" redirectPort="8443" />  
  2.     <Engine name="Catalina" defaultHost="localhost"          
  3.            jvmRoute="tomcat2">    
  4.     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>  
 

 

tomcat7-3

 

Java代码  收藏代码
  1. <Connector port="13009" protocol="AJP/1.3" redirectPort="8443" />  
  2.     <Engine name="Catalina" defaultHost="localhost"          
  3.            jvmRoute="tomcat3">    
  4.     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>  
 

 

OK,这时候可以成功启动三个tomcat7了,当tomcat7-2启动后,tomcat7-1会打印出replication的信息

类似于

 

Xml代码  收藏代码
  1. 2011-9-20 14:12:18 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded  
  2. 信息: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{172, 16, 10, 96}:4001,{172, 16, 10, 96},4001, alive=1000securePort=-1, UDP Port=-1, id={109 112 -14 -8 -44 98 79 85 -89 -48 -33 -127 -47 -30  
  3. 26 -75 }, payload={}, command={}, domain={}, ]  
 

 

 

 

Step3: 建立测试项目
在项目的web.xml中添加<distributable/>
testlb.jsp:
Html代码  收藏代码
  1. <%@ page contentType="text/html; charset=GBK"%>  
  2. <%@ page import="java.util.*"%>  
  3. <html>  
  4.     <head>  
  5.         <title>Cluster App Test</title>  
  6.     </head>  
  7.     <body>  
  8.         Server Info:  
  9.         <%  
  10.         out.println(request.getLocalAddr() + " : " + request.getLocalPort() + "<br>");  
  11.         %>  
  12.         <%  
  13.             out.println("<br> ID " + session.getId() + "<br>");  
  14.             // 如果有新的 Session 属性设置  
  15.             String dataName = request.getParameter("dataName");  
  16.             if (dataName != null && dataName.length() > 0) {  
  17.                 String dataValue = request.getParameter("dataValue");  
  18.                 session.setAttribute(dataName, dataValue);  
  19.             }  
  20.             out.println("<b>Session 列表</b><br>");  
  21.             System.out.println("============================");  
  22.             Enumeration e = session.getAttributeNames();  
  23.             while (e.hasMoreElements()) {  
  24.                 String name = (String) e.nextElement();  
  25.                 String value = session.getAttribute(name).toString();  
  26.                 out.println(name + " = " + value + "<br>");  
  27.                 System.out.println(name + " = " + value);  
  28.             }  
  29.         %>  
  30.         <form action="testlb.jsp" method="POST">  
  31.             名称:  
  32.             <input type=text size=20 name="dataName">  
  33.             <br>  
  34.             值:  
  35.             <input type=text size=20 name="dataValue">  
  36.             <br>  
  37.             <input type=submit>  
  38.         </form>  
  39.     </body>  
  40. </html>  
 
多次刷新页面的sessionID看是同一个ID,说明session是复制成功了。那么session中的存储的东西呢,在输入框中分别输入1、1,2、2,3、3后,显示结果如下图: 
 
 

(以下为原文摘抄,我真的比较lazy)

 

以上的测试说明,集群中的session已经共享,每个集群对于同一访问均有相同的session,而且session中存储的变量也复制了。

 

节点插拔测试

插拔意思是应该保证当运行的集群中某节点中关闭或者启动时,集群正常工作并且节点能够正常工作。

下面描述测试过程了,贴图太占地方了。

关闭Tomcat2,刷新页面,则不断访问Tocmat1和Tomcat3,再关闭Tomcat1后,则只访问一个Tomcat3,说明节点关闭时运行正常。

如果重启Tomcat2,无论怎么刷新,始终访问Tomcat3,难道Apache不能将请求转发给中途启动的Tomcat2?。。。这时利用另外台机器访问页面,发现Tomcat2正常,然后在刷本地页面,又可以访问Tomcat2了。

从上面可以看出Apache的负载均衡时的算法了,对于每个新来的session,Apache按照节点配置中的lbfactor比重选择访问节点,如果某节点node1不能访问,则寻找下一可访问节点,并且将此node1就在该访问session的访问黑名单中,以后该session的访问直接不考虑node1,即使node1又可以访问了。而新来的session是无黑名单的,如果新的session能够访问到node1了,则会将node1在其他所有session访问的黑名单删除,这样其他session就又能访问node1节点了。以上只是个人经过测试后的猜想。

经过以上测试,说明Tomcat集群和负载均衡已经实现了。

 

关于集群我还有些疑问,所以又测试了下,直接把结论写出来:

1.集群下的相同的应用可以名称不同(好像没必要啊),只要配置server.xml中host下的context具有相同的path即可。

2. 如果应用名称可以不同,那么应用下内容是否可以不同呢(这里考虑将不同应用通过集群看起来是一个应用,并且共享session),然后集群下不同应用映射为相同的访问path,具有相同的路径则负载,如果某路径只某个应用具有,则一直访问该应用。可现实很骨干啊,答案是否定的,至少我以上的配置不能实现。如果访问只有某应用具有的特别路径,那么只有负载到该应用才可以访问,否则直接路径未找到的错误页面了。

 

 

 如果您看过网上其他Apache+Tomcat的集群配置,您可能有的疑问?

1.网上大部分的文章配置2个tocmat的集群,有的将workers.properties下的worker.controller.sticky_session=1,
然后tomcat1中的server.xml中的jvmRoute设置为tomcat2,将tomcat2中的jvmRoute设置为tocmat1,当然我这样设置
也成功了,但是如果3个或者更多tocmat呢,怎么设置每个tomcat的jvmRoute,我不会所以才考虑现在的配置

2.server.xml中的Cluster配置问题,网上大部分都是使用BackupManager方式,即Cluster下又粘贴了一堆配置。其实
只要将其中注释掉的<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>去掉注释就完成session的集群
复制了。只是这俩种复制采用的方式不同而已。http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html
这页面已经说的挺清楚了,集群的session复制默认是DeltaManager,是all to all的复制,意思是将集群下1个tomcat应用下的session
对所有的集群中的节点进行复制,即使那个节点没有发布应用。显然是不好的方式,但这在小规模的集群下并没神马问题。
而采用BackupManager,就是众多网上配置那样,对于需要复制的节点设置BackupManager自然也没问题,
但是它的性能并没有DeltaManager 好使“ Downside of the BackupManager: not quite as battle tested as the delta manager”。
因此,具体怎么设置就看大家了,通常说如果不是大规模集群,就默认就好了。反正我自己翻译的就是这个意思了,希望没有误导大家。

 

最后一个比较全的关于session 同步使用jdbc方式的帖子

http://www.datadisk.co.uk/html_docs/java_app/tomcat6/tomcat6_clustering.htm

http://blog.csdn.net/lifuxiangcaohui/article/details/9703297

分享到:
评论
1 楼 sjzcmlt 2016-12-14  
,写的挺好的啊

相关推荐

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

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

    配置Cognos8服务器负载均衡

    在企业级应用中,Cognos 8 是一个强大的商业智能和分析平台,为了提高其服务的可用性和性能,通常会采用负载均衡技术。负载均衡能够有效地分散客户端请求到多台服务器,避免单点故障,确保系统的高可用性和可扩展性...

    一个完整的nginx配置文件范例参考(含负载均衡)

    Nginx 是一款高性能的 HTTP 和反向代理服务器,常用于网站服务器和负载均衡器的角色。下面我们将深入探讨这个包含负载均衡配置的 Nginx 示例。 首先,配置文件的开头定义了 Nginx 运行的基本参数。`user nobody ...

    Nginx负载均衡与地址映射配置的完整配置

    Nginx支持多种负载均衡策略,包括轮询(round-robin)、最少连接数(least connections)、IP哈希(ip_hash)等。以轮询为例,配置如下: ```nginx http { upstream backend { server 192.168.1.100:8080; ...

    SpringCloud 全部完整例子

    通过这个例子,你可以学习如何创建一个Zuul网关,处理微服务间的请求转发。 4. **Hystrix Circuit Breaker**:Hystrix是Netflix开源的熔断器,用于防止服务雪崩。此示例展示了如何在微服务中集成Hystrix,实现服务...

    F5负载均衡命令行。配置F5

    ### F5 负载均衡器命令行配置详解 #### 一、引言 F5 BIG-IP 系统作为一款高性能的负载均衡解决方案,在众多企业和数据中心中扮演着至关重要的角色。通过命令行界面(CLI),管理员可以实现对 F5 设备的高效管理与...

    02Spring Cloud Ribbon:负载均衡的服务调用1

    在Spring Cloud生态系统中,Spring Cloud Ribbon是一个至关重要的组件,它主要负责实现客户端的负载均衡,以确保服务间的调用能够均匀地分散到各个实例上,从而提高系统的整体可用性和性能。Ribbon是Netflix开发的一...

    jboot+dubbo+nacos例子.zip

    【标题】"jboot+dubbo+nacos例子.zip"是一个整合了JBoot、Dubbo和Nacos的示例项目,展示了如何在Java环境中利用这三大框架进行微服务开发。 【描述】"jboot+dubbo+nacos例子" 提示这是一个用于演示JBoot与Dubbo集成...

    springcloud例子(非常完整)

    这个“springcloud例子(非常完整)”的压缩包包含了一系列的示例,涵盖了SpringCloud的核心功能,如API网关、负载均衡以及微服务间的通信。 首先,让我们来了解一下**API网关**。API网关是微服务架构中的一个重要...

    web service 完整例子(绝对好)

    本示例提供了一个完整的Web服务实现,用于客户端向服务端发送数据,并由服务端将这些数据存储到数据库中。这个过程涉及到了多个关键的技术和概念,包括HTTP协议、SOAP(简单对象访问协议)、WSDL(Web服务描述语言)...

    Nginx-1_6_2+Memcached-1_2_6+Tomcat7负载均衡实现Session共享

    总的来说,这个例子提供了一个实用的Web服务架构,通过Nginx的负载均衡能力结合Memcached的Session共享机制,实现了高可用性和高性能。`说明.doc`和`说明.txt`文件应该包含了更详细的步骤和注意事项,建议仔细阅读并...

    rabbitmq完整例子

    RabbitMQ是一个开源的消息队列系统,基于AMQP(Advanced Message Queuing Protocol)协议实现,广泛应用于分布式系统中,用于解耦组件、处理异步任务和实现负载均衡。在这个"rabbitmq完整例子"中,包含了客户端和...

    SpringCloud 15个完整例子

    2. **Spring Cloud Ribbon**:Ribbon是客户端负载均衡器,可以在请求发送到服务器时进行负载均衡,实现服务间的高效调用。 3. **Spring Cloud Hystrix**:Hystrix提供了断路器模式,防止服务雪崩,保护整个微服务...

    springCloud例子

    总之,“springCloudDemo”是一个全面展示SpringCloud功能的实战案例,涵盖了微服务架构中的主要组件和实践,对于学习和掌握SpringCloud技术栈具有很高的参考价值。通过深入研究和实践这个项目,开发者可以提升在...

    dubbo+sping+zookeeper整合例子完整版(包括步骤文档和所有jar).zip

    标题 "dubbo+spring+zookeeper整合例子完整版(包括步骤文档和所有jar).zip" 提供的是一个关于如何集成Dubbo、Spring和Zookeeper的实战示例,这是一套常见的微服务架构组合。Dubbo是一个高性能、轻量级的开源Java RPC...

    从Eureka到Ribbon、RestTemplate、Hystrix、Feign、zuul一个小例子

    在Spring Cloud生态系统中,Eureka、Ribbon、...这个小例子将展示如何整合这些组件,构建一个完整的微服务调用流程。通过学习和实践这个例子,开发者可以更好地理解和掌握Spring Cloud的核心组件及其相互协作的方式。

    spring深入26个例子

    7. **Spring Cloud**:对于微服务架构,Spring Cloud提供了服务发现、配置中心、负载均衡、熔断机制等功能。例子可能会展示Eureka服务注册与发现、Zuul API网关或者Hystrix断路器的使用。 8. **Spring Security**:...

    thinkphp实现在线聊天功能的例子共9页.pdf.zi

    通过阅读这个9页的PDF文档,开发者应该能了解到如何在ThinkPHP项目中集成这些技术和最佳实践,实现一个完整的在线聊天功能。由于未提供具体的文件内容,无法进行更深入的讨论,但以上信息提供了构建此类功能的一般...

    thrift完整例子

    然而,对于大型复杂系统,Thrift可能需要与其他工具(如服务治理框架)配合使用,以解决负载均衡、容错等问题。 通过学习和实践"thrift完整例子",你可以深入了解Thrift的工作原理,掌握如何定义服务接口、如何生成...

Global site tag (gtag.js) - Google Analytics