Tomcat负载均衡原理详解及配置

结构图

使用Tomcat的童鞋们注意了。为了增长tomcat的性能和稳定性,咱们通常采用balance和session同步机制。 下图列出了咱们经常使用也是最简单的解决方案。 html

说明

1 balance

1.1 mod_proxy方式

  mod_proxy是一种分工合做的的形式,经过主服务器跳转到各台主机负责不一样的任务而实现任务分工,这种形式不能实现负载均衡,只能提供主服务器的访问跳转
  修改apache的httpd.conf文件配置

打开httpd.conf文件,取消下面四行的注释,用以打开代理所需的.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  #Include conf/extra/httpd-vhosts.conf

打开文件conf\extra\httpd-vhosts.conf,能够看到以下代码: java

复制代码
 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 >
复制代码

根据须要更改<VirtualHost>节点内的参数。 web

说明:NameVirtualHost *:80和<VirtualHost *:80>中 的*为当前服务器IP,若是有固定IP能够用IP把*替换掉,我这里使用的是动态IP,因此用*,我看apache帮助文档的时候,一直认为这里的*为对 应的域名,这个想法应该是错误的,由于我填上域名的时候一直没有设置成功。ServerName这个填域名,DocumentRoot填 ServerName上域名对应的根目录。

注: 数据库

若是访问域名出现403权限错误,且对应的文件夹everyone的权限都是所有控制,则问题出在httpd.conf上。 
编辑httpd.conf,找到DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"这项,这是默认根目录路径,可是要更改的不是这个,一直往下找,找到<Directory />节点,而后在节点结束后加上:
复制代码
 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 >
复制代码

这里的"C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89"和"C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89"为前面VirtualHost里的路径。 
保存httpd.conf和httpd-vhosts.conf,而后重启Apache。 
然 后访问dummy-host.leader89打开的是C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89目录,
访问dummy-host2.leader89的是C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89目录,
实现了单IP多域名多站点的功能。 apache

1.2 mod_proxy_blancer方式

  mod_proxy_balancer是mod_proxy的扩展,提供负载平衡支持,经过mod_proxy_balancer.so包实现负载平衡,公司生产服务器暂时就采用这种方式。
  修改apache的httpd.conf文件配置

打开httpd.conf文件,取消下面四行的注释,用以打开代理所需的.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文件最后添加如下代码: tomcat

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

将下载的tomcat压缩包解压两份,分别命名为tomcat一、tomcat2。修改tomcat2中conf/server.xml中部分端口号(由于我在本机作测试,因此为了解决端口号被占用的问题修改tomcat2的端口号,使tomcat1与tomcat2可以同时启动,实现多服务器;若是有多台PC服务器可没必要修改),修改内容以下: 服务器

复制代码
………… <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复制功能 …………
复制代码

1)轮询均衡策略的配置 网络

ProxyPass / balancer://proxy/ <Proxy balancer://proxy>  BalancerMember http://127.0.0.1:8080/  BalancerMember http://127.0.0.1:8081/ </Proxy> 实现负载均衡的原理以下:

假设Apache接收到http://localhost/test请求,因为该请求知足ProxyPass条件(其URL前缀为“/"),该请求会 被分发到后台某一个BalancerMember,譬如,该请求可能会转发到http://127.0.0.1:8080/进行处理?当第二 个知足条件的URL请求过来时,该请求可能会被分发到另一台BalancerMember,譬如,可能会转发到http://127.0.0.1:8081/如此循环反复,便实现了负载均衡的机制?

2)按权重分配均衡策略的配置

ProxyPass / balancer://proxy/ <Proxy balancer://proxy>  BalancerMember http://127.0.0.1:8080/ loadfactor=3  BalancerMember http://127.0.0.1:8081/ loadfactor=1 </Proxy>

参数"loadfactor"表示后台服务器负载到由Apache发送请求的权值,该值默认为1,能够将该值设置为1到100之间的任何值?以上面 的配置为例,介绍如何实现按权重分配的负载均衡,现假设Apache收到http://myserver/test 4次这样的请求,该请求分别被负载到后台 服务器,则有3次连续的这样请求被负载到BalancerMember为http://127.0.0.1:8080/的服务器,有1次这样的请求被 负载BalancerMember为http://127.0.0.1:8081/后台服务器?实现了按照权重连续分配的均衡策略?

3)权重请求响应负载均衡策略的配置

ProxyPass / balancer://proxy/ lbmethod=bytraffic <Proxy balancer://proxy>  BalancerMember http://127.0.0.1:8080/ loadfactor=3  BalancerMember http://127.0.0.1:8081/ loadfactor=1 </Proxy>

参数“lbmethod=bytraffic"表示后台服务器负载请求和响应的字节数,处理字节数的多少是以权值的方式来表示的? “loadfactor"表示后台服务器处理负载请求和响应字节数的权值,该值默认为1,能够将该值设置在1到100的任何值?根据以上配置是这么进行均 衡负载的,假设Apache接收到http://myserver/test请求,将请求转发给后台服务器,若是BalancerMember为http://127.0.0.1:8080/后台服务器负载到这个请求,那么它处理请求和响应的字节数是BalancerMember为http://127.0.0.1:8081/服务器的3倍(回想(2)均衡配置,(2)是以请求数做为权重负载均衡的,(3)是以流量为权重负载均衡的,这是 最大的区别)?

至此配置以完成

  在tomcat1中webapps文件夹下新建test项目文件夹,test目录下新建以下页面

复制代码
<%@ 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>
复制代码

如需session复制功能此步骤为必须操做

  打开项目的WEB-INF下的web.xml在</web-app>内添加<distributable/>标签,若是没有则手动创建目录结构

复制代码
<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目录下
至此全部操做已完成 

启动tomcat一、tomcat二、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等。
相关文章
相关标签/搜索