您的位置:首页 > 运维架构 > Tomcat

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

2016-02-20 18:35 1041 查看
本文作者:陈超允[b]chenchaoyun0[/b]

写在前面的知识:

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/article/8005145.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: