随笔-72  评论-20  文章-0  trackbacks-1

本文目的在于分析Jetspeed支持集群的现状。首先介绍了集群计算的背景知识,然后使用tomcat作为例子配置了一个集群,接着分析了 jetspeed对集群的支持现状,提出了解决这些问题的办法,最后详细解释了jetspeed保存sesson数据的操作,这将对jetspeed的改造有帮助。

1 、 集群背景介绍

1.1 术语定义

服务软体是b/s或c/s结构的s部分,是为b或c提供服务的服务性软件系统。

服务硬体指提供计算服务的硬件、比如pc机、pc服务器。

服务实体通指服务软体和服务硬体。

客户端指接受服务实体服务的软件或硬件。

1.2 两大关键特性

集群是一组协同工作的服务实体,用以提供比单一服务实体更具扩展性与可用性的服务平台。在客户端看来,一个集群就象是一个服务实体,但事实上集群由一组服务实体组成。与单一服务实体相比较,集群提供了以下两个关键特性:

可扩展性--集群的性能不限于单一的服务实体,新的服务实体可以动态地加入到集群,从而增强集群的性能。

高可用性--集群通过服务实体冗余使客户端免于轻易遇到out of service的警告。在集群中,同样的服务可以由多个服务实体提供。如果一个服务实体失败了,另一个服务实体会接管失败的服务实体。集群提供的从一个出错的服务实体恢复到另一个服务实体的功能增强了应用的可用性。

1.3 两大能力

为了具有可扩展性和高可用性特点,集群的必须具备以下两大能力:

负载均衡--负载均衡能把任务比较均衡地分布到集群环境下的计算和网络资源。

错误恢复--由于某种原因,执行某个任务的资源出现故障,另一服务实体中执行同一任务的资源接着完成任务。这种由于一个实体中的资源不能工作,另一个实体中的资源透明的继续完成任务的过程叫错误恢复。

负载均衡和错误恢复都要求各服务实体中有执行同一任务的资源存在,而且对于同一任务的各个资源来说,执行任务所需的信息视图(信息上下文)必须是一样的。

1.4 两大技术

实现集群务必要有以下两大技术:

集群地址--集群由多个服务实体组成,集群客户端通过访问集群的集群地址获取集群内部各服务实体的功能。具有单一集群地址(也叫单一影像)是集群的一个基本特征。维护集群地址的设置被称为负载均衡器。负载均衡器内部负责管理各个服务实体的加入和退出,外部负责集群地址向内部服务实体地址的转换。有的负载均衡器实现真正的负载均衡算法,有的只支持任务的转换。只实现任务转换的负载均衡器适用于支持ACTIVE-STANDBY的集群环境,在那里,集群中只有一个服务实体工作,当正在工作的服务实体发生故障时,负载均衡器把后来的任务转向另外一个服务实体。

内部通信--为了能协同工作、实现负载均衡和错误恢复,集群各实体间必须时常通信,比如负载均衡器对服务实体心跳测试信息、服务实体间任务执行上下文信息的通信。

具有同一个集群地址使得客户端能访问集群提供的计算服务,一个集群地址下隐藏了各个服务实体的内部地址,使得客户要求的计算服务能在各个服务实体之间分布。内部通信是集群能正常运转的基础,它使得集群具有均衡负载和错误恢复的能力。

2 集群配置

 



从上图可知,由服务实体1、服务实体2和负载均衡器组成了一个集群。服务实体1和服务实体2参与对客户端的服务支持工作,均衡负载器为客户端维护集群的单一影像。集群实体间通过内部的通信网交流信息,这种交流机制一般采用组播协议。负载均衡器通过内部通信网探测各服务实体的心跳信息,服务实体间通过内部通信网完成任务资源的传播。可以看出,配置集群主要由配置服务实体和配置负载均衡器两部分组成。本文使用tomcat 4.12、apache 2.0.43配置集群环境,相关软件的部署图如下:

 



服务实体1/2,负载均衡器可以部署在不同的机器上,也可以在同一机器上,本文环境为同一机器。

2.1 准备软件

tomcat是开源servlet \jsp服务器,下载地点http://jakarta.apache.org/ ;

apache 2.0.43 是开源的www服务器,下载地点http://www.apache.org/dist/httpd/binaries/ ;

JavaGroups是一个实现集群服务实体间通信的通信协议,下载地址:http://www.javagroups.com/ ;

Tomcat 会话复制库,基于JavaGroups通信协议,完成集群服务实体间任务执行上下文的复制,下载地址: http://www.filip.net/tomcat/tomcat-javagroups.jar

jk2模块,jk 是mod_jserv的替代者,它是Tomcat-Apache插件,处理Tomcat和Apache之间的通信,在集群配置中充当负载均衡器的作用。 JK2是符合apache 2.x系列的新品,下载地址:http://jakarta.apache.org/builds/jakarta-tomcat- connectors/jk2/release/v2.0.2/bin/ 。

2.2 配置负载均衡器

在apache下配置负载均衡器分为三步,注意每次修改httpd.conf和workers2.properties时不要忘了重新启动apache。

第一步,安装和调试apache

负载均衡器jk2模块是apache www 服务的插件,所以配置负载均衡器就得先安装apache。本文下载的是windows版本 2.0.43,执行setup.exe并回答一些简单问题就可完成apache的任务。值得注意的是,安装并启动apache后如果apache对 http://localhost/ 地址没反应,你得修改apache安装路径下htdocs目录下的index.html.xx文件,比如把index.html.en改成 index.html。

第二步,安装jk2

把下载到的mod_jk2-2.0.43.dll 改成mod_jk2.dll 放到apache的modules目录下,修改apache的httpd.conf,即在LoadModule foo_module modules/mod_foo.so 行下插入mod_jk2模块的装载信息:

# Example:

# LoadModule foo_module modules/mod_foo.so

#

LoadModule jk2_module modules/mod_jk2.dll

第三步,配置jk2

jk2的配置全在一个配置文件中,文件名为workers2.properties,和apache 的httpd.conf放在同一个目录下。以下是这个文件的内容:

#++++++++++++++++++++++++++++++++++++

# only at beginnin. In production uncomment it out

[logger.apache2]

level=DEBUG

#shm必须配

[shm]

file=D:\Program Files\Apache Group\Apache2\logs\shm.file

size=1048576

# 第一个tomcat 的地址

# Example socket channel, override port and host.

[channel.socket:tomcat1]

port=11009

host=127.0.0.1

# 定义第一个工作者指向第一个tomcat

# define the worker

[ajp13:tomcat1]

channel=channel.socket:tomcat1

#第二个tomcat 得地址

# Example socket channel, override port and host.

[channel.socket:tomcat2]

port=12009

host=10.1.36.123

# 定义第二个工作者指向第二个tomcat

# define the worker

[ajp13:tomcat2]

channel=channel.socket:tomcat2

#定义负载均衡器,使其包含两个工作者

[lb:lb1]

worker=ajp13:tomcat2

worker=ajp13:tomcat1

#指定负载均衡器完成单一地址映射,使得apache 服务所在的uri全部指向 两个#tomcat 上的 root Uri mapping

[uri:/*]

group=lb:lb1

#++++++++++++++++++++++++++++++++++++++++++

对于jk2模块的负载均衡配置可参见相关站点,值得提及的是jk2的负载均衡还支持权重分配等优秀功能。

2.3 配置tomcat

同属于一个集群下的两个服务实体,要求功能的同一性,所以我们可先安装和配置第一个tomcat,接着拷贝形成第二个tomcat,最后配置第二个tomcat。

2.3.1 安装第一个tomcat

安装tomcat 非常简单,本文就不再描述。我们假设第一个tomcat的安装路径为d:\tomcat1。

拷贝tomcat-javagroups.jar和javagroups.jar到d:\tomcat1\ server\lib 路径下。

2.3.2 配置第一个tomcat

2.3.2.1 配置jk2

tomcat 中的jk2 connector缺省端口为8009,为了在一台机器上运行两个tomcat,修改D:\Tomcat1\conf\jk2.properties,设置jk2 connector的端口为11009,整个文件内容如下:

#++++++++++++++

channelSocket.port=11009

#++++++++++++++

2.3.2.2 修改server.conf

首先为了让一台机器上运行两个tomcat,修改server.conf的tomcat 停止指令监听端口:

改为



然后打开JK2 AJP connector ,关闭其它connector,下面是JK2 AJP 1.3的样子,这里已把它的端口改为11009:




port="11009" minProcessors="5" maxProcessors="75"

enableLookups="true" redirectPort="8443"

acceptCount="10" debug="0" connectionTimeout="20000"

useURIValidationHack="false"

protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"/>

接着配置需要集群支持的webapp(比如examples) 的context,添加如下manager:


className="org.apache.catalina.session.InMemoryReplicationManager"

protocolStack="UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=32):PING(timeout=3000;

num_initial_members=6):FD(timeout=5000):VERIFY_SUSPECT(timeout=1500):

pbcast.STABLE(desired_avg_gossip=10000):pbcast.NAKACK(gc_lag=10;

retransmit_timeout=3000):UNICAST(timeout=5000;min_wait_time=2000):

MERGE2:FRAG:pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;

shun=false;print_local_addr=false)">



注意protocolStack的值必须在一行内写完。

2.3.3 配置第二个tomcat

我们先把已经配好的第一个tomcat复制一份,形成第二个tomcat,假设路径为d:\tomcat2。

2.3.3.1 配置jk2

修改D:\Tomcat2\conf\jk2.properties,设置jk2 connector的端口12009,整个文件内容如下:

#++++++++++++++

channelSocket.port=12009

#++++++++++++++

2.3.3.2 修改server.conf

有了第一个tomcat的配置我们只需修改server.conf的tomcat 停止指令监听端口:

改为



然后设置JK2 AJP connector 端口为12009。

2.4 运行测试

启动apache,tomcat1和tomcat2。

2.4.1 测试负载均衡

我们先准备两个文件,第一个文件为test.jsp,拷贝到第一个tomcat 的根web应用的目录即d:\tomcat1\webapps\ROOT 下:









Tomcat 1







第二个文件也为test.jsp,拷贝到第二个tomcat 的根web应用的目录即d:\tomcat2\webapps\ROOT 下:









Tomcat 2







从不同的浏览器中多次输入地址http://localhost/test.jsp 会看到不同的颜色,这表明apache中的jk2模块起到了负载均衡的作用。
2.4.2 测试错误恢复

访问url: http://localhost/examples/servlet/SessionExample 可以得到一个关于session的例子,我们用它来测试集群的错误恢复能力。

测试步骤如下:

关闭tomcat1和tomcat2;

启动tomcat1

在浏览器中输入属性名tomcat1和属性值tomcat1再提交,返回的页面显示session中有刚刚输入的tomcat1属性;

启动tomcat2;

过一会后(等待tomcat2和tomcat1通信并复制信息)关闭tomcat1;

在浏览器中输入属性名tomcat2和属性值tomcat2再提交,返回的页面显示session中有刚刚输入的tomcat2属性,还有先前输入的tomcat1属性;

启动tomcat1;

过一会后(等待tomcat2和tomcat1通信并复制信息)关闭tomcat2;

在浏览器中输入属性名tomcat11和属性值tomcat11再提交,返回的页面显示session中有刚刚输入的tomcat11属性,还有先前输入的tomcat1和tomcat2属性;

……

2.4.3 测试多目传输的方法

如果运行测试失败,可以使用下面的JAVAGROUP方法测试机器的多目传输性:

启动多目接收器:

java org.javagroups.tests.McastReceiverTest -mcast_addr 224.10.10.10 -port 5555

启动多目传输器:

java org.javagroups.tests.McastSenderTest -mcast_addr 224.10.10.10 -port 5555

这样你在McastSenderTest窗口中输入内容,应该在McastReceiverWindow中可以看到结果。如果看不到结果,在 McastSenderTest运行参数中加入-ttl 32,如果还不行,可以修改多目地址再试试(注意避开系统保留用的多目地址);如果还不行,就去问问网管吧!

2.4.4 对tomcat-javagroups的修改

tomcat-javagroups.jar中的org.apache.catalina.session.ReplicatedSession类的removeAttribute方法会导致stackoverflow错误,请按下面的代码对其进行修改:

public void removeAttribute(String name, boolean notify, boolean jgnotify) {

super.removeAttribute(name);

if ( jgnotify )

{

SessionMessage msg =

new SessionMessage(notify?SessionMessage.EVT_ATTRIBUTE_REMOVED_WNOTIFY:SessionMessage. EVT_ATTRIBUTE_REMOVED_WONOTIFY,

null,

getId(),

name,

null,

null);

sendMessage(msg);

}

}

public void removeAttribute(String name, boolean notify) {

removeAttribute(name,notify,true);

}

3 jetspeed集群

我们现在知道了如何配置、甚至拥有一个集群环境,接下来本文分析Jetspeed的集群现状,主要包括repository和Session数据;为了使分析具有目的,在分析Jetspeed的集群现状之前,先讲述了集群需求和RunData对象。读者可以用集群环境来验证和调试Jetspeed的集群功能。

3.1 集群要求

《Memory Session Replication》一文中讲述了支持集群的应用程序需注意的要点,现在对关于应用系统开发时应注意的事项总结如下:

保存在Session中的对象必须实现java.io.Serializable接口;

从session中获取对象修改后必须用session.setAttribute方法重置session中的属性,因为只有setAttribute能导致session复制。

Java VM不支持类变量的序列化,所以要注意failover不能依赖类变量;

保证各个服务实体的配置完全一样;

保证session状态是唯一决定当前任务状态的东西,临时文件、类变量等会使得错误恢复难以实现、行为可能琢磨不定;

利用request.setAttribute()保存当前请求级的状态,减少服务实体间通信次数。

尽量不要在session中保存大对象,提高服务实体间通信性能。

3.2 RunData对象

RunData对象概念来自于Turbine,在Jetspeed中RunData对象的类型是DefaultJetspeedRunData,这个类扩展了Turbine中的DefaultTurbineRunData类。Jetspeed系统接到用户浏览器的URL请求,进行计算和信息处理,最后返回给浏览器HTTP代码流的整个过程中的代码都可以访问同一个RunData对象。所以RunData对象是Jetspeed系统中各个代码模块共享信息的机制。

3.3 Jetspeed的Repository

Repository 一般指一个软件系统赖以启动、运行的持久性环境,包括启动Repository和运行Repository两部分。启动Repository用于决定系统启动时的参数,系统运行时不会改变它,如果改变了这些参数,软件系统必须重新启动;运行Repository指实时影响软件系统业务操作的参数,这些参数可以被用户或管理员当系统在线时改变。现在的趋势是:尽量减少启动Repository,而扩大运行Repository;针对Repository的修改最好能使用管理性框架,比如SNMP和JMX。Jetspeed的repository主要在Xreg、psml和Properties文件中实现。

Xreg是jetspeed的注册表,用于登记portlet、control、controller、skin、mediatype等原始资源的定义,jetspeed中缺省地把它实现为文件形式,各种类型有自己的注册表文件;

Psml 是门户结构标记语言的简称,用于组织xreg中的原始资源形成一个对门户视图的定义,当用户使用桌面浏览器访问jetspeed系统时,这个系统根据用户的URL定位一个Psml文档,接着解释这个文档形成HTML代码流返回给浏览器,浏览器展现这个代码流从而形成视窗化的门户视图。Jetspeed中包括了对psml的数据库和文件两种实现方式;

Properties定义了Jetspeed的重要服务及其参数,目前只有文件实现方式。

Jetspeed的启动Repository主要在Properties文件中,运行Repository在xreg和psml中。文件形式的实现大大阻碍了jetspeed支持集群的能力和表现,因为现在很少的应用服务器集群能在一个文件系统上运行,如果Repository需要在运行时改变,就必须同步多个服务实体上的文件,这是一个相当麻烦的问题。如果Repository支持数据库实现形式,Jetspeed可以充分利用数据库的存储和同步机制实现同一个Repository服务于多个Jetspeed。所以要想 jetspeed支持集群、拥有更佳表现,对Repository的数据库化是一个不可忽视的任务。

支持数据库的集群配置如下图:

 


这个图显示了在数据库集群环境下的jetspeed集群配置,数据库负载均衡器实现数据库集群的单一影像,例子有weblogic server中的multipool datasource,sql server 基于的windows 2000集群的单一集群IP,ORACLE RAC 的支持多连接地址的thin jdbc driver。

3.4 Jetspeed的Session数据

支持集群必须使得各个服务实体针对某个任务的执行环境是相同的,对于jetspeed来说就是针对各个URL请求,session的数据能在各个 jetspeed上复制。这些session被同一个sessionid所标识,这些标识可能来自浏览器的cookies或URL中。我们首先用一个 velocityportlet来显示Jetspeed的session中到底保存了什么数据,这个portlet的注册名字为 SessionPortlet。

3.4.1 SessionPortlet

SessionPortlet是一个velocityPortlet,其类名可以是CustomizerVelocityPortlet或 VelocityPortlet,一般情况下没有必要开发一个新的portlet class。关于如何开发部署portlet的教程可见参考部分,现在我们分注册、控制助手、portlet模版和运行来讲述这个portlet。

3.4.1.1 注册

SessionPortlet用于显示目前的session数据。它在xreg中的注册代码为:


parent="CustomizerVelocity" application="false">





check infomation in session



org.apache.jetspeed.portal.portlets.CustomizerVelocityPortlet


posted on 2007-10-16 01:52 前方的路 阅读(496) 评论(0)  编辑  收藏 所属分类: Java技术

只有注册用户登录后才能发表评论。


网站导航: