Apache + Tomcat +mod_jk- win7与linux下实现负载均衡与集群-

本文作者:陈超允chenchaoyun0

写在前面的知识:

1、关于mod_jk

mod_jk简称JK,是Apache服务器的一个可插入模块,用于为Apache服务器提供处理JSP/SERVLET的能力。Apache作为一个很强大的Web服

务器,本身缺乏处理JSP/SERVLET的能力,为了能够处理对JSP/SERVLET的请求,必须使用JSP/SERVLET容器,如Tomcat等。Tomcat本身

也可以作为Web服务器使用,但是他的能够远不及Apache强大,所以Tomcat往往作为JSP/SERVLET等容器的使用。mod_jk实质上是Apache与

Tomcat的连接器,并附带提供了集群和负载均衡的功能。

2、apache安装包中的“no ssl”和“openssl”是什么意思?

openSSL是表示带有OpenSSL模块,利用OpenSSL就可以给Apache配置SSL安全链接的,也就是使用https://方式进行访问;no ssl则表示不带

OpenSSL模块,无法用于SSL安全链接。Tomcat中的集群原理是通过组播的方式进行节点的查找并使用TCP连接进行会话的复制。实现效果:

用Apache分发请求到tomcat中对应的项目

操作环境:

操作系统:win7、虚拟机ubuntu15.04

jdk:1.7

Apache:2.2.22-下载地址:http://httpd.apache.org/download.cgi

Tomcat:7.0.67-选择自己的版本即可,我在本机上模拟展示3个节点

Mod_jk:1.2.40-这个很重要,一定要选择对自己的版本,不然apache启动不了。下载地

址:http://mirror.bjtu.edu.cn/apache/tomcat/tomcat-connectors/jk/binaries/windows/




安装步骤:

1、安装JDK,这不用说了吧,必须的。

2、安装Apache,使用默认配置,并且在安装路径中不要空格。我的是D:\Apache2.2

3、解压Tomcat-分别命名:tomcat-node1、tomcat-node2、tomcat-ubuntu(这是在虚拟上的一个tomcat,没有的话两个就可以了,我是放在D盘)

4、拷贝下载的mod_jk.so到Apache安装目录下的modules文件夹下。


配置步骤:

1、修改Apache配置文件httpd.conf(我的路径是:C:\Apache2.2\conf\httpd.conf),在最后一行默认添加:

include "C:\Apache2.2\conf\mod_jk.conf"

 
 

2、在httpd.conf同目录新建mod_jk.conf,并添加以下内容:

#加载mod_jk Module 
LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so<span style="font-family: Arial, Helvetica, sans-serif;">#指定 workers.properties文件路径</span>
JkWorkersFile conf/workers.properties
#指定哪些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器名
JkMount /* controller


 
 
 
 

3、在httpd.conf同目录新建workers.properties

#这里可以配置任意多个Tomcat,此处配置了2个Tomat服务器.
#host和port根据自己实际配置.实例配置的是本机两个tomcat,分别使用不同的端口.避免冲突
#如果Tomcat不再同一机器上,没必要改端口的。




#server 列表
worker.list=controller,tomcat1,tomcat2,tomcat3,tomcat4




#========tomcat1========


worker.tomcat1.port=8888       #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat1.host=localhost        #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor=1        #server的加权比重,值越高,分得的请求越多


#========tomcat2========


worker.tomcat2.port=9999        #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat2.host=localhost        #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor=1        #server的加权比重,值越高,分得的请求越多 


#========tomcat3========


#worker.tomcat3.port=7777   #ajp13 端口号,在tomcat下server.xml配置,默认8009
#worker.tomcat3.host=192.168.0.45  #tomcat的主机地址,如不为本机,请填写ip地址
#worker.tomcat3.type=ajp13#这是在局域网下另一台机器的配置
#worker.tomcat3.lbfactor=1       #server的加权比重,值越高,分得的请求越多 


#========tomcat4========


worker.tomcat4.port=8787   #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat4.host=192.168.0.124   #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat4.type=ajp13#这是在ubuntu下的配置

worker.tomcat4.lbfactor=1#server的加权比重,值越高,分得的请求越多 

#========controller,负载均衡控制器========
worker.controller.type=lb




#指定此负载平衡器负责的Tomcat应用节点。


worker.controller.balanced_workers=tomcat1,tomcat2,tomcat3,tomcat4#指定分担请求的tomcat


#此处指定集群是否需要会话复制,如果设为true,则表明为会话粘性,不进行会话复制,当某用户的请求第一次分发到哪台
#Tomcat后,后继的请求会一直分发到此Tomcat服务器上处理;如果设为false,则表明需求会话复制。


#worker.controller.sticky_session=false    #设为false,则表明需求会话复制。


worker.controller.sticky_session=0    #
worker.controller.sticky_session_force=1  #这里session黏性与session复制




 
  
 

Tomcat配置:

说明:如果修改了tomcat配置文件,最好将文件编码转换成UTF-8,我这里两个在win7下,还有一个在虚拟机里的ubuntu下

因为实例中我们定义了两个tomcat处理分发,所以我们将tomcat的解压版本格式复制一份。Tomcat6和tomcat7的配置方式一样,下面是两个没修改前一样的tomcat。

以tomcat_node1为例:

1、修改分发tomcat对应的service.xml文件,保证Apache对应的workers.properties中的AJP13的connector的port。

<!--定义一个AJP 1.3 连接端口为888 ,默认值为8009,这里我们改成我们自己定义的9988端口 -->
<Connector port="8888" protocol="AJP/1.3" redirectPort="8443" />

 
 

2、增加jvmRoute的值,保证同worders.properties里面的配置一致。

<!--增加jvmRoute,值为在Apache中配置的list集群结点中的值,这里定义为tomcat1结点-->
<Engine name="Catalina"defaultHost="localhost"jvmRoute="tomcat1">

 
 3、 
 去掉默认注释掉的集群配置 
 

<!--取消集群结点相关的注释,该句默认值注释掉的,我们需要配置集群所以去掉注释,让其起作用-->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

 
 如果我们的tomcat节点分布在不同机器上,那么我们的集群至此已经配置完成。去掉多余注释,显示做了修改的部位。修改前的tomcat-node1: 
 

<!--Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!--You should set jvmRoute to support load-balancing via AJP ie :<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering-->
<!--   <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>-->

修改后的tomcat-node1

<!--定义一个AJP 1.3 连接端口为9988 ,默认值为8009,这里我们改成我们自己定义的9988端口 -->
<Connector port="8888" protocol="AJP/1.3" redirectPort="8443" />
<!--增加jvmRoute,值为在Apache中配置的list集群结点中的值,这里定义为tomcat1结点-->
 <Engine name="Catalina" defaultHost="localhost"  jvmRoute="tomcat1">
<!--取消集群结点相关的注释,该句默认值注释掉的,我们需要配置集群所以去掉注释,让其起作用-->  
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

 
 

修改后的tomcat-node2

<!--Define an AJP 1.3 Connector on port 8009 -->
<Connector port="9999" protocol="AJP/1.3" redirectPort="8443" />
<!--You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Engine name="Catalina" defaultHost="localhost"  jvmRoute="tomcat2">
<!--For clustering-->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>


 
 

修改后的tomcat-ubuntu

说明:这里的protocol=”AJP/1.3”,连接以及jvmRoute需要保证同我们Apache服务器中配置的works.properties一致。修改完后最好将service.xml文件的编码方式设置为utf-8。否则可能tomcat启动报错。

4、实例中我们的两个tomcat节点在同一台机器上,所以我们还需要保证protocol=”HTTP/1.1”的端口不一致,不然本地的两个tomcat会起冲突。

下面是本实例中解决同一台机器上多个tomcat服务器之间端口冲突做的修改:

图片参考至 http://www.tuicool.com/articles/feABvu

Tomcat-node2做的修改

<pre name="code" class="html"><Server port="9995" shutdown="SHUTDOWN">
<!--…略…-->
<Connector port="9990" 
protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<!--…略…-->
 
 

说明:这里的protocol=”HTTP/1.1”配置相关端口之间不能冲突,而且也不能同本机其他应用程序占用的端口冲突,否则可能

报错。

测试:

1、需要注意的是,项目的实体类需要实现serializable接口,

(1)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
(2)当你想用套接字在网络上传送对象的时候; java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对            象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象            的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
(3)当你想通过RMI传输对象的时候; RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。在            创建的WEB工程的web.xml文件中增加

<distributable/>

2、修改工程中index.jsp页面的代码,修改的结果如下:

<%@ page contentType="text/html; charset=gbk"%>
<%@ page import="java.util.*"%>
<html>
<head>
<title>Cluster App Test</title>
</head>
<body>
	Server Info:
	<%
	out.println(request.getLocalAddr() + " : " + request.getLocalPort()
			+ "<br>");
	%>
	<%
		out.println("<br> ID " + 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("<b>Session 列表</b><br>");
		System.out.println("============================");
		Enumeration e = session.getAttributeNames();
		while (e.hasMoreElements()) {
			String name = (String) e.nextElement();
			String value = session.getAttribute(name).toString();
			out.println(name + " = " + value + "<br>");
			System.out.println(name + " = " + value);
		}
	%>
	
</body></html>


 

3、测试负载均衡与session分发

将项目部署到每个集群节点中,即实例中的tomcat_node1和tomcat_node2,依次启动Apache,和Tomcat服务器,两个Tomcat服务器的启动顺序随意。这里Apache的端口使用安装的时候选择的8080.


这是tomcat1的


这是tomcat2的



这是在ubuntu里的



相信都能看出来,这两个sesssion斌不一样。

下面说说session的复制问题


关于session的复制讨论

sticky_session           sticky_session_force           结论

0                                   0                                            session无黏性,session会复制

0                                   1                                            session无黏性,session会复制

1                                   0                                            session有粘性(非强制)session会复制

1                                   1                                            session有粘性(强制)session没必要再复制(此处有争议,待深入研究

常见问题:

1、  如果同一台机器上的节点之间session能够同步,但是不同机器间的session无法同步,可能的原因是机器间的时钟不同步,需要进行同步操作。

2、    关于Cluster
此实验中对Cluster的配置如下:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
其实这只是对Cluster的最简单的一种配置,该配置下tomcat使用的是all-to-all方式的session同步,这种方式只适用于小规模的集群。文章开头列举了三种session同步策略,all-to-all属于第二种,tomcat也支持第三种,只需为Cluster配置BackupManager即可

3、  关于jvmRoute
前面实验中的sessionid由两部分组成(前缀+后缀),而其后缀名就是jvmRoute配置的名称,mod_jk需要根据这个后缀名进行请求转发:当sticky_session=1时,mod_jk根据这个后缀名来判断该会话应该始终由哪个tomcat进行处理。

总结:


worker.controller.sticky_session=false,提交页面,将按照负载均衡的规则切换服务器,实现“完全的负载均衡”,代价是
Tomcat不停交换session数据,慢;
worker.controller.sticky_session=true,提交页面将仍使用同一服务器(session建立在哪就用哪台),不能保证完完全全的负
载均衡,但相对能省频繁切换服务器的代价。可能会变上面的快一些。
worker.controller.sticky_session_force=true,始终转发到session创建的服务器上。

我一直很纠结这个,如果说sticky_session=true的话,一个浏览器的请求就都是由一个tomcat去处理。=false的话,就按照负

载均衡去处理但是这个就得tomcat间一直来回复制会话了,性能上也有损失吧。我觉得session不复制是不是应该好一些,不

然如果很多用户登录了,session就得在多个tomcat间来回复制了。sticky_session=true的话,不进行session复制,按照用户

浏览器去实现负载均衡,这样应该好一点~~~其实好像就是,一个是按照请求去负载均衡,就必须得来回复制会话;另一个是

按照用户浏览器去实现的负载均衡,那就不需要了。应该是后者,一开始理解错了 ,现在改成1,0测试。




但结果并非那么乐观,还是一样,可能是因为不同的机子而session不一样。日后找到解决的办法再来补充

参考文档:http://www.tuicool.com/articles/feABvu 、http://blog.csdn.net/lubiaopan/article/details/8936443




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值