通过 Terracotta实现基于Tomcat的Web应用集群

huiyi00 2014-07-15

本文介绍如何配置Tomcat和Terracotta服务器将普通的Web应用部署到集群中,实现跨Tomcat节点的session复制,以达到负载均衡、提高系统吞吐量和灾难恢复的效果。

基本原理简介

一般利用Tomcat搭建Web应用集群有如下几种方法:

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

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

3、第三种方式是通过cookie保存用户信息的一个或几个关键字,每一个http请求到达web应用的时候,web程序拿这个关键字到数据库中读取相关的数据,然后对其进行处理。也就是说把session数据保存到了数据库中。这样以来在内存中的session就完全不需要了。这样做的缺点就是加大了数据库的负载,使得数据库变成了集群的瓶颈。而通过构造数据库集群提高负载能力往往需要高额的成本。

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

为了方便使用Terracotta搭建Tomcat集群,Terracotta提供了专门的插件tim-tomcat。下面将对集群的搭建进行详细描述。

准备工作

首先需要下载如下软件:

ApacheTomcat

目前Terracotta官方支持的Tomcat版本为:

ApacheTomcat6.0.18

ApacheTomcat5.5.26

ApacheTomcat5.0.28

Terracotta3.0或更高版本

安装过程

在所有机器上安装Java

请参考目前支持的软硬件平台

在所有机器上安装Terracotta

选一台机器作为Terracotta服务器

在所有运行Tomcat的机器上也安装Terracotta,他们将称为Terracotta客户端

在应用服务器节点上安装Tomcat

把要部署的Web应用部署在所有Tomcat上

配置过程

下载附件中的tc-config.xml文件,保存到${TERRACOTTA_HOME}/tc-config.xml(Unix上)或者${TERRACOTTA_HOME}/tc-config.xml(Windows上)。

修改web-applications和web-application部分,把要共享session的应用的contex配置上:

<web-applications>

<web-application>my_web_app1</web-application>

<web-application>my_web_app2</web-application>

</web-applications>

您可能还需要修改Terracotta服务器的信息。比如:

<serverhost="192.168.0.100"><!--IPorhostnameofTCserver-->

<dso-port>9510</dso-port>

</server>

把配制好的tc-config.xml文件拷贝到所有机器上。然后在每一台机器上,进入TERRACOTTA_HOME目录,运行:

UNIX/LINUX

bin/tim-get.shupgradetc-config.xml

<Windows

bin/tim-get.batupgradetc-config.xml

配置Tomcat应用服务器

在Tomcat安装目录的bin子目录中创建startupTC.sh(Unix)或startupTC.bat(Windows)文件。其内容为:

UNIX/LINUX

TC_INSTALL_DIR=<本地Terracotta安装目录>

TC_CONFIG_PATH=<本地tc-config.xml的完整文件名>

.$TC_INSTALL_DIR/bin/dso-env.sh-q

exportJAVA_OPTS="$JAVA_OPTS$TC_JAVA_OPTS"

.startup.sh

Windows

setTC_INSTALL_DIR=<本地Terracotta安装目录>

setTC_CONFIG_PATH=<本地tc-config.xml的完整文件名>

call%TC_INSTALL_DIR%/bin/dso-env.bat-q

setJAVA_OPTS=%JAVA_OPTS%%TC_JAVA_OPTS%

startup.bat

启动集群

在Terracotta服务器上的Terracotta安装目录执行如下命令:

UNIX/LINUX

bin/start-tc-server.sh&

Windows

bin/start-tc-server.bat

在每一台Web应用服务器上的Tomcat安装目录的bin子目录下执行:

UNIX/LINUX

./startupTC.sh

Windows

startupTC.bat

等Tomcat启动以后,查看Tomcat日志文件,确认Terrocotta已经启动。比如在Mac环境中,使用Terracotta3.0.1,看到的日志将包括如下内容:

2009-07-1710:57:39,425INFO-Terracotta3.0.1,asof20090514-130552(Revision12704bycruise@su10mo5from3.0)

2009-07-1710:57:39,828INFO-Configurationloadedfromthefileat'/Users/lma/tc-config.xml'.

2009-07-1710:57:39,975INFO-Logfile:'/Users/lma/apps/tomcat-5.5.27/bin/logs/client-logs/terracotta-client.log'.

2009-07-1710:57:42,312INFO-Connectionsuccessfullyestablishedtoserverat192.168.0.102:9510

如果能看到上述信息,说明Terracotta和Tomcat都正常启动,并且已经与Terracotta服务器成功建立了连接。

验证Session集群

集群启动后,我们可以利用Tomcat内置的Web应用examples来验证集群是否成功配置好。

比如有两台Tomcat服务器分别为http://192.168.0.101:8080和http://192.168.0.102:8080。

首先启动dev-concole.sh(Unix)或dev-console.bat(Windows),连接到Terracotta服务器上。您可以看到所有Tomcat节点都显示在ConnectedClients中。另外在ObjectBrowser中可以看到一个共享数据:

tc:session_localhost/examples

说明所有session已经被共享到Terracotta服务器上了。

下面把浏览器指向:

http://localhost:8088/examples/jsp/cal/login.html

输入姓名和EMail。点击Submit进入下一级页面。

这时您可能会看到服务器抛出com.tc.exception.TCNonPortableObjectError异常。仔细查看异常信息会发现原来该例子程序所需的一些类没有包含在tc-config.xml的instrumented-classes配置中。因此需要打开tc-config.xml配置文件,把如下配置添加到<application><dso>中:

<instrumented-classes>

<include>

<class-expression>cal.*</class-expression>

</include>

</instrumented-classes>

重新启动Tomcat。再打开前面的页面。

您可能还会遇见TCNonPortableObjectError,不过这次的错误是有关bootjar的:

com.tc.exception.TCNonPortableObjectError:

*******************************************************************************

Attempttoshareaninstanceofanon-portableclassreferencedbyaportableclass.ThisunshareableclassmustbeintheDSObootjar.ItalsohassuperclasseswhichmustbeintheDSObootjar.Pleaseaddalloftheseclassestothebootjarconfigurationandre-createtheDSObootjar.

只要认真阅读错误信息,按照提示的方法配置tc-config.xml文件,然后执行下面的命令重新生成bootjar文件,再重新启动Tomcat就可以了:

$TERRACOTTA_HOME/bin/make-boot-jar.sh-f$TOMCAT_HOME/tc-config.xml

处理完上述问题后,例子程序中会显示一个日历管理系统。您可以在里面配置一天的工作日程。

在第一台Tomcat服务器上配置好一天的日程,然后到第二台服务器上,打开相同的页面,您会看到前面输入的日程已经显示出来了。您还可以试着在第二台服务器上对日程进行修改,再到第一台上面刷新页面,前面的修改也会立即显示出来。这说明两台Tomcat服务器的session信息已经完全同步了。

错误处理

1.如果启动失败,有可能是JAVA_OPTS没有配置好。

可以尝试在startupTC文件中,在setJAVA_OPTS后面打印出JAVA_OPTS的内容。应该看到类似下面的内容:

-Xmx512m-Xms512M-Xbootclasspath/p:/Users/lma/terracotta/terracotta-3.0.1/lib/dso-boot/dso-boot-hotspot_osx_150_19.jar-Dtc.install-root=/Users/lma/terracotta/terracotta-3.0.1-Dtc.config=/Users/lma/tc-config.xml

2.如果遇见TCNonPortableObjectException异常,说明在Session中共享的类没有包含在tc-config.xml的instrumented-classes配置中。一般在异常新吸力面Terracotta会包含需要添加到配置文件中的信息,比如:

<instrumented-classes>

<include>

<class-expression>num.NumberGuessBean</class-expression>

</include>

<instrumented-classes>

</instrumented-classes>

只要按照提示把配置信息放到tc-config.xml文件中,然会从新启动Tomcat即可。

附件-tc-config.xml

<tc:tc-configxmlns:tc="http://www.terracotta.org/config"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-4.xsd">

<servers>

<!--FormoreinformationonworkingwiththeTerracottaconfigurationfile,includinghowtoadd

moreservers,seehttp://www.terracotta.org/web/display/docs/About+Terracotta+Configuration+Files.

Editthefollowingserverelementsothatitshostattributecontainsthevaluematchingthe

hostnamefortheTerracottaserver.-->

<serverhost="localhost">

<dso-port>9510</dso-port>

</server>

<update-check>

<enabled>true</enabled>

</update-check>

</servers>

<!--CheckthattheTIMshowninthe<module>element'snameattributematchestheTomcatversionyou

areusing.TheTIMlistedhere,"tim-tomcat-5.5"isforTomcat5.5.Forexample,ifyouareusing

Tomcat6.0,editthenameto"tim-tomcat-6.0".-->

<clients>

<modules>

<modulename="tim-tomcat-6.0"version="1.1.0"/>

</modules>

</clients>

<!--Using<web-application>elements,enterthecontextrootofthewebapplicationbeingclustered.

Ifyouareclusteringmorethanonewebapplication,useone<web-application>elementperapplication.

Twoexample<web-application>elementsareshownbelow.Editorremovetheseelementsasneeded.

Tosetthevalueofthe<web-application>elementtothedefaultweb-applicationcontext,usethe

specialvalue"ROOT"(withoutquotationmarks).-->

<application>

<dso>

<instrumented-classes>

<include>

<class-expression>num.NumberGuessBean</class-expression>

</include>

<include>

<class-expression>cal.*</class-expression>

</include>

</instrumented-classes>

<web-applications>

<web-application>examples</web-application>

</web-applications>

</dso>

</application>

</tc:tc-config>

相关推荐