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

Tomcat负载均衡原理详解及配置(Apache2.2.19+Tomcat7.0.12)

2014-03-28 16:01 483 查看

结构图

JAVA项目一般直接用Tomcat作为Web服务器。为了增加tomcat的性能和稳定性,我们一般采用balance和session同步机制。 下图列出了我们常用也是最简单的解决方案。View Code
1 #LoadModule proxy_http_module modules/mod_proxy_http.so
2 #LoadModule proxy_connect_module modules/mod_proxy_connect.so
3 #LoadModule proxy_module modules/mod_proxy.so
4 #Include conf/extra/httpd-vhosts.conf
1 #LoadModule proxy_http_module modules/mod_proxy_http.so
2 #LoadModule proxy_connect_module modules/mod_proxy_connect.so
3 #LoadModule proxy_module modules/mod_proxy.so
4 #Include conf/extra/httpd-vhosts.conf

打开文件conf\extra\httpd-vhosts.conf,可以看到如下代码:

View Code
1 #
2 # Use name-based virtual hosting.
3 #
4 NameVirtualHost *:80
5
6 #
7 # VirtualHost example:
8 # Almost any Apache directive may go into a VirtualHost container.
9 # The first VirtualHost section is used for all requests that do not
10 # match a ServerName or ServerAlias in any <VirtualHost> block.
11 #
12 <VirtualHost *:80>
13 ServerAdmin webmaster@dummy-host.leader89
14 DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89"
15 ServerName dummy-host.leader89
16 ServerAlias www.dummy-host.leader89
17 ErrorLog "logs/dummy-host.leader89-error.log"
18 CustomLog "logs/dummy-host.leader89-access.log" common
19 </VirtualHost>
20
21 <VirtualHost *:80>
22 ServerAdmin webmaster@dummy-host2.leader89
23 DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89"
24 ServerName dummy-host2.leader89
25 ErrorLog "logs/dummy-host2.leader89-error.log"
26 CustomLog "logs/dummy-host2.leader89-access.log" common
27 </VirtualHost>
View Code

1 <Directory "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89">
2 Options Indexes FollowSymLinks
3 AllowOverride all
4 Order Allow,Deny
5 Allow from all
6 </Directory>
7 <Directory "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89">
8 Options Indexes FollowSymLinks
9 AllowOverride all
10 Order Allow,Deny
11 Allow from all
12 </Directory>
View Code

1 #LoadModule proxy_http_module modules/mod_proxy_http.so
2 #LoadModule proxy_connect_module modules/mod_proxy_connect.so
3 #LoadModule proxy_module modules/mod_proxy.so
4 #LoadModule proxy_module modules/mod_proxy_blancer.so


1 #LoadModule proxy_http_module modules/mod_proxy_http.so
2 #LoadModule proxy_connect_module modules/mod_proxy_connect.so
3 #LoadModule proxy_module modules/mod_proxy.so
4 #LoadModule proxy_module modules/mod_proxy_blancer.so


在httpd.conf文件最后添加以下代码:

View Code

1 ProxyPass / balancer://proxy/ #注意这里以"/"结尾
2 <Proxy balancer://proxy>
3 BalancerMember http://127.0.0.1:8080/ loadfactor=3 #BalancerMember 及其后面的URL表示要配置的后台服务器、test表示该服务器下的项目名称
4 BalancerMember http://127.0.0.1:8081/ loadfactor=1 #参数”loadfactor”表示后台服务器负载到由Apache发送请求的权值,该值默认为1
5 </Proxy>


View Code

…………
<Server port="9005" shutdown="SHUTDOWN"> #此处修改为9005,避免与tomcat1的8005冲突
…………
…………
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"/> #此处修改为8081,避免与tomcat1的8080冲突
…………
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="9009" protocol="AJP/1.3" redirectPort="8443"/> #此处修改为9009,避免与tomcat1的8009冲突。如果使用的是mod_proxy_blancer方式此处可以注释掉,如果使用的是mod_jk方式则此处必须存在
…………
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> #去掉该行注释即可实现session复制功能
…………


View Code

<%@ 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);

}

%>

<form action="test.jsp" method="POST">

名称:<input type=text size=20 name="dataName">

<br>

值:<input type=text size=20 name="dataValue">

<br>

<input type=submit>

</form>

</body>

</html>


View Code

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<display-name>TomcatDemo</display-name>

<distributable/> #一般均放在web-app结束节点上一行
</web-app>


<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>TomcatDemo</display-name> <distributable/> #一般均放在web-app结束节点上一行 </web-app>

将tomcat1下的test项目复制一份到tomcat2的webapps目录下
至此所有操作已完成

启动tomcat1、tomcat2、apache。打开浏览器,输入http://localhost/test/test.jsp回车,刷新几次即可从tomcat1与tomcat2的控制台看到负载效果。输入session即可看到session复制效果



1.3 mod_jk方案
mod_jk是比较专门针对Tomcat的方法,通过AJP协议连接Tomcat
1)需要下载mod_jk-1.2.31-httpd-2.2.3.so http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.31/mod_jk-1.2.31-httpd-  2.2.3.so包并放到Apache安装目录下的modules子目录中
2)然后配置mod_jk.conf
3)配置workers2.properties
注意:因为mod_jk2方式不被推荐,mod_jk2已经不再被更新了。因此,此处不予列举,如有需要参考者请留言,将随后贴出。

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形式来完成任务的所以你的主机性能一定要好。

2 session同步

对于tomcat的集群有两种方式,这个主要是针对session而言的。一种就是sticky模式,即黏性会话模式;另外一种就是session复制模式了。

2.1 sticky模式

利 用负载均衡器的sticky模式的方式把所有同一session的请求都发送到相同的Tomcat节点。这样不同用户的请求就被平均分配到集群 中各个tomcat节点上,实现负载均衡的能力。这样做的缺点是没有灾难恢复的能力。一旦一个节点发生故障,这个节点上所有的session信息全部丢 失;

这种方式其实是由前端balancer实现的,基本不需要webServer做任何改动(只需要修改jvmRoute="tomcat1")

同一用户同一session只和一个webServer交互,一旦这个webserver发生故障,本次session将丢失,用户不能继续使用

2.2 复制模式

利 用Tomcat session复制的机制使得所有session在所有Tomcat节点中保持一致。当一个节点修改一个session数据的时候,该节点会把这个 session的所有内容序列化,然后广播给所有其它节点。这样当下一个用户请求被负载均衡器分配到另外一个节点的时候,那个节点上有完备的 session信息可以用来服务该请求。这种做法的问题是对session哪怕有一点点修改,也要把整个sessions数据全部序列化 (serialize),还要广播给集群中所有节点,不管该节点到底需不需要这个session。这样很容易会造成大量的网络通信,导致网络阻塞。一般采 用这种方式,当Tomcat节点超过4个时候,整个集群的吞吐量就不能再上升了;

此方式是通过tomcat本身提供的功能,只需要修改server.xml文件
(1)修改Engine节点信息: <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
(2)去掉<Cluster> <\Cluster> 的注释符
(3)web.xml中增加 <distributable/>

2.3 Terracotta模式

另 一种方式就是利用开源软件Terracotta。Terracotta的基本原理是对于集群间共享的数据,当在一个节点发生变化的时 候,Terracotta只把变化的部分发送给Terracotta服务器,然后由服务器把它转发给真正需要这个数据的节点。这样对网络的压力就非常小, 各个节点也不必浪费CPU时间和内存进行大量的序列化操作。把这种集群间数据共享的机制应用在session同步上,相当于对tomcat第二种集群实现 机制进行了优化,既避免了对数据库的依赖,又能达到负载均衡和灾难恢复的效果。在对比测试中,采用Terracotta搭建Tomcat集群,节点达到8 个时候,整个集群的吞吐量还一直是线性增长的。

2.4 三种模式比较

sticky模式最大的缺点就是不支持failover,一旦某一个webServer发生故障则此节点上的session就会丢失,因此不建议使用。

复制模式可以保证个别节点发生故障不丢失session,但是复制时需要序列化数据这会影响到系统的性能。
另外性能随着服务器增加急剧下降,而且容易引起广播风暴。经测试当Tomcat节点超过4个时候,整个集群的吞吐量就不能再上升了。
需要修改server.xml和web.xml文件

使用第三方软件Terracotta进行session同步,配置对原来的web应用完全透明,原有程序不用做任何修改。。
数据不需要序列化,也不占用webServer的内存,执行效率高。

terracotta本身支持HA,增加了系统的稳定性。

Terracotta是开源的,并且可以集成在很多主流的开源软件中,如Jetty、Tomcat、Spring、Geronimo和EHCache等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: