最近公司提出了负载均衡的新需求,以减轻网站的高峰期的服务器负担。趁空闲时间我就准备了一下这方面的知识,都说有备无患嘛。网上相关资料很多,但是太散。我希望可以通过这篇随笔,系统的总结。

一、Tomcat集群对负载均衡可以用以下几种实现方式:

  • proxy
  • proxy_blancer
  • mod_jk

二、proxy、proxy_blancer和mod_jk的优缺点比较:

proxy的缺点:当其中一台tomcat停止运行的时候,apache仍然会转发请求过去,导致502网关错误。但是只要服务器再启动就不存在这个问题。

mod_jk方式的优点:Apache 会自动检测到停止掉的tomcat,然后不再发请求过去。缺点:当停止掉的tomcat服务器再次启动的时候,Apache检测不到,仍然不会转发请求过去。

proxymod_jk的共同优点是:可以只将Apache置于公网,节省公网IP地址资源。可以通过设置来实现Apache专门负责处理静态网页,让Tomcat专门负责处理jsp和servlet等动态请求。共同缺点是:如果前置Apache代理服务器停止运行,所有集群服务将无法对外提供。

proxy和mod_jk对静态页面请求的处理,都可以通设置来选取一个尽可能优化的效果。

mod_proxy_balancer和mod_jk都需要修改tomcat的配置文件配合<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
这三种Tomcat集群方式对实现最佳负载均衡都有一定不足,mod_proxy_balancer和mod_jk相对好些,mod_jk的设置能力更强些。lbfactor参数来分配请求任务。
apache自带mod_proxy功能模块中目前只可以实现两种不同的负载均衡集群实现方式,第一种是分工合作的的形式,通过各台主机负责不同的任务而实现任务分工。第二种是不同的机器在担任同样的任务,某台机器出现故障主机可以自动检测到将不会影响到客户端,而第一种却不能实现但第一种实现方式的优点在于他是主服务器负担相应没第二种大因为台只是提供跳转指路功能,形象的说他不给你带路只是告诉你有条路可以到,但到了那是否可以看到你见的人他已经不会去管你了。相比之下第二种性能要比第一种会好很多;但他们都有个共同点都是一托N形式来完成任务的所以你的主机性能一定要好。

本文的例子是利用ApacheHttpServer2.2+tomcat6+mod_jk做负载均衡。

一、准备工作

1、下载相关软件包:

  ApacheHttpServer

  Tomcat6.rar(复制两份)

  mod_jk.so(可以看做ApacheHttpServer的一个插件吧,用来给tomcat分流)

2、下载解压后的文件,复制到C盘根目录,如图:

  说明:如果apache是安装版的安装到指定目录(我的例子安装在了C盘更目录),如果是解压版直接解压到指定目录就OK。

  注意:不论是安装板还是解压版,在安装或解压后,必须在cmd命令窗口下安装apache服务。

  在安装后的apache下的bin目录,在地址栏输入cmd进入命令窗口,输入httpd -k install 安装服务成功后,可根据以下命令进行操作:

/*
* 安装apache服务
* 默认服务名称为apache+版本号
* 如果想自定义服务名称可在该命令后加" -n 自定义服务名 "
*/
httpd -k install /*
*开启服务
*/
httpd -k start /*
*停止服务
*/
httpd -k stop /*
*重启服务
*/
httpd -k restart /*
*卸载服务
*/
httpd -k uninstall /*
*测试服务配置
*/
httpd -t /*
*服务版本详情
*/
httpd -v /*
*命令行选项卡
*/
httpd -h

安装apache服务成功后,开启服务,在浏览器输入locahost,看到如下页面说明安装成功:

接下来,解压Tomcat,复制一份,一个命名为tomcat1,另一个命名为tomcat2。

  

 

3、把tomcat2中一个conf文件夹里的server.xml,将所有的端口号(port)开头的80全部改为90,下面红色框圈出的三处都要改。

3、在tomcat1中大约102行处,添加jvmRoute="tomcat1",在tomcat2中server.xml大约102行处,添加jvmRoute="tomcat2",如下:

<!--tomcat1中添加-->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
<!--tomcat2中添加-->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">

4、在tomcat2中大约第107~108行插入以下代码。

   在tomcat1的server.xml里也插入以下代码,更改<Receiver>里的port为4000,以保证两个tomcat<Receiver>端口不重复。

<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" bind="127.0.0.1" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="127.0.0.1" port="4002" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" timeout="60000" keepAliveCount="120000"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

5、复制下载好的mod_jk.so连接模块到apache安装目录下的modules文件夹。

6、打开apache安装目录下的conf文件夹,新建mod_jk.conf文件,新建workers.properties文件

  • mod_jk.conf文件内容如下:
#加载mod_jk Module
LoadModule jk_module modules/mod_jk.so #指定 workers.properties文件路径
JkWorkersFile conf/workers.properties #指定那些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器
JkMount /*.jsp controller #指定jk的日志输出文件
JkLogFile logs/mod_jk.log #指定日志级别
JkLogLevel info #查询日志格式
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]" #Jk请求日志格式
JkRequestLogFormat "%w %V %T"
  • workers.properties文件内容如下:
#server 列表
worker.list = controller,tomcat1,tomcat2 #========tomcat1========
#ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat1.port=8009
#tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat1.host=localhost
#指定协议类型为AJP13定向包协议
worker.tomcat1.type=ajp13
#server的权重,值越高,分得的请求越多
worker.tomcat1.lbfactor = 1 #========tomcat2========
#ajp13 端口号,在tomcat下server.xml配置,默认8009,这里我们刚才改的是9009
worker.tomcat2.port=9009
#tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat2.host=localhost
#指定协议类型为AJP13定向包协议
worker.tomcat2.type=ajp13
#server的权重,值越高,分得的请求越多
worker.tomcat2.lbfactor = 1 #========controller,负载均衡控制器========
worker.controller.type=lb
#指定分担请求的tomcat
worker.controller.balance_workers=tomcat1,tomcat2
#是否为设置为黏着session,设置为1或true使用粘着session,设置为0或false不使用粘着session
worker.controller.sticky_session=false
#是否强制黏着
worker.controller.sticky_session_force=false #需要注意的地方
# sticky_session sticky_session_force 含义
# true false SESSION会复制,有粘性
# true true SESSION不复制,有粘性
# false false SESSION会复制,无粘性
# false true SESSION会复制,无粘性

7、打开apache目录下的conf文件夹下的httpd.conf配置文件,在最下方添加以下代码:

#加载mod_jk.conf文件
Include conf/mod_jk.conf

8、ok,配置完毕!可以进行测试了。以下是测试步骤:

  • 新建一个web项目命名为test

  • 在该项目下新建test.jsp和WEB-INFO文件夹
    • test.jsp内容:
    • <%@ page contentType="text/html; charset=UTF-8" %>
      <%@ page import="java.util.*" %>
      <html>
      <head>
      <title>Apache2+Tomcat+mod_jk测试负载均衡</title>
      <style>
      html { color:#000; background:#F5F5F5; font-family:"微软雅黑","Microsoft YaHei","黑体","SimHei","宋体"; font-size:12px;}
      form{ font-size: 14px;}
      body{margin-left:300px;margin-right:auto;margin-top: 30px;}
      h3{display: inline;}
      input{ border: 1px solid #D3D3D3;width: 200px;height: 30px;margin-bottom: 10px;margin-top: 10px; text-indent: 10px;font-family: "微软雅黑";font-size: 14px;}
      .btn{ border: 1px solid #D3D3D3;border-radius: 15px;outline: 0;background: #DB6D4C;font-family: "微软雅黑";font-weight: bold;font-size: 12px;color: white;width: 100px;height: 30px; margin: 0 auto;}
      .btn:hover{background: #3A3A3A;}
      .content{ border: 1px solid #D3D3D3; margin: auto 10px; margin-bottom: 10px; width:500px;height:auto;padding:10 10 10 10 ;}
      table{ border: 1px solid #D3D3D3;margin: auto 10px;}
      td div{margin:10 10 10 10 ; float: left;}
      </style>
      </head> <body>
      <form action="http://localhost/test/test.jsp" method="POST">
      <table cellpadding="0" cellspacing="0">
      <tr>
      <td>
      <div>
      session名:<input type="text" size=20 name="dataName"placeholder="请输入session名"><br/>
      session值:<input type="text" size=20 name="dataValue"placeholder="请输入session值"><br>
      <input type="submit" value="点击提交" class="btn">
      </div>
      </td>
      </tr>
      </table>
      </form> <div class="content">
      <h3>请求地址:</h3>
      <% out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%> <%
      out.println("<br><h3>Session ID:</h3> " + session.getId()+"<br/>");
      // 如果有新的 Session 属性设置
      String dataName = request.getParameter("dataName");
      if (dataName != null && dataName.length() > 0) {
      String dataValue = request.getParameter("dataValue");
      session.setAttribute(dataName, dataValue);
      } out.println("<br/><h3>Session 列表:</h3><br>");
      System.out.println("=========================================");
      System.out.println("Tomcat print session Info:"); out.println("------------------------------------------<br/>"); Enumeration e = session.getAttributeNames();
      while (e.hasMoreElements()) {
      String name = (String)e.nextElement();
      String value = session.getAttribute(name).toString();
      out.println("SessionName:"+ name + " | SessionValue:" + value + "<br>");
      System.out.println("SessionName:" + name + " | SessionValue:" + value);
      }
      out.println("------------------------------------------<br/>");
      %>
      </div>
      </body>
      </html>
  • 在WEB-INFO下新建web.xml文件复制test项目到tomcat1、tomcat2文件夹的wabapp下分别部署
    • web.xml内容:

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>test</display-name>
      <distributable/>
      </web-app>
  • 依次启动apache、tomcat1、tomcat2;在浏览器输入http://localhost/test/test.jsp按页面填写数据、刷新浏览器、宕掉其中一个节点等测试,观察页面信息和tomcat后台打印信息进行测试!
  • 测试页面如下:

好了,这篇随笔就介绍到这里,欢迎大家多多批评,有不足之处还望各位前辈斧正!

 

Apache+Tomcat+mod_jk实现负载均衡的更多相关文章

  1. Apache + Tomcat集群 + 负载均衡

    Part I: 取经处: http://www.ramkitech.com/2012/10/tomcat-clustering-series-simple-load.html  http://blog ...

  2. Linux中Apache+Tomcat+JK实现负载均衡和群集的完整过程

    人原创,一个字一个字地码的,尊重版权,转载请注明出处! http://blog.csdn.net/chaijunkun/article/details/6987443 最近在开发的项目需要承受很高的并 ...

  3. ngnix apache tomcat集群负载均衡配置

    http://w.gdu.me/wiki/Java/tomcat_cluster.html 参考: Tomcat与Apache或Nginx的集群负载均衡设置: http://huangrs.blog. ...

  4. Apache + Tomcat + mod_jk实现集群服务及session共享

    实现效果:用apache 分发请求到tomcat中的对应的项目 原理:

  5. 2.Apache + Tomcat + mod_jk实现集群服务

    转自:http://www.cnblogs.com/dennisit/p/3370220.html Tomcat中的集群原理是通过组播的方式进行节点的查找并使用TCP连接进行会话的复制. 实现效果:用 ...

  6. 搭建nginx+tomcat+Java的负载均衡环境

    转载  未测 供参考 另外这篇文章也不错.http://blog.csdn.net/wang379275614/article/details/47778201 一.简介: Tomcat在高并发环境下 ...

  7. 【转】搭建nginx+tomcat+Java的负载均衡环境

    一.简介: Tomcat在高并发环境下处理动态请求时性能很低,而在处理静态页面更加脆弱.虽然Tomcat的最新版本支持epoll,但是通过Nginx来处理静态页面要比通过Tomcat处理在性能方面好很 ...

  8. Nginx+Tomcat+Redis实现负载均衡、资源分离、session共享

    Nginx+Tomcat+Redis实现负载均衡.资源分离.session共享 CentOS安装Nginx http://centoscn.com/CentosServer/www/2013/0910 ...

  9. Apache+Tomcat+mod_jk配置教程

    0.说明 首先我们要弄明白mod_jk的作用是反向代理,而其实使用httpd.conf中的<VirtualHost>标签就可以实现反向代理,为什么还要多搞个mod_jk那么麻烦做反向代理. ...

随机推荐

  1. 【转载】Understanding When to use RabbitMQ or Apache Kafka

    https://content.pivotal.io/rabbitmq/understanding-when-to-use-rabbitmq-or-apache-kafka RabbitMQ: Erl ...

  2. MongoDB入门 和nodejs操作

    简介 MongoDB 开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序:高伸缩性: NoSQL毕竟还处于发展阶段,也有说它的各种问题的:http://coolshel ...

  3. mybatis 传递参数的两种方式与模糊匹配 很重要

  4. Java进阶之路

    Java进阶之路——从初级程序员到架构师,从小工到专家. 怎样学习才能从一名Java初级程序员成长为一名合格的架构师,或者说一名合格的架构师应该有怎样的技术知识体系,这是不仅一个刚刚踏入职场的初级程序 ...

  5. ubuntu关闭和开启防火墙

    1.关闭ubuntu的防火墙 ufw disable 2开启防火墙 ufw enable 3.卸载了iptables apt-get remove iptables 4.关闭ubuntu中的防火墙的其 ...

  6. Chemical table CodeForces - 1012B

    题意: 一个棋盘 对于任何一个棋盘中的矩形 如果 任意三角存在棋子 则第四个角会自动生成一个棋子  求铺满整个棋盘 我们至少要向棋盘里加多少枚棋子 解析: 这题就是求图中有多少个连通图,可以直接dfs ...

  7. Sum 南京网络赛J题

    题意: 统计每个数的因子的对数,如果因子能被某个平方数整除,则不统计在内,每对因子有序 解析: 我们对某个数n进行质因子分解,如果某个质因子的指数大于2则 f(n) = 0, 例 N = X3 * M ...

  8. oracle 查出一个表中字段值出现次数大于2的所有记录

    表web_order  列 name ,businesscode, a.account 周桥 18929609222 3754031157710000妙药 18929609233 3754031157 ...

  9. 【BZOJ1434】[ZJOI2009]染色游戏(博弈论)

    [BZOJ1434][ZJOI2009]染色游戏(博弈论) 题面 BZOJ 洛谷 题解 翻硬币的游戏我似乎原来在博客里面提到过,对于这类问题,当前局面的\(SG\)函数就是所有反面朝上的硬币单一存在时 ...

  10. 神奇:java中float,double,int的值比较运算

    float x = 302.01f;    System.out.println(x == 302.01); //false  System.out.println(x == 302.01f); // ...