级别: 中级 张 松 (scorpio.song@gmail.com), IBM中国软件开发中心软件工程师
2006 年 7 月 20 日 本文将从实现机制和示例配置两个方面介绍WAS CE的集群。
引言
WebSphere Application Server Community Edition(以下简称WAS CE)是IBM在2005年底开始推出的基于开源项目Apache Geronimo技术构建的轻量级J2EE应用服务器,是WebSphere Application Server产品家族的新成员。受益于开源软件项目的快速和创新的开发模式,WAS CE服务器在第一版的后续的版本中不断加入新的特性,使得产品在功能上不断完善和扩充,及时和有效的满足了客户的需求。2006年5月最新发布的WAS CE V1.0.1版本中,加入了对Web层集群的支持。我们通过构建WAS CE服务器集群,可以获得单服务器环境所无法比拟的好处:
1) 通过在集群成员间进行Session复制的方式,避免单点失效并实现了灾难恢复(failover),从而提高了web应用系统的高可用性(high availability);
2) 利用负载均衡(load balance)的方法,支持更多的、可扩充的并发用户访问数,提高了web应用系统的负载能力。
本文将从实现机制和示例配置两个方面介绍WAS CE的集群。
1.WAS CE集群的实现机制
1.1.利用Tomcat集群实现Session复制
由于WAS CE架构中集成了Tomcat作为J2EE应用服务器中的Web容器,因此它的Web层集群相应的也是通过Tomcat对集群的支持来实现的。每个Tomcat集群成员都会启动两个服务:
1) Membership Service:用于发布Multicast消息来声明自己的集群成员身份。一个集群中的所有成员共用同一个Multicast地址。每个成员通过Membership Service周期性的向这个Multicast地址发送Multicast消息,消息中包含的本机IP地址和用于Session复制的TCP侦听端口等信息。如果在预先设定的一段时间之内没有收到某成员发出的Multicast消息,则其他成员将认为该成员处于非活动状态。需要特别注意的是,由于使用了Multicast,所有集群成员必须在同一子网中。
2) Replication Service:用于跟集群中其他成员之间进行Session复制。两个集群成员通过Membership Service获得对方的IP地址和用于Session复制的TCP侦听端口,在需要复制的时候根据这些信息建立Socket连接。发送方将自己的Session数据序列化,通过Socket连接发送给接收方;接收方再将接收到的数据反序列化成Session数据存放于本地内存空间。这样就完成了从发送方到接收方的Memory-to-Memory的Session复制过程。
除了上述两个服务之外,每个Tomcat集群成员还将启动一个ReplicationValve。Tomcat处理完用户请求(request)之后,将响应(response)返回给用户之前,ReplicationValve会截获响应,检查其中是否涉及到Session数据的修改。如果Session数据发生了更改,ReplicationValve将触发Replication Service同其他集群成员重新进行Session复制,然后再将响应返回给用户。ReplicationValve的功能保证了本地Session数据的更新能够及时的和其他集群成员上的Session数据备份之间进行同步。
下图描绘了Tomcat集群中的两个成员Tomcat A和Tomcat B之间进行成员发现和Session复制的实现逻辑:
1.2.在WAS CE中加入Tomcat集群功能的GBean
在WAS CE所使用的Geronimo架构中,GBean是最小的可管理的单元,Geronimo内核负责GBean生命周期的管理和GBean之间依赖关系的管理。服务器中的每个模块或者系统服务都对应到一组GBean;为了向服务器中加入新的功能或者服务,需要相应的实现一组GBean,并部署到WAS CE运行环境中。
因此,为了在WAS CE运行环境中使用集群的功能,需要部署一组已经实现的GBean。这组GBean及其功能如下表所示:
1.3.利用Web Server + Tomcat Redirector Module实现负载均衡
Tomcat集群中仅实现了集群成员之间的Session复制,即支持灾难恢复、提高了系统的高可用性。在集群系统的前端,还需要通过Web Server负责在集群成员间进行用户请求分发,实现负载均衡的功能。
Apache JServ Protocol Version 1.3(简称为AJP13)是用于支持Web Server和Servlet/JSP Container之间进行通讯的协议。Tomcat 5中内置了对AJP13协议的支持;在WAS CE服务器启动以后,将显示支持AJP协议的Tomcat Connector正在侦听,缺省使用端口8009,如下图所示:
为了使Web Server支持AJP13协议,需要在Web Server中加载Tomcat Redirector Module(即mod_jk模块)。目前Jakarta Tomcat Connector项目支持的Web Server包括Apache、IIS、Donimo、SunOne;即分别针对这4种Web Server提供了对应的mod_jk实现。加载并配置了mod_jk模块后,Web Server首先分别为每个Tomcat引擎加载一个Servlet Container Adapter;当接收到HTTP请求时,Web Server将判断该请求属于哪个Servlet Container,然后调用相应的Servlet Container Adapter来处理该请求。在此负载均衡系统中,Web Server从功能的角度被称为Load Balancer。
在Apache HTTP Server中使用mod_jk包含三个步骤:1)安装mod_jk.so模块;2)定制mod_jk的配置文件workers.properties;3)修改Apache的配置文件httpd.conf。每个步骤的详细操作将在后面给出的示例中说明。
Apache和WAS CE集群协同工作完成负载均衡的系统实现逻辑如下图所示:
2.WAS CE集群的示例配置
2.1.示例程序说明
WAS CE的下载网站提供了示例程序包(wasce_samples-1.0.1.2.zip)可供用户下载,在这个示例程序包中有一个用于演示集群环境的tomcat-cluster的示例。通过此示例应用程序,我们将对WAS CE集群的实现机制有更加清晰的理解,对配置过程有更加具体的掌握。在这个示例中,我们将构建运行在两台不同机器上的WAS CE服务器组成的集群。
示例程序tomcat-cluster包含以下几个文件:
2.2.实验说明
1)所有机器必须处于同一子网(subnet)中,并且支持广播(multicast)。
2)某些Linux平台需要手工配置IP广播,请参考以下链接获得帮助:
http://tomcat.apache.org/faq/cluster.html
3)所有集群成员必须尽可能保证系统时间一致,较大的系统时间差异可能会出现问题。
4)本示例程序已在以下操作系统上进行了验证:
Linux IA32 - RHEL3u7, RHEL4u3, SLES9u3
Linux PPC64 - RHEL4u2
Windows IA32 - Windows 2003 Server SP1, Windows XP SP2
需要特别注意的是,由于存在已知问题,请将RHEL3u5升级至RHEL3u7以支持WAS CE的集群功能。
2.3.更新WAS CE服务器配置,指定jvmRoute标识
WAS CE集群中的每个成员服务器都需要指定一个唯一的jvmRoute标识。通过使用jvmRoute标识,Load Balancer(即加载了mod_jk模块的Apache)把同一个HTTP Session的所有请求发送到同一个集群成员,实现了Sticky Session的要求。事实上,Load Balancer在返回给浏览器的响应中通过Session Cookie或者URL重写两种方式之一,加入了jvmRoute的属性值。
为了给每个集群成员分配jvmRoute,需要在WAS CE服务器停止的状态下,修改成员服务器server1配置文件var/config/config.xml中TomcatEngine的initParams属性值如下:
<gbean name="TomcatEngine">
<attribute name="initParams">
name=Geronimo
jvmRoute=server1
</attribute>
</gbean>
|
在成员服务器server2的配置文件中相应的修改为:
<gbean name="TomcatEngine">
<attribute name="initParams">
name=Geronimo
jvmRoute=server2
</attribute>
</gbean>
|
2.4.在server1和server2上分别安装应用程序
在server1上,替换部署计划servlet-examples-cluster-plan.xml中的<xx.yy.zz.aa>为server1的IP地址(例如9.186.117.240):
<gbean name="TomcatReceiver"
class="org.apache.geronimo.tomcat.cluster.ReceiverGBean">
<attribute name="className">
org.apache.catalina.cluster.tcp.ReplicationListener
</attribute>
<attribute name="initParams">
tcpListenAddress= 9.186.117.240
tcpListenPort=4001
tcpSelectorTimeout=100
tcpThreadCount=6
</attribute>
</gbean>
|
使用管理员用户名(初始为system)和密码(初始为manager)登陆WAS CE的管理控制台http://<server1_IP>:8080/console
在管理控制台的应用程序安装页面Deploy New中指定应用程序servlet-examples-cluster-server1.war的文件路径和部署计划servlet-examples-cluster-plan.xml的文件路径,安装示例程序:
管理控制台中显示安装成功的信息以后,在浏览器中通过链接
http://<server1_hostname_or_IP>:8080/servlet-examples-cluster/
验证server1上已安装的示例程序,将看到页面中显示以下标题:
类似的,在server2上,首先在部署计划中更新server2的IP地址(例如9.186.117.66),然后安装servlet-examples-cluster-server2.war,得到的验证页面中将显示以下标题:
2.5.安装Apache HTTP Server + mod_jk
1)从http://httpd.apache.org/ 下载并安装Apache HTTP Server,建议使用v2.0.54或更新的v2.0.x版本。Apache可以安装在跟server1和server2不同的第三台机器上。
2)从http://tomcat.apache.org/connectors-doc/ 下载mod_jk,建议使用v1.2.14或更新版本。
3)将下载的mod_jk(以WIN32平台为例,下载后文件名是mod_jk-1.2.14-apache-2.0.54.so)文件重命名为mod_jk.so,拷贝到Apache安装目录下的modules目录中。
4)在Apache安装目录下的conf目录中, 修改配置文件httpd.conf。在配置文件中LoadModule部分的末尾加入如下内容(参考示例程序中的httpd.conf.txt):
LoadModule jk_module modules/mod_jk.so
<IfModule mod_jk.c>
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
<Location /*/WEB-INF/*>
AllowOverride None
deny from all
</Location>
<Location /*/META-INF/*>
AllowOverride None
deny from all
</Location>
# forward ALL web requests to our mod_jk loadbalancer workers
JkMount /* loadbalancer
</IfModule>
|
5)将workers.properties拷贝到Apache安装目录下的conf目录中,并根据server1和server2的IP地址作相应的修改,如下例所示:
worker.list=loadbalancer,status
worker.maintain=60
worker.server1.type=ajp13
worker.server1.host=9.186.117.240
worker.server1.port=8009
worker.server1.socket_timeout=60
worker.server1.socket_keepalive=true
worker.server1.lbfactor=1
worker.server2.type=ajp13
worker.server2.host=9.186.117.66
worker.server2.port=8009
worker.server2.socket_timeout=60
worker.server2.socket_keepalive=true
worker.server2.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=server1,server2
worker.loadbalancer.sticky_session=1
worker.status.type=status
|
注意:如果WAS CE集群中有除了server1和server2之外,还有jvmRoute属性为xyz的成员,则需要在loadbalancer管理的worker列表中加入xyz:
worker.loadbalancer.balanced_workers=server1,server2,xyz
并且相应的加入对该成员的worker描述信息:
worker.xyz.type=ajp13
worker.xyz.host=<xyz_hostname_or_IP>
worker.xyz.port=8009
worker.xyz.socket_timeout=60
worker.xyz.socket_keepalive=true
worker.xyz.lbfactor=1
|
当然需要从集群中删除某个成员的时候,则需要从worker.loadbalancer.balanced_workers的取值列表中删除该成员的jvmRoute值,并且删除对该成员的worker描述信息。
通过设置worker.server1.lbfactor和worker.server2.lbfactor的值,可以根据server1和server2服务器性能的差异,设置server1和server2负载用户请求的权重:数值越大,分配到的用户请求数就越多。
2.6.验证实验结果
1)在浏览器中通过Apache访问示例程序的URL为
http://<Apache_hostname_or_IP>/servlet-examples-cluster/servlet/SessionExample
向session中添加一些数据后,得到的结果类似下图所示:
从上图标题可以看出,当前用户访问的session是在server1上创建的。
2)停止集群成员服务器server1,在浏览器中刷新以上页面,将发现用户session转移到server2上。继续向session中添加一些数据后得到的结果如下:
从上图标题可以看出,当前用户访问的session被转移到了server2上:Session ID不变,session中以前的数据也仍然存在。所以当集群成员server1失效时,sever2利用保存的server1上的session数据,实现了灾难恢复。Apache将把以前针对server1的用户请求定向到当前处于活动状态的server2。
3)重新启动server1,在浏览器中刷新以上页面,将发现用户session又被恢复到server1。可见恢复活动状态的server1又重新加入到了集群中:
3.结束语
本文介绍了WAS CE中Web层集群功能的实现方式,通过一个示例程序的配置介绍了具体的操作步骤,并且展示了集群所提供的灾难恢复的特性。虽然对于J2EE应用服务器系统而言,完整的集群环境应该包含Web层、EJB层、JMS层和全局JNDI四个层面的集群,但是对于大多数中小型企业客户的应用系统来说,Web层的集群已经能够满足生产环境的需要。在开源社区广泛的参与者们不断的努力下,Geronimo和WAS CE将迅速的发展和完善,提供更强大的集群功能。
参考资料
关于作者  | |  | 张松是IBM中国软件开发中心的软件工程师,所在团队目前从事WebSphere Application Server Community Edition产品相关的开发测试、售后服务和客户技术支持等工作。他的电子邮箱是scorpio.song@gmail.com。 |
对本文的评价
|