`

Tomcat集群(使用了nginx负载)

阅读更多
前一篇文章介绍了使用nginx进行负载均衡的方式,本篇开始搭建Tomcat的负载,前端采用nginx进行负载(参考上一篇)

    对于WEB应用集群的技术实现而言,最大的难点就是如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块。要实现这一点,大体上有两种方式,一种是把所有Session数据放到一台服务器上或者数据库中,集群中的所有节点通过访问这台Session服务器来获取数据;另一种就是在集群中的所有节点间进行Session数据的同步拷贝,任何一个节点均保存了所有的Session数据。两种方式都各有优点,第一种方式简单、易于实现,但是存在着Session服务器发生故障会导致全系统不能正常工作的风险;第二种方式可靠性更高,任一节点的故障不会对整个系统对客户访问的响应产生影响,但是技术实现上更复杂一些。常见的平台或中间件如microsoftasp.net和IBM WAS都会提供对两种共享方式的支持,tomcat也是这样,但是一般采用第二种方式。

搭建Tomcat集群
1.首先对Tomcat进行配置
配置tomcat的server.xml。修改 <Engine name="Catalina" defaultHost="localhost">添加jvmRoute标示: <Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat1">
在Engine节点下,添加集群配置(各配置项的意义参考tip2):
<Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat1">
  <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"     
                        address="228.0.0.4"     <!--组播地址,参看tip1-->
                        port="45564"     
                        frequency="500"     
                        dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"     
                      address="auto"   #默认为auto,改为自己的IP   
                      port="14000"    #同一台服务器上的tomcat必须修改为不同的端口,tomcat1修改为4001,tomcat2修改为4002。注意修改配置时,要把#后面的内容删掉,要不然会启动报错
                          autoBind="100"     
                      selectorTimeout="5000"     
                      maxThreads="6"/>     
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">     
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>     
        </Sender>     
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>     
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>     
    </Channel>     
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"     
                 filter=""/>     
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>     
    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"     
                    tempDir="/tmp/war-temp/"     
                    deployDir="/tmp/war-deploy/"     
                    watchDir="/tmp/war-listen/"     
                    watchEnabled="false"/>  
   
    <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>     
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>     
  </Cluster>
...


2.启动两个Tomcat,会看到类似下面的信息
信息: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[
tcp://{192, 168, 1, 101}:14000,{192, 168, 1, 101},14000, alive=1047, securePort=
-1, UDP Port=-1, id={87 -12 -72 -127 82 63 78 112 -121 -75 125 -56 32 63 26 48 }
, payload={}, command={}, domain={}, ]
启动时看到的大致如下:


关闭其中一个时,另一个的信息如下:



3.新建测试项目
有两点注意事项:1.如果有自定义session对象的话,要继承自serializable接口;2.在web.xml中添加<distributable />标签。测试项目比较简单,只包含一个jsp页面,懒得写的童鞋可以再附件中下载测试项目(ClusterValidate.rar)。
test.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<String> e = session.getAttributeNames();
		while (e.hasMoreElements()) {
			String name = 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>



4.测试
上一篇文章中配置好的nginx,端口是8080,映射到18080和28080端口。
访问地址:
http://localhost:8080/ClusterValidate/test.jsp,多提交几次,可以看到请求到不同的tomcat了,但是sessionid是一致的。

-------------------------------------------------------------
over
-------------------------------------------------------------

Tips:
Tip1 组播地址:
IP组播地址,或称为主机组地址,由D类IP地址标记。D类IP地址的最高四位为“1110”,起范围从224.0.0.0到239.255.255.255。如前所述,部分D类地址被保留,用作永久组的地址,这段地址从224.0.0.0-224.0.0.255。比较重要的地址有:

     224.0.0.1 - 网段中所有支持组播的主机
     224.0.0.2 - 网段中所有支持组播的路由器
     224.0.0.4 - 网段中所有的DVMRP路由器
     224.0.0.5 - 所有的OSPF路由器
     224.0.0.6 - 所有的OSPF指派路由器
     224.0.0.9 - 所有RIPv2路由器
     224.0.0.13 -所有PIM路由器

    临时主机组的组播地址由网络管理员选择,他需要保证这个地址在一定的范围内没有其他的主机组在使用这个组播地址。

     第2层的组播地址(组播MAC地址)可以从IP组播地址中衍生。计算方法是把IP地址的最后23位拷贝到MAC地址的最后23位,然后把这23位前面的那一位置为0。MAC地址的前24位必须为0x01-00-5E。例如:组播IP地址224.0.1.128,16进制表示为0xE0-00-01-10,最低的23位为0x00-01-10,计算得出的MAC地址为:0x01-00-5E-00-01-10。

Tip2 Tomcat Cluster各配置项的意义
    tomcat集群各节点通过建立tcp链接来完成Session的拷贝,拷贝有同步和异步两种模式。在同步模式下,对客户端的响应必须在Session拷贝到其他节点完成后进行;异步模式无需等待Session拷贝完成就可响应。异步模式更高效,但是同步模式可靠性更高。同步异步模式由channelSendOptions参数控制,默认值是8,为异步模式,4是同步模式。在异步模式下,可以通过加上拷贝确认(Acknowledge)来提高可靠性,此时channelSendOptions设为10。
    Manager用来在节点间拷贝Session,默认使用DeltaManager,DeltaManager采用的一种all-to-all的工作方式,即集群中的节点会把Session数据向所有其他节点拷贝,而不管其他节点是否部署了当前应用。当集群中的节点数量很多并且部署着不同应用时,可以使用BackupManager,BackManager仅向部署了当前应用的节点拷贝Session。但是到目前为止BackupManager并未经过大规模测试,可靠性不及DeltaManager。
    Channel负责对tomcat集群的IO层进行配置。Membership用于发现集群中的其他节点,这里的address用的是组播地址(Multicastaddress),使用同一个组播地址和端口的多个节点同属一个子集群,因此通过自定义组播地址和端口就可将一个大的tomcat集群分成多个子集群。Receiver用于各个节点接收其他节点发送的数据,在默认配置下tomcat会从4000-4100间依次选取一个可用的端口进行接收,自定义配置时,如果多个tomcat节点在一台物理服务器上注意要使用不同的端口。Sender用于向其他节点发送数据,具体实现通过Transport配置,PooledParallelSender是从tcp连接池中获取连接,可以实现并行发送,即集群中的多个节点可以同时向其他所有节点发送数据而互不影响。Interceptor有点类似下面将要解释的Valve,起到一个阀门的作用,在数据到达目的节点前进行检测或其他操作,如TcpFailureDetector用于检测在数据的传输过程中是否发生了tcp错误。关于Channel的编程模型,请参见http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/tribes/Channel.html。
    Valve用于在节点向客户端响应前进行检测或进行某些操作,ReplicationValve就是用于用于检测当前的响应是否涉及Session数据的更新,如果是则启动Session拷贝操作,filter用于过滤请求,如客户端对图片,css,js的请求就不会涉及Session,因此不需检测,默认状态下不进行过滤,监测所有的响应。JvmRouteBinderValve会在前端的Apachemod_jk发生错误时保证同一客户端的请求发送到集群的同一个节点,tomcat官方文档并未解释如何实现这一点,而且笔者认为这一设置似乎并无多大实用性。
    Deployer用于集群的farm功能,监控应用中文件的更新,以保证集群中所有节点应用的一致性,如某个用户上传文件到集群中某个节点的应用程序目录下,Deployer会监测到这一操作并把这一文件拷贝到集群中其他节点相同应用的对应目录下以保持所有应用的一致。这是一个相当强大的功能,不过很遗憾,tomcat集群目前并不能做到这一点,开发人员正在努力实现它,这里的配置只是预留了一个接口。
   Listener用于跟踪集群中节点发出和收到的数据,也有点类似Valve的功能。

Tip3 tomcat集群工作机制
下面通过假想的一组场景来描述tomcat集群如何工作,集群采用默认配置,由t1和t2两个tomcat例程组成,场景按照时间顺序排列。
1. t1启动
     t1按照标准的tomcat启动,当Host对象被创建时,一个Cluster对象(默认配置下是SimpleTcpCluster)也同时被关联到这个Host对象。当某个应用在web.xml中设置了distributable时,Tomcat将为此应用的上下文环境创建一个DeltaManager。SimpleTcpCluster启动membership服务和Replication服务(用于建立tcp连接)。

2. t2启动(待t1启动完成后)
     首先t2会执行和t1一样的操作,然后SimpleTcpCluster会建立一个由t1和t2组成的membership。接着t2向集群中已启动的服务器即t1请求Session数据,如果t1没有响应t2的拷贝请求,t2会在60秒后time out。在Session数据拷贝完成之前t2不会接收客户端的http或mod_jk/ajp请求。

3. t1接收http请求,创建Session s1
     t1正常响应客户请求,但是在t1把结果发送回客户端时,ReplicationValve会拦截当前请求(如果filter中配置了不需拦截的请求类型,这一步就不会进行,默认配置下拦截所有请求),如果发现当前请求更新了Session,调用Replication服务建立tcp连接把Session拷贝到membership列表中的其他节点即t2,返回结果给客户端(注意,如果采用同步拷贝,必须等拷贝完成后才会返回结果,异步拷贝在数据发送到tcp连接就返回结果,不等待拷贝完成)。在拷贝时,所有保存在当前Session中的可序列化的对象都会被拷贝,而不仅仅是发生更新的部分。

4. t1崩溃
     当t1崩溃时,t2会被告知t1已从集群中退出,然后t2就会把t1从自己的membership列表中删除,发生在t2的Session更新不再往t1拷贝,同时负载均衡器会把后续的http请求全部转发给t2。在此过程中所有的Session数据不会丢失。

5. t2接收s1的请求
     t2正常响应s1的请求,因为t2保存着s1的所有数据。

6. t1重新启动
     按步骤1、2一样的操作启动,加入集群,从t2拷贝所有Session数据,拷贝完成后开放自己的http和mod_jk/ajp端口接收请求。

7. t1接收请求,s1失效
     t1继续接收来自s1的请求,把s1设置为过期。这里的过期并非因为s1处于非活动状态超过设置的时间,而是执行类似注销的操作而引起的Session失效。这时t1并非发送s1的所有数据而是一个类似s1 expired的消息,t2收到消息后也会把s1设为过期。

8. t2接收请求,创建Session s2
     和步骤3一样。

9. t1 s2过期
     对于因超时引起的Session失效t1无需通知t2,因为t2同样知道s2已经超时。因此对于tomcat集群有一点非常重要,所有节点的操作系统时间必须一致!不然会出现某个节点Session已过期而在另一节点此Session仍处于活动状态的现象。


参考资料:
http://xmong.iteye.com/blog/1288740
http://hi.baidu.com/dc_life/item/e2e03c3438ded6c82e8ec249
http://zyycaesar.iteye.com/blog/296501
http://www.iteye.com/topic/1017961
  • 大小: 260.8 KB
  • 大小: 45.9 KB
分享到:
评论

相关推荐

    Nginx+tomcat配置集群负载均衡实例

    配置Nginx+Tomcat集群负载均衡的第一步是安装Nginx和多个Tomcat实例。在多台服务器上部署Tomcat,形成一个集群,确保服务的高可用性。每台服务器上的Tomcat实例都需要配置相同的应用,以处理相同类型的请求。 接...

    nginx+tomcat集群部署与负载均衡

    ### Nginx+Tomcat集群部署与负载均衡 #### 版本信息与集群及负载均衡概念 在深入了解如何实现Nginx与Tomcat集群的部署和负载均衡之前,我们需要先了解一些基本的概念以及版本信息。 - **集群**:通常指一组计算机...

    Nginx实现tomcat与weblogic集群的负载均衡及故障处理

    本文将详细讲解如何使用Nginx作为负载均衡器,实现对Tomcat和WebLogic集群的负载均衡以及故障处理。我们将遵循由浅入深的原则,适合初学者和进阶者学习。 首先,我们来看看基础环境。系统为Redhat7.5,JDK版本为1.8...

    Tomcat集群-负载平衡

    【标题】:Tomcat集群-负载平衡 在Java Web应用开发中,Apache Tomcat作为一款广泛应用的开源Servlet容器,常被用于部署和运行Java EE应用。然而,单一的Tomcat服务器可能无法满足高并发、高可用性和高可扩展性的...

    nginx_tomcat8_redis负载均衡demo

    在这个“nginx_tomcat8_redis负载均衡demo”中,我们将探讨如何利用Nginx作为反向代理服务器,Tomcat作为应用服务器集群,以及Redis作为会话持久化存储,构建一个高效且可扩展的负载均衡解决方案。 首先,Nginx是一...

    tomcat7+nginx+memcached 配置tomcat 集群以及负载均衡

    在构建高性能、高可用性的Web应用系统时,配置Tomcat集群和负载均衡是至关重要的步骤。本主题将详细讲解如何利用Tomcat 7、Nginx和Memcached来实现这一目标,同时关注session共享和Kryo序列化技术。 首先,Tomcat 7...

    Nginx+tomcat配置集群负载均衡

    然后,对于**Tomcat集群**,你需要在每个Tomcat实例上配置相同的Context,以便处理相同的应用。这可以通过在`server.xml`文件中的`Host`元素中定义`appBase`和`unpackWARs`属性来实现: ```xml &lt;!-- ... --&gt; ```...

    Nginx 集群 tomcat session 共享配置有源码

    为解决这个问题,我们可以利用Redis作为中央session存储,实现Nginx和Tomcat集群间的session共享。 首先,让我们理解Nginx、Tomcat和Redis的角色: 1. Nginx:作为前端反向代理服务器,负责接收用户的请求,并根据...

    Nginx与tomcat 负载均衡

    Nginx与Tomcat的负载均衡是指通过Nginx服务器来实现Tomcat集群的负载均衡,以提高系统的高性能和可扩展性。下面是实现负载均衡的详细步骤和知识点: 一、环境准备 * Nginx 1.8.0 * Apache Tomcat 6.0.33 二、目标...

    Tomcat服务器集群和负载均衡

    2. **配置通信机制**:Tomcat集群中的节点需要相互通信,这通常通过两种方式实现:共享内存(适用于同一台物理机上的多个Tomcat实例)和基于网络的通信(如JMS,适用于跨网络的节点)。 3. **共享session**:为了...

    nginx+tomcat负载、集群简单搭建

    ### Nginx+Tomcat 负载均衡与集群简单搭建 #### 一、概述 在互联网技术领域中,随着用户访问量的增加,单一服务器往往难以满足需求,因此需要通过负载均衡和集群技术来提高系统的稳定性和可用性。本文将详细介绍...

    tomcat+nginx集群

    在集群环境中,多个Tomcat实例可以并行运行,通过Nginx进行负载均衡,提高服务的响应能力和容错性。 集群部署时,Nginx通常配置为反向代理服务器,它接收来自Internet的请求,然后将这些请求转发到后端的Tomcat实例...

    Nginx+Tomcat负载均衡企业实战.docx

    本文档主要介绍了 Nginx+Tomcat 负载均衡的企业实战,涵盖了从0开始构建 Nginx WEB 平台、Tomcat WEB 集群、代码发布、Nginx 负载均衡 Tomcat 集群、动静分离、Rewrite 实战等方面的内容。 一、从 0 开始构建 Nginx...

    Nginx和Tomcat集群环境部署

    ### Nginx与Tomcat集群环境部署详解 #### 一、背景介绍 随着互联网应用规模的不断增大,单个服务器已经难以满足日益增长的访问需求。为了提高系统的可用性和扩展性,采用集群技术来实现负载均衡和服务冗余变得至关...

    redis+tomcat+nginx负载均衡配置

    在构建高性能、高可用性的Web服务时,"redis+tomcat+nginx负载均衡配置"是一个常见且有效的架构模式。这个组合充分利用了各个组件的优势,确保系统稳定、响应快速,并能够处理大量的并发请求。以下是关于这个配置的...

    Nginx+KeepAlived+Tomcat负载架构

    ### Nginx+KeepAlived+Tomcat负载架构详解 #### 一、概述 随着互联网应用的日益增多,单一服务器已经难以满足高并发、高可用性的需求。因此,越来越多的企业开始采用集群技术来提高系统的稳定性和扩展性。本文将...

    Redis+nginx集群部署

    在Tomcat集群中,每个请求可能被分发到不同的服务器,为了保持会话状态的一致性,我们可以使用Redis来存储和同步Session。 4. **Session共享**:在分布式环境中,Session共享是通过在所有服务器之间同步Session数据...

    tomcat7.0.5+nginx负载均衡配置

    `Nginx`负责前端的静态资源处理和反向代理,将动态请求转发到`Tomcat`集群,这样既能充分利用硬件资源,又可以提高系统的响应速度和容错能力。 在提供的压缩包文件中,可能包含了配置示例,如`nginx.conf`和`server...

Global site tag (gtag.js) - Google Analytics