英文原版 ,中文版由Tony Tang 翻译整理
在第一部分中,我简述了具有可升级和高可靠性的大型J2EE 系统在设计时需要考虑的各种因素。
讨论Tomcat 对集群、负载均衡、容错和 session 复制等能力的支持。
在这个部分,我们将看到完整一个集群的架构和部署集群过程的安装和配置细节(通过运行多个Tomcat 服务器实例)。
+ 集群的设置
下面列出的是这个 Tomcat 集群例子要实现的目标:
* 可升级能力
* 容错
* 动态配置,易于管理
* 自动发现新成员
* 失败重启和负载均衡,session 数据内存复制
* 可插拔/ 配置的负载均衡策略
* 当一个成员加入或离开时,能通知组成员
* 通过多播的方式,无掉包的信息传输
* 集群对 web 应用和服务器来说都是无缝的。
在这个集群环境中,安装有四个 Tomcat 服务器实例。一个作负载均衡服务器,三个作集群。
集群以垂直缩放的方法设置(多个 Tomcat 服务器实例运行在一台机器上)。
下面是集群的主要组成部分的设置:
* 负载均衡 : 一个Tomcat 实例,分发交易到集群的个节点上。代号TC-LB 。
* 集群 : 集群包含3 个Tomcat 服务器实例,代号分别是 TC01, TC02 和 TC03 。
* session 持久化 : 选择内存复制的方式。当session 对象改变时,session 数据将被复制到所有3 个集群成员。
* 失败重启 : Tomcat 安装时自带的负载均衡器应用不能处理失败重启。
我写了一个工具类 ServerUtil ,在转发请求给服务器之前检查服务器状态。
有种两种方法检查集群节点的状态。在第一种方法中,使用 McastService 来检测是否有一个指定的服务器实例运行。
而第二种方法则通过以Web 页的URL 为参数创建一个URL 对象,验证集群节点的有效性。
要使用这个类,需要确保 catalina-cluster.jar( 位于 %TOMCAT_HOME%/server/ 库目录)
和 commons-logging-api.jar( 位于%TOMCAT_HOME%/bin 目录) 文件在 classpath 中指定。
下面集群的主要组件的架构图。
http://image.360doc.com/DownloadImg/15084/348251_1.gif
图1 ,Tomcat 集群架构图
+ 安装和配置 Tomcat 实例
表1 ,本例中设置 Tomcat 集群环境所用到的硬件和软件
Processor HP Pavilion Pentium III with 800 MHz
Memory 512 MB RAM
Hard Disk 40 GB
Operating System Windows 2000 server with Service Pack 4
JDK Version 1.4.0_02 (Note: JDK version 1.4 or a later version is required to enable Tomcat Clustering)
Tomcat Version 5.0.19
Tools Used Ant 1.6.1, Log4J, JMeter, JBuilder
+ 集群框架的主要元素
++ Java 类
* BaseLoadBalancingRule
抽象类,封装通用的规则逻辑。在这个例子中的自定义负载均衡规则就是扩展自这个基类。
* RandomRedirectRule
使用“随机”的规则,定义重定向web 请求到一个有效的服务器上的逻辑。使用当前系统时间作为种子,生成一个随机的号码。
* RoundRobinRule
这个类定义一个负载均衡的逻辑,基于“轮循”规则。当一个请求进入,它将其重定向到集群成员列表中的下一个成员。
使用一个静态变量来跟踪下一个有效的集群成员,每处理一个请求,就将这个值加1 。
* ServerUtil
一个工具类,用来检测指定的集群节点是否有效。
这个类用 McastService (org.apache.catalina.cluster.mcast 包)来检测某集群成员是否离开了这个组。
下面的类图表示这些Java 类之间的关系。
http://image.360doc.com/DownloadImg/15084/348251_2.gif
图2 集群应用类图
++ 配置文件
* server.xml
用于对 Tomcat 服务器实例进行集群配置。这个版本的Tomcat 安装后,server.xml 文件中包含被注释掉的集群配置细节。
* web.xml
在这个文件中可指明该web 应用的session 数据需要被复制。
* rules.xml
这个文件用来定义的负载均衡规则。
++ 脚本
* test.jsp
一个简单的测试 JSP 脚本,用于检查服务器的状态。显示运行的Tomcat 实例的名字和系统时间。
* testLB.jsp
在本应用中,这个是起始页面。它使用 HTML 重定向将web 请求转发到负载均衡过滤器上。
* sessiondata.jsp
这个脚本用来验证当一个集群节点挂起时,session 数据并没有丢失。显示session 的内容,使用 HTML 字段操作 HTTP session 对象。
* build.xml
Ant build 脚本,让启动和停止Tomcat 实例的任务实现自动化(由Ant 1.6.1 用来执行这个脚本)。一旦某个Tomcat 实例启动成功,你可以通过指定IP 地址和端口号,调用test.jsp 来验证该Tomcat 实例是否在运行。这个JSP 页将显示当前系统时间和Tomcat 实例的名称。你需要改变 build.properties 文件中的 home 目录的指定,在你自己的环境中运行这个脚本。
build 脚本中用于启动或停止 Tomcat 实例的几个 targets:
* 调用 target “start.tomcat5x” 启动一个特定的 Tomcat 实例( 例如: tomcat50) 。
* 调用 stop.tomcat5x 停止一个特定的Tomcat 实例
* 调用 stop.alltomcats 中止所有运行的 Tomcat 实例
+ 范例代码
本例子的代码 tomcatclustering.zip 。安装完 Tomcat 服务器实例后(4 个) ,解压这个zip 文件中的文件到tomcat 目录。
例子代码使用RoundRobinRule 作为负载均衡规则。如果您想使用随机的重定向规则,修改rules.xml 文件( 在tomcat50/webapps/balancer/WEB-INF/conf 目录中) 。
注释掉 关于 RoundRobinRule 的元素,取消关于 RandomRedirectRule 元素的注释。 同样,如果您想用两个实例,而不是三个,注释掉第三个,并改变maxServerInstances 属性的值为2 (替换原来的3 )。
注意:缺省情况下,tomcat 安装后会包含好几个其他的应用,我删除了所有其他的web 应用(jsp-examples ,等等) ,仅仅保留 balancer 和 本例的web 应用。
+ HTTP 请求流程
本例集群环境中的 web 请求流程如下:
1. 运行起始页面(http://localhost:8080/balancer/testLB.jsp) ;
2. JSP 将请求重定向到负载均衡过滤器(URL:http://localhost:8080/balancer/LoadBalancer)
3. 负载均衡器(TC-LB) 拦截web 请求,并根据配置文件中指定的负载均衡规则重定向到下一个有效的集群成员(TC01, TC02 或者 TC03) ;
4. 被选中的集群成员的sessiondata.jsp ( 位于 “clusterapp” web 应用) 被调用;
5. 如果 session 被修改, ClusterAppSessionListener 的 session 监听器方法将被调用,用于记录 session 修改事件;
6. sessiondata.jsp 在web 浏览器上显示session 的详细内容( 例如session id, 最后访问事件,等等) ;
7. 随机停止一个或两个集群节点(调用 Ant 脚本的 “stop.tomcat5x” target );
8. 重复上面7 个步骤,查看是否对某个有效的集群成员的请求失败。同时,检查session 信息是否在集群成员内部进行无数据丢失的拷贝。
http://image.360doc.com/DownloadImg/15084/348251_3.gif
图3 表示一个web 请求的流程
集群应用的序列图
+ 集群的配置
在这个集群中,运行一个“clusterapp” 的web 应用。为优化session 复制,所有的实例拥有一样的目录结构和内容。
由于Tomcat 服务器实例使用IP 多播来传输session ,我们必须确定集群机器上的IP 多播功能是可用的。为验证,你可以运行《如果编写多播服务和客户程序。Tomcat:The Definitive Guide 》这本书中的例子Java 程序MulticastNode ,或者,参考http://java.sun.com/docs/books/tutorial/networking/datagrams/broadcasting.html 。
当一个集群节点启动,集群中的其他成员将在服务器控制台上显示一条记录信息,说明一个成员已经被添加到集群中。类似的,当一个集群节点下线,其他的节点将在控制台上显示一个集群成员离开的记录。
http://image.360doc.com/DownloadImg/15084/348251_4.gif
图4 当集群中添加或者删除一个成员时所产生的记录信息
按照下面的步骤可打开Tomcat 服务器的集群和session 复制功能:
1. 所有的session 属性必须实现java.io.Serailizable 接口
2. 取消对server.xml 文件中Cluster 元素的注释。userDirtyFlag 和replicationMode 两个属性用于优化频率和session 复制机制。
3. 取消对server.xml 中Value 元素的注释。ReplicationValue 用于拦截HTTP 请求并在集群成员内复制session 数据。Value 元素有一个“filter” 的属性,可以用来过滤不会对session 进行修改的请求( 如HTML 页面和图像文件) 。
4. 由于全部Tomcat 实例都是运行在同一台机器上,每个Tomcat 实例的tcpListenPort 属性需要设置成唯一。名字格式为 mcastXXX(mcastAddr, mcastPort, mcastFrequency, 和 mcastDropTime) 的属性都是用于集群关系的多播ping ,而名字格式为tcpXXX(tcpThreadCount, tcpListenAddress, tcpListenPort 和 tcpSelectorTimeout) 是用于 session 复制( 下面的集群配置参数表显示Tomcat 服务器实例的不同配置)
5.web.xml meta 文件( 位于clusterapp/WEB-INF 目录) 应该拥有元素。为一个指定的web 应用复制session 状态,distributable 元素必须被定义。这表示如果你有不止一个web 应用需要session 复制,那么你需要增加distributable 到所有web 应用的web.xml 文件中。《Tomcat:The Definitive Guide 》这本书的“Tomcat 集群”这章对这个问题有很好的解释。
表2 集群的配置参数
配置参数实例 1 实例 2 实例 3 实例 4 Instance Type 负载均衡器集群节点1 集群节点2 集群节点3 Code name TC-LB TC01 TC02 TC03 Home Directory c:/web/tomcat50 c:/web/tomcat51 c:/web/tomcat52 c:/web/tomcat53 Server Port 8005 9005 10005 11005 Connector 8080 9080 10080 11080 Coyote/JK2 AJP Connector 8009 9009 10009 11009 Cluster mcastAddr 228.0.0.4 228.0.0.4 228.0.0.4 228.0.0.4 Cluster mcastPort 45564 45564 45564 45564 tcpListenAddress 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 Cluster tcpListenPort 4000 4001 4002 4003
注意:由于所有的集群成员都是运行在同一台机器上,他们使用同一个IP 地址(127.0.0.1) 。
如果你没有使用Ant 脚本启动和停止Tomcat 实例,不要在你的机器上设置CATALINA_HOME 环境变量。如果这个变量被设置,所有的实例都尝试使用同一个目录(CATALINA_HOME 变量指定的)来启动Tomcat 实例。结果只有第一个实例能成功启动,其他的实例会崩溃,出现邦定异常信息,通知端口已经被使用:“java.net.BindException: Address already in use: JVM_Bind:8080” 。
+ 负载均衡的设置
我写了两个简单,自定义的负载均衡规则(RoundRobinRule 和 RandomRedirect) ,用于重定向进入的web 请求。这些规则都是基于负载均衡算法( 例如轮循和随机重定向) 。你可以编写基于其他因素(如加权和最后访问时间等)类似的自定义负载均衡规则。Tomcat 负载均衡器提供一个样例(基于参数的负载均衡规则),它根据HTTP 请求的参数决定重定向web 请求到不同的URL 上。
保持 server.xml (TC-LB 实例) 中关于集群和value 元素的注释状态,因为该实例并非集群成员。
+ 测试的设置
++ session 持久化测试
在 session 持久化测试中, 主要目标是在一个web 请求过程中验证当一个集群成员崩溃后,session 数据并没有丢失。JSP sessiondata.jsp 用来显示session 内容。这个脚本同时提供HTML text 字段,用于添加/ 修改/ 删除 session 属性。在添加属性给HTTP session 后,我随机的停止集群节点,并检测有效的集群成员上的session 。
++ 负载测试
负载测试的目的是研究自定义的负载均衡算法,当一个或多个节点停止服务的情况下,web 请求如何被有效的分发到指定的集群节点。JMeter 负载测试工具就是用来模拟多并发web 用户的情况。
测试负载均衡的步骤如下:
1. 启动负载均衡器和集群实例。
2. 运行起始JSP 脚本(testLB.jsp )。
3. 通过手动停止一个或者多个容器来模拟服务器崩溃。
4. 检查负载分发模式。
5. 重复100 次步骤1 至4 。
所有的记录信息被重定向到一个文本文件,叫tomcat_cluster.log (位于 tomcat50/webapps/balancer 目录)。在序列图中(图2 )的所有web 对象的响应时间是使用Log4J 信息记录。表3 是耗时(毫秒)表。
下表表示负载测试的耗时(使用RoundRobinRule 算法)和负载分发百分比(使用RandomRedirectRule 算法)。
Table 3. 负载测试的耗时
# Scenario testLB.jsp
(ms) RoundRobinRule
(ms) sessiondata.jsp
(ms) Total
(ms) 1 三个服务器都在运行54 76 12 142 2 两个服务器实例在运行(TC02 was stopped) 55 531 14 600 3 一个服务器在运行
(TC01 and TC02 were stopped)56 1900 11 1967
注意:所有的耗时是100 个并发用户的平均值。
表 4. 当使用随机负载均衡规则是的负载分发。
# Scenario TC01 (%) TC02 (%) TC03 (%) 1 所有服务实例在运行30 46 24 2 两个服务实例在运行 (TC02 was stopped) 56 0 44
注意:负载分发的百分比也是基于100 个并发用户的负载。
+ 总结
在session 持久化测试中,增加session 属性后,其中的一个集群节点挂起,通过验证,证实在服务器停机时间,session 属性并没有丢失。session 属性的具体内容记录在文本文件中。
在负载测试中,当一个或者两个服务器实例停止,仅有一个 Tomcat 实例运行,回应的时间比起所有三个实例都有效时长。当原先停止的实例重新启动,负载均衡器自动重新发现这些服务器有效,将接下来的请求重定到这些服务器实例上,马上能提高回应的时间。
这里用来发现集群成员是否有效的机制(ServerUtil) 并非是最快的方法。
这个集群设置的一个缺陷是它仅仅提供一个负载均衡器。当用作负载均衡器的 Tomcat 实例挂起时会发生什么事情呢?就没有途径转发请求到集群,这个结果叫做单点失败(SPoF). 其中一个解决方法就是有另外一个Tomcat 实例运行着,作为一个备用负载均衡器。如果主负载均衡器崩溃时,备用均衡器将接替它的工作。典型的 高可靠性集群(HA) 包含两个负载均衡器防止 SPoF 的情况发生。
在上面的例子中,所有Tomcat 实例(包括负载均衡器)都是配置在同一台机器上运行。更好的设置就是在一台独立的机器上运行负载均衡器。同样,限制每台机器拥有两个集群节点,充分利用水平缩放的方法来保证集群的效率。
对J2EE Web 应用服务器来讲,HTTP session 复制是一种昂贵的操作。J2EE 集群环境下,session 管理的实现应该在项目的分析和设计阶段中就需要考虑。编码时必须想着集群环境。如果没有在设计阶段就考虑集群的实现,为了让应用能在集群环境下工作,代码可能需要全部重写。这会造成非常大的影响。
如果web 应用支持各种对象缓存机制,那么在应用开发的初始阶段,集群环境中的缓存对象就应该被考虑。这是非常重要的,因为对于提供精确和即时的事务数据给Web 用户,在所有集群的节点中保持缓存数据的同步是非常危险的。
一旦J2EE 集群成功设置和运行,它的管理和维护将变得非常重要。保持集群的运行和将应用的变化推到所有的集群节点上。需要有一个方法提供这些服务,实现一个监视器服务,周期性的检测服务器的有效性,如果集群中有节点无效,它将会发出通知。这个服务有规律间隔的检测失效的节点,并从活动集群节点列表中删除失效的节点。它应该拥有一种能力,当改变和更新出现时,它能同步和更新集群中所有的服务器。由于对web 应用的所有的请求必须通过负载均衡系统,这个系统能检测到活动session 的数量,活动session 的数量,回应次数,高峰负载的次数,高峰其间活动session 的数量,低谷其间活动负载的数量,等等。这些审计信息可以为提高性能, 优化整个系统作为参考。
在这里,可以通过手动调整配置文件(server.xml 和 rules.xml )满足设置集群和负载均衡器的所有配置需求。如果Jakarta 项目组提供基于Web 的集群管理工具,那我们就可以通过使用管理工具修改配置来管理集群和负载均衡。
+ 资源
* Tomcat 5 主页
* Tomcat 站点的集群主页
* Tomcat 站点的负载均衡主页
* Tomcat: The Definitive Guide by Jason Brittain and Ian F. Darwin
* Java Performance Tuning, 2nd Edition by Jack Shiraji
* Creating Highly Available and Scalable Applications Using J2EE, The Middleware Company, EJB Essentials Training Class Material
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com