第一部分
原文地址:http://www.onjava.com/pub/a/onjava/2004/11/24/replication1.html
Tomcat 5服务器为集群和SESSION复制提供了集成的支持。本系列的第一篇文章将为大家提供SESSION持久性以及TOMCAT集群中SESSION复制的 内在工作机制一个概要认识。我将会讨论SESSION复制在TOMCAT5中是怎样进行的以及跨越多集群节点的SESSION持久性的复制机制。在第2部 分,我会详细讨论一个带有SESSION复制功能的TOMCAT集群的安装例子,并且比较不同的复制情形。
集群
传统独立服务器(非集群的)不提供任何失效无缝转移以及负载平衡能力。当服务器失败的时候,就无法获取整个网站的内容,除非服务器被重新唤起。由于服务器失效,任何存储在服务器内存中的SESSION都会丢失,用户必须重新登陆并且输入所有由于服务器失效丢失的数据。
不 同的是,作为集群一部分的服务器则提供了可测性以及失效无缝转移能力。一个集群就是一组同步运行并且协同工作,能提供高可靠性,高稳定性以及高可测性的多 服务器例程。服务端集群对客户端表现出来似乎就是一个单独的服务器例程。从客户端的视角来看,集群的客户端和单独的服务器没多大不同,但是他们通过提供实 效无缝转移和SESSION复制做到了不间断服务以及SESSION数据持久性。
集群中的服务器通讯
集群中的应用程序服务器通过诸如IP多点传送(IP multicast)和IP sockets这样的技术和其他服务器共享信息
●IP多点传送:主要用于1对多的服务器通讯,通过广播服务和 heartbeats消息的可用来显示服务器的有效
●IP sockets:主要用于在集群的服务器例程中进行P2P服务器通讯
使用ip多点传送进行一对多通讯
TOMCAT 服务器使用IP多点传送在集群中的服务器例程间进行一对多的通讯,IP多点传送是一种能够让多服务器向指定IP地址和端口号进行订阅并且监听消息的广播技 术(多点传送IP地址范围从224.0.0.0 到239.255.255.255)。在集群中的每个服务器都使用多点传送广播特定的 heartbeat消息,通过监视这些 heartbeat消息,在集群中的服务器例程判断什么时候服务器例程失效。在服务器通讯中使用IP多点传送的一个缺点是他不能保证这些消息被确实接收到 了。例如,一个应用持续的本地多点传送缓存满了,就不能写入新的多点传送消息,等消息过了之后该应用程序就没有被通知到。
使用ip Sockets进行服务器通讯
IP sockets 同样也通过了一套在集群中的服务器间进行发送消息和数据的机制。服务器例程使用IP sockets 在集群节点间进行HTTP SESSION状态的复制。正确的SOKET配制对于集群的性能是至关重要的,基于SOCKET的通讯的效率取决于SOCKET的实现类别(例如:系统使 用本地的或者纯JAVA SOCKET读取器实现),如果服务器使用纯JAVA SOCKET读取器则要看服务器例程是否注册使用了足够的SOCKET读取器线程。
如果想要有最佳的SOCKET性能,系统应该注册使用 本地的SOCEKT而不是纯JAVA实现。这是因为相对于基于JAVA的SOCKET实现,本地SOCKET消耗更少的系统资源。虽然SOCKET读取器 的JAVA实现是P2P通信中一种可靠而且可移动的方法,可是他不能为集群中的重型SOCKET使用提供最好的性能。当判断从SOCKET是否有数据读取 的时候本地SOCKET读取器使用了更有效率的方法。使用本地SOCKET读取器实现,读取器线程不需要去统计静止的SOCKET:他们仅仅为活动的 SOCKET服务,并且在一个给定的SOCKET开始活跃起来时他们可以立刻捕捉到。而使用纯JAVA SOCKET读取器,线程必须动态的统计所有打开的SOCKET,判断他们是否包含可读取的数据。
换句话说,SOCKET读取器总是忙于统计SOCKET,即使这些SOCKET没有数据可读。这些本不应该的系统开销降低了性能。
TOMCAT 5中的集群
虽 然在TOMCAT5的早些版本中也有集群的功能,但是在稍后的版本中(5。0。19或者更高),集群变的更加模块组件化。在 server.xml 中集群元素已经被重构,这样我们可以替换集群的不同部分而不会影响其他元素。例如,当前配置中把成员服务设置为多点传送发现。这里可以轻易地把成员服务修 改替换为使用TCP或者 Unicast ,而不会改变集类逻辑的其他部分。
其他一些集群元素,例如SESSION管理器,复制发送端,复制接受端也可以被自定义的实现取代而不影响集群配置的其他部分。同样,在TOMCAT集群中的任何服务器组件可以使用集类API向集群中的所有成员发送消息。
SESSION复制
服 务器集群通常操纵两种SESSION: sticky sessions和 replicated sessions 。sticky sessions就是存在单机服务器中的接受网络请求的SESSION,其他集群成员对该服务器的SESSION状态完全不清楚,如果存有SESSION 的服务器失败的话,用户必须再次登陆网站,重新输入所有存储在SESSION中的数据。
另一种SESSION类型是,在一台服务器中 SESSION状态被复制到集群中的其他所有服务器上,无论何时,只要SESSION 被改变,SESSION数据都要重新被复制。这就是 replicated session 。 sticky 和 replicated sessions都有他们的优缺点, Sticky sessions简单而又容易操作,因为我们不必复制任何SESSION数据到其他服务器上。这样就会减少系统消耗,提高性能。但是如果服务器失败,所有 存储在该服务器内存中的SESSION数据也同样会消失。如果SESSION数据没有被复制到其他服务器,这些SESSION就完全丢失了。当我们在进行 一个查询事务当中的时候,丢失所有已经输入的数据,就会导致很多问题。
为了支持 JSP HTTP session 状态的自动失效无缝转移,TOMCAT服务器复制了在内存中的SESSION状态。这是通过复制存储在一台服务器上的SESSION数据到集群中其他成员上防止数据丢失以及允许失效无缝转移。
对象的状态管理
通过在服务器上的保存状态可以区分出4种对象:
● 无状态:一个无状态对象在调用的时候不会在内存中保存任何状态,因为客户端和服务器端没必要保存任何有关对方的信息。在这种情况下,客户端会在每次请求服 务器时都会发送数据给服务器。SESSION状态被在客户端和服务器端来回发送。这种方法不总是可行和理想的,特别是当传输的数据比较大或者一些安全信息 我们不想保存在客户端的时候;
●会话:一个会话对象在一个SESSION中只被用于特定的某个客户端。在SESSION中,他可以为所有来自该客 户端的请求服务,并且仅仅是这个客户端的请求。贯穿一个SESSION,两个请求间的状态信息必须保存。会话服务通常在内存中保存短暂的状态,当在服务器 失败的时候可能会丢失。SESSION状态通常被保存在请求间的服务器的内存中。为了清空内存,SESSION状态也可以被从内存中释放(就像在一个对象 CACHE)。在该对象中,性能和可量测性都有待提高,因为更新并不是被单独的写到磁盘上,并且服务器失败的时候数据也没办法抢救。
●缓存:缓存对象在内存中保存状态,并且使用这个去处理从多客户端来的请求。缓存服务的实现可以扩展到他们把缓存的是数据备份保存在后端存储器中(通常是一个关系数据库)。
● 独立的:一个独立的对象在一个时间内只活跃在集群中的一台服务器上,处理来自多客户端的请求。他通常由那些私有的,持久的,在内存中缓寸的数据支持。他同 样也在内存中保持短暂状态,在服务器失败的时候要重建或者丢失。当失败的时候,独立对象必须在同一个服务器上重起或者移植到另一台服务器上。
(来源: "Using WebLogic Server Clusters")
SESSION复制的设计考虑事项
网络考虑事项
把集群的多点传送地址和其他应用程序隔离是至关重要的。我们不希望集群配置或者网络布局干扰到多点传送服务器通信。和其他应用程序共享集群多点传送地址将迫使集群的服务器例程处理不应该的消息,消耗系统内存。
共享多点传送地址可能也会使IP多点传送缓冲过载,延迟服务器 heartbeat 消息传输。这样的延迟可能导致一个服务器例程被标识为死亡,仅仅因为他的 heartbeat 消息没有被及时接收。
编程考虑事项
除了上面提到的网络相关因素,还有些和我们写 J2EE 网络应用程序有关的设计考虑也会影响SESSION复制。以下列出了一些编程方面的考虑:
●SESSION数据必须被序列化:为了支持HTTP session 状态的内存内复制,所有的 servlet 和 JSP session 数据必须被序列化,对象中的每个域都必须被序列化,这样对象被可靠的序列化。
● 把应用程序设计为幂等的:幂等的的意思就是一个操做不会修改状态信息,并且每次操作的时候都返回同样的结果(换句话说就是:做多次和做一次的效果是一样 的),通常,WEB请求,特别是 HTML forms 都被发送多次(当用户点击发送按纽两次,重载页面多次),导致多次HTTP请求。设计SERVLET和其他WEB对象为 幂等的,可以容忍多次请求。详细可以去参考设计模式“Synchronized Token ”和“Idempotent Receiver ”关于怎样设计幂等的的应用程序。
●在BUSINESS层存储状态:会话状态应该使用有状态的SESSION BEANS存储在EJB层,而不是存储在WEB层的HttpSession。因为企业应用程序要支持各种类型客户端(WEB客户端,JAVA应用程序,其 他EJB),存储数据在WEB层会导致在客户端的双数据存储。因此,有状态的SESSION BEAN在这些情况下就被用于存储SESSION状态。无状态的SESSION BEAN要为每次的调用重构造会话状态。这些状态可能必须从数据库中恢复的数据中重编译。这些缺点失去了使用无状态SESSION BEAN去提高性能和可测量性的目的,严重的减低了性能。
●序列化系统消耗:序列化SESSION数据在复制SESSION状态的时候回会些系统 消耗。随着序列化对象大小的增长消耗也越多。最好是保持SESSION容量适当的小。但是如果你必须在SESSION中创建非常大的对象,最好测试下你的 servlets 性能以保证性能是可接受的以及SESSION的复制时间是适当的。
●用户SESSION:判断在集群中每个TOMCAT服务器 例程所控制的并发用户SESSION最大数是很重要的。为了控制更多并发SESSION,我们应该为提高效率添加更多内存。最大并发客户端数,以及每个客 户端请求的频率在决定SESSION复制对服务器的性能影响方面也是个因素。
Tomcat 5中的SESSION复制
在 版本5之前,TOMCAT服务器只支持sticky sessions (使用mod_jk模块进行负载平衡)。如果我们需要SESSION复制,必须依靠第3方软件例如JavaGroups 去实现。 Tomcat 5服务器带有SESSION复制功能。和集群特征类似,只要修改 server.xml 注册文件就能实现SESSION复制。
Martin Fowler 在他的书《 Enterprise Patterns》中谈到三个SESSION状态持久性模式,这些模式包括:
1.客户端SESSION状态:在客户端存储SESSION状态
2.服务端SESSION状态:在一个序列化的FORM中保持SESSION状态到一个服务器系统上。
3.数据库SESSION状态:当在数据库中提交数据的时候存储SESSION数据。
TOMCAT支持以下三种SESSION持久性类型:
1. 内存复制:在JVM内存中复制SESSION状态,使用TOMCAT 5安装带的SimpleTcpCluster 和 SimpleTcpClusterManager 类。这些类在包org.apache.catalina.cluster中,是server/lib/catalina-cluster.jar的一部 分。
2.数据库持久性:在这种类型中,SESSION状态保存在一个关系数据库中,服务器使用JDBCManager类从数据库中获取 SESSION信息。这个类在包org.apache.catalina.session.JDBCStore中,是catalina.jar的一部分。
3.基于文件的持久性:这里使用类PersistenceManager把SESSION状态保存到一个文件系统。这个类在包org.apache.catalina.session.FileStore中,是catalina.jar的一部分。
TOMCAT集群元素以及SESSION复制
这章简要介绍一下组成TOMCAT集群的元素以及SESSION复制。
集群:
这个是集群中的主要元素, SimpleTcpCluster类代表这个元素。他使用在server.xml中指定的管理类为所有可分配的web contexts生成ClusterManager。
集群管理器
这 个类关注跨越集群中所有节点间的SESSION数据复制。所有在web.xml文件中指定了distributable标记的WEB应用程序都会有 SESSION复制。集群管理器作为集群元素的managerClassName属性在server.xml中指定。集群管理器的代码主要被设计用来分离 集群中的元素。我们所要做的就是写一个SESSION管理器类去实现ClusterManager接口。这样能让我们灵活的使用客户集群管理器而不会影响 到集群中的其他元素。这里有两个复制算法。SimpleTcpReplicationManager每次复制全部的SESSION,而 DeltaManager只复制SESSION增量。
最简单的复制管理器在每次HTTP请求都复制所有的SESSION。在SESSION较小的时候这样是很有用的,我们可以只用以下代码:
这 里,我们不需要特别调用session.setAttribute() 或者 removeAttribute方法去复制SESSION变化。对于每次HTTP请求,在SESSION中的所有属性都被复制。可以使用一个叫做 useDirtyFlag的属性去最优化SESSION被复制的次数。如果这个标记被设为真,我们必须调用setAttribute()方法去获取被复制 的SESSION变化。如果被设为假,每次请求后SESSION都被复制。
SimpleTcpReplicationManager生成ReplicatedSession执行SESSION复制工作。
提 供增量管理器仅仅是为了性能的考虑。它在每次请求的时候都做一次复制。同时他也调用监听器,所以如果我们调用 session.setAttribute(),那么在其他服务器上的监听器就会被调用。DeltaManager生成DeltaSession执行 SESSION复制。
成员
成员的建立通过由TOMCAT例程在同样的多点传送IP和端口发送广播消息。广播的消息包括服务器的IP地址和TCP监听端口(默认IP地址为228.0.0.4)。
如果在给定的时间框架内一个例程没有接收到消息(由集群配置中的mcastDropTime参数指定),成员被认为死亡。这个元素由McastService类表示。
由mcastXXX开始的属性用于成员资格多点传送PING。以下表格列出了用于IP多点传送服务器通讯的属性。
发送端
这 个元素由ReplicationTransmitter类代表。当多点传送广播消息被接收到,成员被添加到机群。在下次复制请求前,发送例程将使用主机和 端口信息建立一个TCP SOCKET。使用这些SOCKET发送序列化的数据。在TOMCAT 5中有3种不同的方法操纵SESSION复制:异步,同步,池复制模式。以下部分解释了这些模式怎样工作,以及他们将被使用在什么情况下。
●异 步:在这种复制模式中,每个集群节点都有一个单线程扮演SESSION数据传送器。这里,请求线程会把复制请求发送到一个队列,然后返回给客户端。在失效 无缝转移前,如果我们拥有sticky sessions,就应该使用异步复制。这里复制时间不是至关重要的,但是请求时间却是。在异步复制期间,请求在数据被复制完之前就返回了。这种复制模式 缩短了请求时间。当每个请求被分的更开这种模式是很有用的。(例如,在WEB请求间有更长的延迟)。同样,如果我们不关心SESSION是否完成复制这个 也很有用,当SESSION很较小时, SESSION复制时间也更短。
●同步:在这种模式中,一个单线程执行了HTTP请求和数据复制。集群中所有节点都接收到SESSION数据后线程才返回。同步意味被被复制的数据通过一 个单SOCKET发送。由于使用一个单线程,同步模式可能会是簇性能的一个潜在的瓶颈。这种复制模式保证了在请求返回前SESSION 已 经被复制。
●池:TOMCAT5 在使用池复制模式进行SESSION复制的方法上提供了很大的改进。池模式基本上是同步模式的一个扩展版本。他基于的一个原则是:划分服务到多例程,每个 例程处理不同的SESSION数据片段。同时对接收服务器开放多SOCKET进行发送SESSION信息。这种方法比通过单SOCKET发送所有东西更 快。因此,使用一个SOCKET池同步复制SESSION。直到所有SESSION数据都复制完请求才返回。为了有效使用这种模式要增加TCP线程。由于 使用多SOCKET,池模式使得集群性能的逐步提高以及更好的可测性。同样这种模式也是最安全的配置,因为它有足够数量的SOCKET在理想的时间内发送 所有的SESSION数据到其他节点上。而使用单SOCKET,SESSION数据在通过集群时可能丢失或者只是部分传输。
接收端
这个集群元素由类ReplicationListener表示。在集群配置中以tcpXXX开始的属性用于TCP SESSION复制。以下表格列出了用于配置服务器复制中基于SOCEKT服务器通讯的属性。
复制值
复制值用于判断哪些HTTP请求需要被复制。由于我们不经常复制静态内容(例如HTML和JavaS cript, stylesheets,图像文件),我们可以使用复制值元素过滤掉静态内容。这个值可以用于找出什么时候请求已完成以及初始化复制。
部署器
部 署器元素可以用于部署集群范围的应用程序。通常,部署只部署/解除部署簇内的工作成员。所以在损坏的节点在启动时没有WARS的复制。当 watchEnabled="true"时配置器为WAR文件监视一个目录(watchDir)。当添加一个新的WAR文件时,WAR被部署到本地例程, 然后被部署到集群中的其他例程。当一个WAR文件从watchDir删除,这个WAR被从本地和集群范围内解除部署。
所有在TOMCAT集群结构中的元素以及他们的层次关系都在列在图1中
图 1. Tomcat 集群等级结构图。单击看原图。
TOMCAT中SESSION复制是怎么工作的
以下部分简要解释当TOMCAT服务器启动或则关闭时集群节点怎样分享SESSION信息,详细信息可参考Tomcat 5 Clustering文挡。
TC-01:集群中第一个节点
TC-02:集群中第2个节点
● 服务器启动:TC-01使用标准服务器启动队列启动。当主机对象被创建,即有一个集群对象和它相关联。当contexts被解析,如果 distributable已经在web.xml中指定,那么TOMCAT为WEB CONTEXT创建SESSION管理器(SimpleTcpReplicationManager 取代StandardManager)。集群将会启动一个成员服务(成员的一个例程)和一个复制服务。
当TC-02启动,他也遵循第一个成员 (TC-01)同样的队列但是有一个不同。集群被启动并且创建一个成员关系(TC-01,TC-02)。TC-02将向TC-01请求SESSION状 态。TC-01回应该请求,在TC-2开始监听HTTP请求前,TC-01发送状态给TC-02。如果TC-01不回应,TC-02将在60秒后进入中止 状态并且发布一个日志入口。SESSIONG 状态发送给所有在web.xml中指定了distributable的WEB应用程序。
●创建SESSION:当TC-01接收到请求,一个SESSION(S1)被创建,处理进入TC-01的请求和没有SESSION复制时是一样的。当请 求完成时会有以下事件:ReplicationValve将会在回应返回给用户前截取请求。这里,会发现SESSION已经被改变,使用TCP复制 SESSION到TC-02。
●服务器储运损耗/关闭:当在集群中的一台服务器失败,维护损坏或者系统升级,其他节点会受到第一个节点已经脱离集 群的通知。TC-02从他的成员资格列删除TC-01,并且TC-02在也不会收到有关TC-01任何变动的通知。负载平衡将会移至TC-02,所有的 SESSION由TC-02控制。
当TC-01开始恢复,他再次遵循在服务器开始阶段描述的启动队列。加入到簇中并且以所有SESSIONG的当 前状态和TC-02通讯。一旦接收到 SESSIONG状态,也就完成了加载然后打开它的HTTP/ mod_jk端口。所以,要等到从TC-2接受到SESSION状态TC-01才能发送请求。
●SESSION终止:如果在第一个节点的一个 SESSION已经无效或则由于过期终止,无效请求将被截取,SESSION会被同其他无效SESSION放在一个队列中。当请求完成,服务器发送 SESSIONG终止消息给TC-02而不是发送已经改变的SESSION,TC-02同样也会把该SESSION置无效。我们可以从服务器控制台看到 SESSIONG无效的消息。无效SESSION在集群中将不会被复制,直到其他请求传出系统并且检查无效队列。
结束语
在 这篇文章中,我谈了有关在集群环境中的SESSION复制,以及编写要求在内存内SESSIONG复制的J2EE应用程序时的一些设计注意事项。我同时也 讨论了在TOMCAT 5容器中被指定来进行SESSIONG复制的簇元素。在这个系列的第2部分,我们将会看看怎样使用不同的SESSIONG 管理器和复制模式在TOMCAT集群中配置SESSIONG复制。
Srini Penchikala 是一个在Flagstar 银行工作的信息系统主题专家。
第二部分
集群安装
为了在TOMCAT5容器中SESSION复制可用,必须完成以下步骤:
● 为了集群能够工作,你必须使用你系统上的多点传送可使用
● 为了有些使用SESSION复制,所有TOMCAT例程必须同样配置。这意味着WEB应用程序必须统一的部署在集群中的每台服务器上。这些配置同样简化了集群管理,维护和发现维修故障的任务。
● 在server.xml未注释的Cluster 和Valve (ReplicationValve) 元素。起用server.xm中的CLUSTER元素意味着所有WEB CONTEXT的SESSION管理器将会改变。因此 当运行一个集群的时候,你应该确保只有一个需要被集成WEB应用程序并且移除其他的。
● 如果服务器例程运行在同样的机器上,应该确保每个例程的tcpListenPort属性是一致的。
● 确保web.xml有distributable属性
● 所有的SESSION属性必须实现java.io.Serializable接口
范例集群安装有两个TOMCAT例程和一个负载平衡用于分配服务器间的请求。所有三个服务器都运行在一个单独的机器上,以下表格列出了集群和负载平衡上的配置参数。
编辑注解:以上Web App Directory中的值为了适应排版而换行了。在你的部署中,每个值应该是单一而完整的一行
注意:不要设置tcpListenAddress为127.0.0.1,因为127用于回环地址,在SESSION复制期间可能会出现问题。
负载平衡器安装
TOMCAT服务器不提供失效转移能力用于当一个集群接点失效的时候重定向任何引入的请求到下一个可用的服务器上。所以我使用一个分开的负载平衡器去管 理WEB请求的负载平衡。有一些流行的负载平衡器例如Apache/mod_jk, Balance, 和 Pen。我在范例集群安装中使用Pen作为负载平衡器。
Pen是一个简单的,基于TCP协议,例如HTTP或者SMTP的负载平 衡器。他允许多个服务器对外表现为一个服务器,并且自动检测关闭的服务器,在可用的服务器间分配客户断。他提供了负载平衡和失效转移能力。Pen易于安装 以及配置,非常容易使用和运行在Windows和UNIX操做系统上。范例配置使用round-robin负载平衡算法用于在集群节点间分配负载平衡
运行负载平衡器的命令如下:
pen -r -a -f -d localhost:8080 192.168.0.10:9080 192.168.0.20:10080
以下是用于启动负载平衡器的每个命令行参数的解释
-r: 使用round robin负载平衡
-a: 打印来回发送的ASCII格式的数据
-f: 保持在前台
-d: 起用DEBUG模式
想要知道更多用于启动PEN的参数细节,请访问PEN网站
图表1展示了两个集群节点,一个负载平衡器,仪器层,以及测试客户端的拓扑图
图文
Figure 1. Cluster setup diagram
测试安装
我创建了一个叫做clusterapp的WEB应用程序来验证集群安装以及SESSION复制原理。为了测试真实的SESSION复制,我写了一个叫做 SessionReplicationClient的简单JAVA客户端用语测试从一个服务器拷贝SESSION数据到另外一个服务器的需要的时间。这个 客户端使用Jakarta Commons HttpClient况架去创建和操作HTTP SESSION并且调用TOMCAT服务器上的一个SERVLET。用于测试SESSION复制的机器软硬件配置如下:
● CPU: HP Pavilion Pentium III 800MHz
● Memory: 512MB RAM
● Hard disk: 40GB
● Operating system: Windows 2000 server
● JDK version: 1.4.2_05 (Note: JDK 1.4 or later version is required to use clustering and session replication)
● Tomcat version: 5.0.28
● Tools: Pen, Log4J, Eclipse, Commons HttpClient
当一个复制客户端程序运行的时候,他首先设置一个作用指令用于这样操纵SESSION(例如,添加一个新的属性到SESSION,从SESSION中移 除一个已存在的属性,或则让一个SESSION失效)。然后客户端通过在Commons HttpClient框架使用HttpClient和PostMethod类调用ReplicationServlet。基于这些SESSION命 令,servlet生成一个新的SEESION或者修改一个已经存在的SESSION并且转到一个WEB页面中瞻示SESSION细节。如果在管理 SESSION中有任何错误,则转到一个错误页面。我写了一个定制的SESSION监听类(ClusterAppSessionListener)用于跟 踪SESSION管理的细节,例如新SESSION的创建,修改或则终止已经存在的SEESION。
图表2展现了SESSION复制流程
图文
Figure 2. Session replication sequence diagram
服务器上的SESSION状态通过每个WEB请求的COOKIE跟踪,所以为了保持使用同样的SESSION,从客户端发出的请求URL必须一样。另 外,在每次请求都创建一个新的HTTP SESSION。我使用了两种类型的,基于添加到SESSION中的属性类别的测试方法去测试复制。
第一个类别有100个轻量对象(每个1K)添加到SESSION。第2个类别中,我添加了一个单一的大对象(100K)去比较基于SESSION属性大小的SESSION复制所花费的时间
以下列出了SessionReplicationClient的测试规格:
● 客户端线程数:2
● 旋环次数:1000
● 请求延迟:1000 milliseconds
● 测试范例数:1000
● SESSION属性:小(100个1K大小的对象)或则大(一个100K大小的对象)
使用指定参数运行测试客户端的命令如下:
java -Dlog4j.configuration=log4j.xml com.clusterapp.test.SessionReplicationClient 2 192.168.0.10 9080 1000 1000 lite
测试环境包括使用不同的SESSION管理器(SimpleTcpReplicationManager 或则 DeltaManager)和SESSION复制模式(同步,异步,池),以下表格列出了在TOMCAT集群中的一系列测试环境:
您正在看的JAVA教程是:Tomcat 5集群中的SESSION复制二。
想要把复制模式从池该到同步或异步,只要在server.xml文件中的SENDER标志中修改replicationMode属性值就可以了。同样,要改变SESSION管理器的类型,只要改变Cluster元素的managerClassName属性。
以下参数用于比较反应时间和SESSION复制的效率:
● 平均反映时间(ms)
● 平均请求时间(ms)
● 集群开销时间(ms)
● 复制时间(ms)
● 比率(bytes/ms)
● 比率(bytes/request)
测试结果
delta管理器和池复制模式相结合使用对与SESSION复制效率是最好的标准。同样,保持SESSION大小较小可以比复制大SESSION快2到3倍。
复制管理器
DeltaManager在SESSION复制方面更有效,因为他仅仅处理SESSION deltas而不是全部的SESSION数据。使用DeltaManager,与使用简单复制管理器比较,SESSION复制效率会提高30%(大 SESSION)到50%(小SESSION)。
复制模式
与其他两个选项(同步和异步)比较,池复制模式复制SESSION花费更好的时间。在一个复制时间内,池选项几乎是同意选项的 4倍快。但是在反应时间和集群开销时间方面,池和同步模式几乎一样,因为在同步模式里,集群在返回前不用等待SESSIONG完成复制
综述
基于SESSION复制测试的结果,我们得出结论:应该在任何可能时候使用DeltaManager。因为复制SESSION数据的开销是意义重大的, 必须确保没有在SESSION中存储太多的数据同样,添加到SESSION中的属性大小也是影响到SESSION复制时间的另一个因素。当我运行测试在 SESSION存储大对象(100K)的时候,与在SESSION中存储小对象(1K)相比较,复制时间非常高。想要最小化SESSION复制开销最好的 方法是避免调用session.setAttribute()以及把数据存储在请求对象中而不是SESSION中。这样相对更好因为当WEB请求完成的时 候请求属性会被重置。同样,如果没有商业方面的原因要在服务器存储数据,我们可以以COOKIES的形式在客户端存储数据。这种方法完全避免了使用任何 SESSIOIN的需要。
一种最小化SESSION复制时间开销的方法是限制集群中到两个或则三个服务器上的服务器例程数目。这 样当第一个服务器失败的时候第一个服务器上的SESSION数据已经被拷贝到第二个服务器上。为了保持网络畅通,集群可以分割成小块的组,每个组包括两个 或则三个服务器例程。记住,集群中的服务器越多,SESSION复制花费的时间也越多。目前TOMCAT5不支持首要/次要复制的概念。在以后发布的版本 中将会有,这样我们将可以在一个或则两个备份服务器上存储SESSION。拥有这个特性的话,TOMCAT将会为在集群环境中运行WEB服务器提供更全面 的SESSION复制方法。
在未来TOMCAT将会支持的一些属性:
● 拥有在SESSION中存在非序列化的属性的能力,集群将会忽略该属性
● 拥有复制context属性以及非序列化的相关数据的能力,例如JDBC连接池和对象CACHES。
这些特性将会使在TOMCAT集群中的SESSION复制更强壮和灵活。
I want to thank Filip Hanik for his valuable suggestions and feedback on the replication modes, session replication web application setup, and the test client sections of this article.
原文地址:http://www.onjava.com/pub/a/onjava/2004/11/24/replication1.html
Tomcat 5服务器为集群和SESSION复制提供了集成的支持。本系列的第一篇文章将为大家提供SESSION持久性以及TOMCAT集群中SESSION复制的 内在工作机制一个概要认识。我将会讨论SESSION复制在TOMCAT5中是怎样进行的以及跨越多集群节点的SESSION持久性的复制机制。在第2部 分,我会详细讨论一个带有SESSION复制功能的TOMCAT集群的安装例子,并且比较不同的复制情形。
集群
传统独立服务器(非集群的)不提供任何失效无缝转移以及负载平衡能力。当服务器失败的时候,就无法获取整个网站的内容,除非服务器被重新唤起。由于服务器失效,任何存储在服务器内存中的SESSION都会丢失,用户必须重新登陆并且输入所有由于服务器失效丢失的数据。
不 同的是,作为集群一部分的服务器则提供了可测性以及失效无缝转移能力。一个集群就是一组同步运行并且协同工作,能提供高可靠性,高稳定性以及高可测性的多 服务器例程。服务端集群对客户端表现出来似乎就是一个单独的服务器例程。从客户端的视角来看,集群的客户端和单独的服务器没多大不同,但是他们通过提供实 效无缝转移和SESSION复制做到了不间断服务以及SESSION数据持久性。
集群中的服务器通讯
集群中的应用程序服务器通过诸如IP多点传送(IP multicast)和IP sockets这样的技术和其他服务器共享信息
●IP多点传送:主要用于1对多的服务器通讯,通过广播服务和 heartbeats消息的可用来显示服务器的有效
●IP sockets:主要用于在集群的服务器例程中进行P2P服务器通讯
使用ip多点传送进行一对多通讯
TOMCAT 服务器使用IP多点传送在集群中的服务器例程间进行一对多的通讯,IP多点传送是一种能够让多服务器向指定IP地址和端口号进行订阅并且监听消息的广播技 术(多点传送IP地址范围从224.0.0.0 到239.255.255.255)。在集群中的每个服务器都使用多点传送广播特定的 heartbeat消息,通过监视这些 heartbeat消息,在集群中的服务器例程判断什么时候服务器例程失效。在服务器通讯中使用IP多点传送的一个缺点是他不能保证这些消息被确实接收到 了。例如,一个应用持续的本地多点传送缓存满了,就不能写入新的多点传送消息,等消息过了之后该应用程序就没有被通知到。
使用ip Sockets进行服务器通讯
IP sockets 同样也通过了一套在集群中的服务器间进行发送消息和数据的机制。服务器例程使用IP sockets 在集群节点间进行HTTP SESSION状态的复制。正确的SOKET配制对于集群的性能是至关重要的,基于SOCKET的通讯的效率取决于SOCKET的实现类别(例如:系统使 用本地的或者纯JAVA SOCKET读取器实现),如果服务器使用纯JAVA SOCKET读取器则要看服务器例程是否注册使用了足够的SOCKET读取器线程。
如果想要有最佳的SOCKET性能,系统应该注册使用 本地的SOCEKT而不是纯JAVA实现。这是因为相对于基于JAVA的SOCKET实现,本地SOCKET消耗更少的系统资源。虽然SOCKET读取器 的JAVA实现是P2P通信中一种可靠而且可移动的方法,可是他不能为集群中的重型SOCKET使用提供最好的性能。当判断从SOCKET是否有数据读取 的时候本地SOCKET读取器使用了更有效率的方法。使用本地SOCKET读取器实现,读取器线程不需要去统计静止的SOCKET:他们仅仅为活动的 SOCKET服务,并且在一个给定的SOCKET开始活跃起来时他们可以立刻捕捉到。而使用纯JAVA SOCKET读取器,线程必须动态的统计所有打开的SOCKET,判断他们是否包含可读取的数据。
换句话说,SOCKET读取器总是忙于统计SOCKET,即使这些SOCKET没有数据可读。这些本不应该的系统开销降低了性能。
TOMCAT 5中的集群
虽 然在TOMCAT5的早些版本中也有集群的功能,但是在稍后的版本中(5。0。19或者更高),集群变的更加模块组件化。在 server.xml 中集群元素已经被重构,这样我们可以替换集群的不同部分而不会影响其他元素。例如,当前配置中把成员服务设置为多点传送发现。这里可以轻易地把成员服务修 改替换为使用TCP或者 Unicast ,而不会改变集类逻辑的其他部分。
其他一些集群元素,例如SESSION管理器,复制发送端,复制接受端也可以被自定义的实现取代而不影响集群配置的其他部分。同样,在TOMCAT集群中的任何服务器组件可以使用集类API向集群中的所有成员发送消息。
SESSION复制
服 务器集群通常操纵两种SESSION: sticky sessions和 replicated sessions 。sticky sessions就是存在单机服务器中的接受网络请求的SESSION,其他集群成员对该服务器的SESSION状态完全不清楚,如果存有SESSION 的服务器失败的话,用户必须再次登陆网站,重新输入所有存储在SESSION中的数据。
另一种SESSION类型是,在一台服务器中 SESSION状态被复制到集群中的其他所有服务器上,无论何时,只要SESSION 被改变,SESSION数据都要重新被复制。这就是 replicated session 。 sticky 和 replicated sessions都有他们的优缺点, Sticky sessions简单而又容易操作,因为我们不必复制任何SESSION数据到其他服务器上。这样就会减少系统消耗,提高性能。但是如果服务器失败,所有 存储在该服务器内存中的SESSION数据也同样会消失。如果SESSION数据没有被复制到其他服务器,这些SESSION就完全丢失了。当我们在进行 一个查询事务当中的时候,丢失所有已经输入的数据,就会导致很多问题。
为了支持 JSP HTTP session 状态的自动失效无缝转移,TOMCAT服务器复制了在内存中的SESSION状态。这是通过复制存储在一台服务器上的SESSION数据到集群中其他成员上防止数据丢失以及允许失效无缝转移。
对象的状态管理
通过在服务器上的保存状态可以区分出4种对象:
● 无状态:一个无状态对象在调用的时候不会在内存中保存任何状态,因为客户端和服务器端没必要保存任何有关对方的信息。在这种情况下,客户端会在每次请求服 务器时都会发送数据给服务器。SESSION状态被在客户端和服务器端来回发送。这种方法不总是可行和理想的,特别是当传输的数据比较大或者一些安全信息 我们不想保存在客户端的时候;
●会话:一个会话对象在一个SESSION中只被用于特定的某个客户端。在SESSION中,他可以为所有来自该客 户端的请求服务,并且仅仅是这个客户端的请求。贯穿一个SESSION,两个请求间的状态信息必须保存。会话服务通常在内存中保存短暂的状态,当在服务器 失败的时候可能会丢失。SESSION状态通常被保存在请求间的服务器的内存中。为了清空内存,SESSION状态也可以被从内存中释放(就像在一个对象 CACHE)。在该对象中,性能和可量测性都有待提高,因为更新并不是被单独的写到磁盘上,并且服务器失败的时候数据也没办法抢救。
●缓存:缓存对象在内存中保存状态,并且使用这个去处理从多客户端来的请求。缓存服务的实现可以扩展到他们把缓存的是数据备份保存在后端存储器中(通常是一个关系数据库)。
● 独立的:一个独立的对象在一个时间内只活跃在集群中的一台服务器上,处理来自多客户端的请求。他通常由那些私有的,持久的,在内存中缓寸的数据支持。他同 样也在内存中保持短暂状态,在服务器失败的时候要重建或者丢失。当失败的时候,独立对象必须在同一个服务器上重起或者移植到另一台服务器上。
(来源: "Using WebLogic Server Clusters")
SESSION复制的设计考虑事项
网络考虑事项
把集群的多点传送地址和其他应用程序隔离是至关重要的。我们不希望集群配置或者网络布局干扰到多点传送服务器通信。和其他应用程序共享集群多点传送地址将迫使集群的服务器例程处理不应该的消息,消耗系统内存。
共享多点传送地址可能也会使IP多点传送缓冲过载,延迟服务器 heartbeat 消息传输。这样的延迟可能导致一个服务器例程被标识为死亡,仅仅因为他的 heartbeat 消息没有被及时接收。
编程考虑事项
除了上面提到的网络相关因素,还有些和我们写 J2EE 网络应用程序有关的设计考虑也会影响SESSION复制。以下列出了一些编程方面的考虑:
●SESSION数据必须被序列化:为了支持HTTP session 状态的内存内复制,所有的 servlet 和 JSP session 数据必须被序列化,对象中的每个域都必须被序列化,这样对象被可靠的序列化。
● 把应用程序设计为幂等的:幂等的的意思就是一个操做不会修改状态信息,并且每次操作的时候都返回同样的结果(换句话说就是:做多次和做一次的效果是一样 的),通常,WEB请求,特别是 HTML forms 都被发送多次(当用户点击发送按纽两次,重载页面多次),导致多次HTTP请求。设计SERVLET和其他WEB对象为 幂等的,可以容忍多次请求。详细可以去参考设计模式“Synchronized Token ”和“Idempotent Receiver ”关于怎样设计幂等的的应用程序。
●在BUSINESS层存储状态:会话状态应该使用有状态的SESSION BEANS存储在EJB层,而不是存储在WEB层的HttpSession。因为企业应用程序要支持各种类型客户端(WEB客户端,JAVA应用程序,其 他EJB),存储数据在WEB层会导致在客户端的双数据存储。因此,有状态的SESSION BEAN在这些情况下就被用于存储SESSION状态。无状态的SESSION BEAN要为每次的调用重构造会话状态。这些状态可能必须从数据库中恢复的数据中重编译。这些缺点失去了使用无状态SESSION BEAN去提高性能和可测量性的目的,严重的减低了性能。
●序列化系统消耗:序列化SESSION数据在复制SESSION状态的时候回会些系统 消耗。随着序列化对象大小的增长消耗也越多。最好是保持SESSION容量适当的小。但是如果你必须在SESSION中创建非常大的对象,最好测试下你的 servlets 性能以保证性能是可接受的以及SESSION的复制时间是适当的。
●用户SESSION:判断在集群中每个TOMCAT服务器 例程所控制的并发用户SESSION最大数是很重要的。为了控制更多并发SESSION,我们应该为提高效率添加更多内存。最大并发客户端数,以及每个客 户端请求的频率在决定SESSION复制对服务器的性能影响方面也是个因素。
Tomcat 5中的SESSION复制
在 版本5之前,TOMCAT服务器只支持sticky sessions (使用mod_jk模块进行负载平衡)。如果我们需要SESSION复制,必须依靠第3方软件例如JavaGroups 去实现。 Tomcat 5服务器带有SESSION复制功能。和集群特征类似,只要修改 server.xml 注册文件就能实现SESSION复制。
Martin Fowler 在他的书《 Enterprise Patterns》中谈到三个SESSION状态持久性模式,这些模式包括:
1.客户端SESSION状态:在客户端存储SESSION状态
2.服务端SESSION状态:在一个序列化的FORM中保持SESSION状态到一个服务器系统上。
3.数据库SESSION状态:当在数据库中提交数据的时候存储SESSION数据。
TOMCAT支持以下三种SESSION持久性类型:
1. 内存复制:在JVM内存中复制SESSION状态,使用TOMCAT 5安装带的SimpleTcpCluster 和 SimpleTcpClusterManager 类。这些类在包org.apache.catalina.cluster中,是server/lib/catalina-cluster.jar的一部 分。
2.数据库持久性:在这种类型中,SESSION状态保存在一个关系数据库中,服务器使用JDBCManager类从数据库中获取 SESSION信息。这个类在包org.apache.catalina.session.JDBCStore中,是catalina.jar的一部分。
3.基于文件的持久性:这里使用类PersistenceManager把SESSION状态保存到一个文件系统。这个类在包org.apache.catalina.session.FileStore中,是catalina.jar的一部分。
TOMCAT集群元素以及SESSION复制
这章简要介绍一下组成TOMCAT集群的元素以及SESSION复制。
集群:
这个是集群中的主要元素, SimpleTcpCluster类代表这个元素。他使用在server.xml中指定的管理类为所有可分配的web contexts生成ClusterManager。
集群管理器
这 个类关注跨越集群中所有节点间的SESSION数据复制。所有在web.xml文件中指定了distributable标记的WEB应用程序都会有 SESSION复制。集群管理器作为集群元素的managerClassName属性在server.xml中指定。集群管理器的代码主要被设计用来分离 集群中的元素。我们所要做的就是写一个SESSION管理器类去实现ClusterManager接口。这样能让我们灵活的使用客户集群管理器而不会影响 到集群中的其他元素。这里有两个复制算法。SimpleTcpReplicationManager每次复制全部的SESSION,而 DeltaManager只复制SESSION增量。
最简单的复制管理器在每次HTTP请求都复制所有的SESSION。在SESSION较小的时候这样是很有用的,我们可以只用以下代码:
HashMap map = session.getAttribute("map");
map.put("da ta","da ta");
这 里,我们不需要特别调用session.setAttribute() 或者 removeAttribute方法去复制SESSION变化。对于每次HTTP请求,在SESSION中的所有属性都被复制。可以使用一个叫做 useDirtyFlag的属性去最优化SESSION被复制的次数。如果这个标记被设为真,我们必须调用setAttribute()方法去获取被复制 的SESSION变化。如果被设为假,每次请求后SESSION都被复制。
SimpleTcpReplicationManager生成ReplicatedSession执行SESSION复制工作。
提 供增量管理器仅仅是为了性能的考虑。它在每次请求的时候都做一次复制。同时他也调用监听器,所以如果我们调用 session.setAttribute(),那么在其他服务器上的监听器就会被调用。DeltaManager生成DeltaSession执行 SESSION复制。
成员
成员的建立通过由TOMCAT例程在同样的多点传送IP和端口发送广播消息。广播的消息包括服务器的IP地址和TCP监听端口(默认IP地址为228.0.0.4)。
如果在给定的时间框架内一个例程没有接收到消息(由集群配置中的mcastDropTime参数指定),成员被认为死亡。这个元素由McastService类表示。
由mcastXXX开始的属性用于成员资格多点传送PING。以下表格列出了用于IP多点传送服务器通讯的属性。
发送端
这 个元素由ReplicationTransmitter类代表。当多点传送广播消息被接收到,成员被添加到机群。在下次复制请求前,发送例程将使用主机和 端口信息建立一个TCP SOCKET。使用这些SOCKET发送序列化的数据。在TOMCAT 5中有3种不同的方法操纵SESSION复制:异步,同步,池复制模式。以下部分解释了这些模式怎样工作,以及他们将被使用在什么情况下。
●异 步:在这种复制模式中,每个集群节点都有一个单线程扮演SESSION数据传送器。这里,请求线程会把复制请求发送到一个队列,然后返回给客户端。在失效 无缝转移前,如果我们拥有sticky sessions,就应该使用异步复制。这里复制时间不是至关重要的,但是请求时间却是。在异步复制期间,请求在数据被复制完之前就返回了。这种复制模式 缩短了请求时间。当每个请求被分的更开这种模式是很有用的。(例如,在WEB请求间有更长的延迟)。同样,如果我们不关心SESSION是否完成复制这个 也很有用,当SESSION很较小时, SESSION复制时间也更短。
●同步:在这种模式中,一个单线程执行了HTTP请求和数据复制。集群中所有节点都接收到SESSION数据后线程才返回。同步意味被被复制的数据通过一 个单SOCKET发送。由于使用一个单线程,同步模式可能会是簇性能的一个潜在的瓶颈。这种复制模式保证了在请求返回前SESSION 已 经被复制。
●池:TOMCAT5 在使用池复制模式进行SESSION复制的方法上提供了很大的改进。池模式基本上是同步模式的一个扩展版本。他基于的一个原则是:划分服务到多例程,每个 例程处理不同的SESSION数据片段。同时对接收服务器开放多SOCKET进行发送SESSION信息。这种方法比通过单SOCKET发送所有东西更 快。因此,使用一个SOCKET池同步复制SESSION。直到所有SESSION数据都复制完请求才返回。为了有效使用这种模式要增加TCP线程。由于 使用多SOCKET,池模式使得集群性能的逐步提高以及更好的可测性。同样这种模式也是最安全的配置,因为它有足够数量的SOCKET在理想的时间内发送 所有的SESSION数据到其他节点上。而使用单SOCKET,SESSION数据在通过集群时可能丢失或者只是部分传输。
接收端
这个集群元素由类ReplicationListener表示。在集群配置中以tcpXXX开始的属性用于TCP SESSION复制。以下表格列出了用于配置服务器复制中基于SOCEKT服务器通讯的属性。
复制值
复制值用于判断哪些HTTP请求需要被复制。由于我们不经常复制静态内容(例如HTML和JavaS
部署器
部 署器元素可以用于部署集群范围的应用程序。通常,部署只部署/解除部署簇内的工作成员。所以在损坏的节点在启动时没有WARS的复制。当 watchEnabled="true"时配置器为WAR文件监视一个目录(watchDir)。当添加一个新的WAR文件时,WAR被部署到本地例程, 然后被部署到集群中的其他例程。当一个WAR文件从watchDir删除,这个WAR被从本地和集群范围内解除部署。
所有在TOMCAT集群结构中的元素以及他们的层次关系都在列在图1中
图 1. Tomcat 集群等级结构图。单击看原图。
TOMCAT中SESSION复制是怎么工作的
以下部分简要解释当TOMCAT服务器启动或则关闭时集群节点怎样分享SESSION信息,详细信息可参考Tomcat 5 Clustering文挡。
TC-01:集群中第一个节点
TC-02:集群中第2个节点
● 服务器启动:TC-01使用标准服务器启动队列启动。当主机对象被创建,即有一个集群对象和它相关联。当contexts被解析,如果 distributable已经在web.xml中指定,那么TOMCAT为WEB CONTEXT创建SESSION管理器(SimpleTcpReplicationManager 取代StandardManager)。集群将会启动一个成员服务(成员的一个例程)和一个复制服务。
当TC-02启动,他也遵循第一个成员 (TC-01)同样的队列但是有一个不同。集群被启动并且创建一个成员关系(TC-01,TC-02)。TC-02将向TC-01请求SESSION状 态。TC-01回应该请求,在TC-2开始监听HTTP请求前,TC-01发送状态给TC-02。如果TC-01不回应,TC-02将在60秒后进入中止 状态并且发布一个日志入口。SESSIONG 状态发送给所有在web.xml中指定了distributable的WEB应用程序。
●创建SESSION:当TC-01接收到请求,一个SESSION(S1)被创建,处理进入TC-01的请求和没有SESSION复制时是一样的。当请 求完成时会有以下事件:ReplicationValve将会在回应返回给用户前截取请求。这里,会发现SESSION已经被改变,使用TCP复制 SESSION到TC-02。
●服务器储运损耗/关闭:当在集群中的一台服务器失败,维护损坏或者系统升级,其他节点会受到第一个节点已经脱离集 群的通知。TC-02从他的成员资格列删除TC-01,并且TC-02在也不会收到有关TC-01任何变动的通知。负载平衡将会移至TC-02,所有的 SESSION由TC-02控制。
当TC-01开始恢复,他再次遵循在服务器开始阶段描述的启动队列。加入到簇中并且以所有SESSIONG的当 前状态和TC-02通讯。一旦接收到 SESSIONG状态,也就完成了加载然后打开它的HTTP/ mod_jk端口。所以,要等到从TC-2接受到SESSION状态TC-01才能发送请求。
●SESSION终止:如果在第一个节点的一个 SESSION已经无效或则由于过期终止,无效请求将被截取,SESSION会被同其他无效SESSION放在一个队列中。当请求完成,服务器发送 SESSIONG终止消息给TC-02而不是发送已经改变的SESSION,TC-02同样也会把该SESSION置无效。我们可以从服务器控制台看到 SESSIONG无效的消息。无效SESSION在集群中将不会被复制,直到其他请求传出系统并且检查无效队列。
结束语
在 这篇文章中,我谈了有关在集群环境中的SESSION复制,以及编写要求在内存内SESSIONG复制的J2EE应用程序时的一些设计注意事项。我同时也 讨论了在TOMCAT 5容器中被指定来进行SESSIONG复制的簇元素。在这个系列的第2部分,我们将会看看怎样使用不同的SESSIONG 管理器和复制模式在TOMCAT集群中配置SESSIONG复制。
Srini Penchikala 是一个在Flagstar 银行工作的信息系统主题专家。
第二部分
集群安装
为了在TOMCAT5容器中SESSION复制可用,必须完成以下步骤:
● 为了集群能够工作,你必须使用你系统上的多点传送可使用
● 为了有些使用SESSION复制,所有TOMCAT例程必须同样配置。这意味着WEB应用程序必须统一的部署在集群中的每台服务器上。这些配置同样简化了集群管理,维护和发现维修故障的任务。
● 在server.xml未注释的Cluster 和Valve (ReplicationValve) 元素。起用server.xm中的CLUSTER元素意味着所有WEB CONTEXT的SESSION管理器将会改变。因此 当运行一个集群的时候,你应该确保只有一个需要被集成WEB应用程序并且移除其他的。
● 如果服务器例程运行在同样的机器上,应该确保每个例程的tcpListenPort属性是一致的。
● 确保web.xml有distributable属性
● 所有的SESSION属性必须实现java.io.Serializable接口
范例集群安装有两个TOMCAT例程和一个负载平衡用于分配服务器间的请求。所有三个服务器都运行在一个单独的机器上,以下表格列出了集群和负载平衡上的配置参数。
编辑注解:以上Web App Directory中的值为了适应排版而换行了。在你的部署中,每个值应该是单一而完整的一行
注意:不要设置tcpListenAddress为127.0.0.1,因为127用于回环地址,在SESSION复制期间可能会出现问题。
负载平衡器安装
TOMCAT服务器不提供失效转移能力用于当一个集群接点失效的时候重定向任何引入的请求到下一个可用的服务器上。所以我使用一个分开的负载平衡器去管 理WEB请求的负载平衡。有一些流行的负载平衡器例如Apache/mod_jk, Balance, 和 Pen。我在范例集群安装中使用Pen作为负载平衡器。
Pen是一个简单的,基于TCP协议,例如HTTP或者SMTP的负载平 衡器。他允许多个服务器对外表现为一个服务器,并且自动检测关闭的服务器,在可用的服务器间分配客户断。他提供了负载平衡和失效转移能力。Pen易于安装 以及配置,非常容易使用和运行在Windows和UNIX操做系统上。范例配置使用round-robin负载平衡算法用于在集群节点间分配负载平衡
运行负载平衡器的命令如下:
pen -r -a -f -d localhost:8080 192.168.0.10:9080 192.168.0.20:10080
以下是用于启动负载平衡器的每个命令行参数的解释
-r: 使用round robin负载平衡
-a: 打印来回发送的ASCII格式的数据
-f: 保持在前台
-d: 起用DEBUG模式
想要知道更多用于启动PEN的参数细节,请访问PEN网站
图表1展示了两个集群节点,一个负载平衡器,仪器层,以及测试客户端的拓扑图
Figure 1. Cluster setup diagram
测试安装
我创建了一个叫做clusterapp的WEB应用程序来验证集群安装以及SESSION复制原理。为了测试真实的SESSION复制,我写了一个叫做 SessionReplicationClient的简单JAVA客户端用语测试从一个服务器拷贝SESSION数据到另外一个服务器的需要的时间。这个 客户端使用Jakarta Commons HttpClient况架去创建和操作HTTP SESSION并且调用TOMCAT服务器上的一个SERVLET。用于测试SESSION复制的机器软硬件配置如下:
● CPU: HP Pavilion Pentium III 800MHz
● Memory: 512MB RAM
● Hard disk: 40GB
● Operating system: Windows 2000 server
● JDK version: 1.4.2_05 (Note: JDK 1.4 or later version is required to use clustering and session replication)
● Tomcat version: 5.0.28
● Tools: Pen, Log4J, Eclipse, Commons HttpClient
当一个复制客户端程序运行的时候,他首先设置一个作用指令用于这样操纵SESSION(例如,添加一个新的属性到SESSION,从SESSION中移 除一个已存在的属性,或则让一个SESSION失效)。然后客户端通过在Commons HttpClient框架使用HttpClient和PostMethod类调用ReplicationServlet。基于这些SESSION命 令,servlet生成一个新的SEESION或者修改一个已经存在的SESSION并且转到一个WEB页面中瞻示SESSION细节。如果在管理 SESSION中有任何错误,则转到一个错误页面。我写了一个定制的SESSION监听类(ClusterAppSessionListener)用于跟 踪SESSION管理的细节,例如新SESSION的创建,修改或则终止已经存在的SEESION。
图表2展现了SESSION复制流程
Figure 2. Session replication sequence diagram
服务器上的SESSION状态通过每个WEB请求的COOKIE跟踪,所以为了保持使用同样的SESSION,从客户端发出的请求URL必须一样。另 外,在每次请求都创建一个新的HTTP SESSION。我使用了两种类型的,基于添加到SESSION中的属性类别的测试方法去测试复制。
第一个类别有100个轻量对象(每个1K)添加到SESSION。第2个类别中,我添加了一个单一的大对象(100K)去比较基于SESSION属性大小的SESSION复制所花费的时间
以下列出了SessionReplicationClient的测试规格:
● 客户端线程数:2
● 旋环次数:1000
● 请求延迟:1000 milliseconds
● 测试范例数:1000
● SESSION属性:小(100个1K大小的对象)或则大(一个100K大小的对象)
使用指定参数运行测试客户端的命令如下:
java -Dlog4j.configuration=log4j.xml com.clusterapp.test.SessionReplicationClient 2 192.168.0.10 9080 1000 1000 lite
测试环境包括使用不同的SESSION管理器(SimpleTcpReplicationManager 或则 DeltaManager)和SESSION复制模式(同步,异步,池),以下表格列出了在TOMCAT集群中的一系列测试环境:
您正在看的JAVA教程是:Tomcat 5集群中的SESSION复制二。
想要把复制模式从池该到同步或异步,只要在server.xml文件中的SENDER标志中修改replicationMode属性值就可以了。同样,要改变SESSION管理器的类型,只要改变Cluster元素的managerClassName属性。
以下参数用于比较反应时间和SESSION复制的效率:
● 平均反映时间(ms)
● 平均请求时间(ms)
● 集群开销时间(ms)
● 复制时间(ms)
● 比率(bytes/ms)
● 比率(bytes/request)
测试结果
delta管理器和池复制模式相结合使用对与SESSION复制效率是最好的标准。同样,保持SESSION大小较小可以比复制大SESSION快2到3倍。
复制管理器
DeltaManager在SESSION复制方面更有效,因为他仅仅处理SESSION deltas而不是全部的SESSION数据。使用DeltaManager,与使用简单复制管理器比较,SESSION复制效率会提高30%(大 SESSION)到50%(小SESSION)。
复制模式
与其他两个选项(同步和异步)比较,池复制模式复制SESSION花费更好的时间。在一个复制时间内,池选项几乎是同意选项的 4倍快。但是在反应时间和集群开销时间方面,池和同步模式几乎一样,因为在同步模式里,集群在返回前不用等待SESSIONG完成复制
综述
基于SESSION复制测试的结果,我们得出结论:应该在任何可能时候使用DeltaManager。因为复制SESSION数据的开销是意义重大的, 必须确保没有在SESSION中存储太多的数据同样,添加到SESSION中的属性大小也是影响到SESSION复制时间的另一个因素。当我运行测试在 SESSION存储大对象(100K)的时候,与在SESSION中存储小对象(1K)相比较,复制时间非常高。想要最小化SESSION复制开销最好的 方法是避免调用session.setAttribute()以及把数据存储在请求对象中而不是SESSION中。这样相对更好因为当WEB请求完成的时 候请求属性会被重置。同样,如果没有商业方面的原因要在服务器存储数据,我们可以以COOKIES的形式在客户端存储数据。这种方法完全避免了使用任何 SESSIOIN的需要。
一种最小化SESSION复制时间开销的方法是限制集群中到两个或则三个服务器上的服务器例程数目。这 样当第一个服务器失败的时候第一个服务器上的SESSION数据已经被拷贝到第二个服务器上。为了保持网络畅通,集群可以分割成小块的组,每个组包括两个 或则三个服务器例程。记住,集群中的服务器越多,SESSION复制花费的时间也越多。目前TOMCAT5不支持首要/次要复制的概念。在以后发布的版本 中将会有,这样我们将可以在一个或则两个备份服务器上存储SESSION。拥有这个特性的话,TOMCAT将会为在集群环境中运行WEB服务器提供更全面 的SESSION复制方法。
在未来TOMCAT将会支持的一些属性:
● 拥有在SESSION中存在非序列化的属性的能力,集群将会忽略该属性
● 拥有复制context属性以及非序列化的相关数据的能力,例如JDBC连接池和对象CACHES。
这些特性将会使在TOMCAT集群中的SESSION复制更强壮和灵活。
I want to thank Filip Hanik for his valuable suggestions and feedback on the replication modes, session replication web application setup, and the test client sections of this article.