Apache+Tomcat+mod_jk实现负载均衡
最近公司提出了负载均衡的新需求,以减轻网站的高峰期的服务器负担。趁空闲时间我就准备了一下这方面的知识,都说有备无患嘛。网上相关资料很多,但是太散。我希望可以通过这篇随笔,系统的总结。
一、Tomcat集群对负载均衡可以用以下几种实现方式:
- proxy
- proxy_blancer
- mod_jk
二、proxy、proxy_blancer和mod_jk的优缺点比较:
proxy的缺点:当其中一台tomcat停止运行的时候,apache仍然会转发请求过去,导致502网关错误。但是只要服务器再启动就不存在这个问题。
mod_jk方式的优点:Apache 会自动检测到停止掉的tomcat,然后不再发请求过去。缺点:当停止掉的tomcat服务器再次启动的时候,Apache检测不到,仍然不会转发请求过去。
proxy和mod_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>
- web.xml内容:
- 依次启动apache、tomcat1、tomcat2;在浏览器输入http://localhost/test/test.jsp按页面填写数据、刷新浏览器、宕掉其中一个节点等测试,观察页面信息和tomcat后台打印信息进行测试!
- 测试页面如下:
好了,这篇随笔就介绍到这里,欢迎大家多多批评,有不足之处还望各位前辈斧正!
Apache+Tomcat+mod_jk实现负载均衡的更多相关文章
- Apache + Tomcat集群 + 负载均衡
Part I: 取经处: http://www.ramkitech.com/2012/10/tomcat-clustering-series-simple-load.html http://blog ...
- Linux中Apache+Tomcat+JK实现负载均衡和群集的完整过程
人原创,一个字一个字地码的,尊重版权,转载请注明出处! http://blog.csdn.net/chaijunkun/article/details/6987443 最近在开发的项目需要承受很高的并 ...
- ngnix apache tomcat集群负载均衡配置
http://w.gdu.me/wiki/Java/tomcat_cluster.html 参考: Tomcat与Apache或Nginx的集群负载均衡设置: http://huangrs.blog. ...
- Apache + Tomcat + mod_jk实现集群服务及session共享
实现效果:用apache 分发请求到tomcat中的对应的项目 原理:
- 2.Apache + Tomcat + mod_jk实现集群服务
转自:http://www.cnblogs.com/dennisit/p/3370220.html Tomcat中的集群原理是通过组播的方式进行节点的查找并使用TCP连接进行会话的复制. 实现效果:用 ...
- 搭建nginx+tomcat+Java的负载均衡环境
转载 未测 供参考 另外这篇文章也不错.http://blog.csdn.net/wang379275614/article/details/47778201 一.简介: Tomcat在高并发环境下 ...
- 【转】搭建nginx+tomcat+Java的负载均衡环境
一.简介: Tomcat在高并发环境下处理动态请求时性能很低,而在处理静态页面更加脆弱.虽然Tomcat的最新版本支持epoll,但是通过Nginx来处理静态页面要比通过Tomcat处理在性能方面好很 ...
- Nginx+Tomcat+Redis实现负载均衡、资源分离、session共享
Nginx+Tomcat+Redis实现负载均衡.资源分离.session共享 CentOS安装Nginx http://centoscn.com/CentosServer/www/2013/0910 ...
- Apache+Tomcat+mod_jk配置教程
0.说明 首先我们要弄明白mod_jk的作用是反向代理,而其实使用httpd.conf中的<VirtualHost>标签就可以实现反向代理,为什么还要多搞个mod_jk那么麻烦做反向代理. ...
随机推荐
- springboot项目的创建
创建springboot项目 包名和项目名 选择需要使用的框架,web 然后再点击下一步,完成即可创建springboot项目
- ElasticSearch 2 (31) - 信息聚合系列之时间处理
ElasticSearch 2 (31) - 信息聚合系列之时间处理 摘要 如果说搜索是 Elasticsearch 里最受欢迎的功能,那么按时间创建直方图一定排在第二位.为什么需要使用时间直方图? ...
- HDU 2051 Bitset
http://acm.hdu.edu.cn/showproblem.php?pid=2051 Problem Description Give you a number on base ten,you ...
- js浮点数保留一位小数
function changeTwoDecimal_f(x) { var f_x = parseFloat(x); if (isNaN(f_x)) { alert('function:changeTw ...
- 如何用js替换文本里的换行符 \n?
有下面一段文本, 在编辑器里的格式如下: <div id="foo"> line1line2line3</div> 切换到浏览器, 显示如下 line1li ...
- BZOJ2428 HAOI2006均分数据(模拟退火)
显然可以状压dp.显然过不了. 考虑暴力模拟退火.每次随机改变一个数所属集合即可. 并不明白要怎么调参. #include<iostream> #include<cstdio> ...
- MT【184】$\epsilon$助力必要性
已知满足不等式$|x^2-4x+a|+|x-3|\le5$的最大值为$3$,求实数$a$的值,并解该不等式. 证明:1)当$x=3$时,$|a-3|\le5$,得$a\in[-2,8]$2)$\for ...
- pandas read_csv 读取中文列标题文件报错
Traceback (most recent call last): File "C:/Users/arron/PycharmProjects/ML/ML/test.py", li ...
- Installshield 打包安装程序时写入注册表,及运行bat文件
一.写入注册表 1. 打开project assistant –> Project Registry 可以像注册表里一样操作,其中[INSTALLDIR]是指的安装路径 二. 运行bat文件 ...
- SQL Server 查询性能优化——覆盖索引
覆盖索引又可以称为索引覆盖. 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖. 解释二: 索引是高效找到行的一个方法,当能通过检索索引 ...