BEA WebLogic Server (WLS)是使用最广泛的J2EE 应用服务器,对于大多数企业类情形来说,它一直是最有吸引力的平台。
作为对J2EE 1.3支持的一部分, Java消息服务(JMS)已嵌入在WLS之内。它的实现利用了很多WLS的嵌入式特性,比较直观易懂。对于WLS这样的主流产品而言,实现中等规模的JMS确实是很有价值的。
尽管新增了内嵌的JMS,WLS仍然保留着多样性,可扩展性已及实用性,即除了提供本地的功能以外,也对第三方解决复杂消息的方案提供支持。如,当有多种应用服务器,C客户端或者是非Java遗留应用参与其中时,就会要求解决方案覆盖较多的平台;如果有象存储客户端或支持大容量消息这些特殊要求时,专门的解决方案可能更好。如果对经由集群,路由及错误恢复(failover)等的扩展性、实用性要求非常高,则企业系统设计师必须向专门的消息服务供应商寻求解决方案。
应用第三方JMS于高度扩展的、面向关键任务的系统有很多优点,尤其当有Enterprise JavaBean(EJB) 和XA Container-Managed Transaction (CMT) 参与系统时,与仅仅从消息队列取入取出的配置相比,它能够进行更复杂的处理。这个问题的提出主要基于两个方面的考虑:一. WLS 6.x 中实现Java Transaction API(JTA) 和 Java Transaction Service (JTS) 的方式; 二. JMS和J2EE应用服务器在运行阶段和开发阶段相互关联的问题。对第一点来说,与JMS供应商合作是必须的解决方案(除非JMS将其内部交易API公开-read:open source)。对第二点来说,一个完整的解决方案吸引各种各样的设计模式对JMS供应商提供的工具进行补充。
本文探讨了第三方JMS 服务与WLS的集成,并且提出了经由Sonic Software实现SonicMQ WLSAdapter从而解决前面所述两个问题的方法。我们将回顾SonicMQ JMS实现XA 交易的方法以及与非标准的WLS JTA之间建立映射的途径,并进一步演示了围绕客户端连接,装载JNDI,异常处理,以及复杂EJB交互等所有相关问题的处理办法。
WLS XA 交易与第三方JMS
支持Global Transaction(XA)或者CMT,通常意味着要处理特殊的、复杂的问题。当WLS EJB利用其它JMS产品发送或接收消息,并且双方都试图以正常方式参与交易时,经常会以失败告终。这是因为WLS 6.x 的JTA 和JTS是以非标准方式实现的。
按照JMS规范所述,JMS提供者必须遵从JTA的规范,在创建和实用XA资源,即XAConnectionFactory, XAConnection 和XASeesion对象时应该符合JTA的标准。同样地,由XASeesion对象直接提供XAResourec对象时,JMS也必须符合JTA的标准(有关详细情况请参考JMS1.0.2.b规范第八章 http://java.sun.com/products/jms/docs.html)。
假设所有第三方的JMS产品都符合这些标准,那么它们也会期望作为JMS客户端的应用服务器完全遵从JMS规范,从而保证与XA兼容的操作能够顺利完成。WLS在处理XA交易中有四个方面的问题。
1. 没有XAConnectionFactory, XAConnection 或者说 XASession
当J2EE应用服务器设置XA交易时,它期望利用外部JMS提供的XAQueueConnectionFactory 或者是XATopicConnectionFactory对象创建XAConnection和XASession对象。而WLS仅仅创建了JMS 连接和会话对象,因此,XA交易所指定的步骤和第八章所提出的规范并未实现。
2. 从未启用XAResource
XA 交易的实现必须经由XAResource开始。由于WLS没有利用第三方提供的XAConnectionFActory对象,因此也就无从取得XAResource对象了。这样在消息驱动bean的情况下,本来应该在应用服务器的控制之下自动生成的外部XAResource对象也就从未实际进入CMT。同样,会话bean也不能直接调用XAResource,XAResource无法在此处创建。
3. 专有的会话接口
WLS要求外部JMS的会话对象要实现一个指定的专门接口-weblogic.jms.extensions.MDBTransaction。该接口包含一个方法associateTransaction(),WLS将在CMT调用这个方法进入JMS交易管理器。由于这个接口是非标准的,第三方的JMS供应商必须包含一个适配器才能实现它。WLS会在内部检查会话对象是否支持该接口,如果不是,则容器会扔出一个异常。
4. XA交易分支未被串行化
按照JTA规范,所有XA交易的分支必须以串行的方式进行。但WLS是以另一种方式对交易分支进行管理的,它允许由外部交易管理器提供给容器的第二个交易分支在其它交易分支没有完成之前即开始进行。这种情况的发生是由于在WLS中,交易的开始分支和结束分支分属于不同的线程。“开始”线程的动作已经完成,允许下一个交易分支开始,而此时第一个交易分支的“结束”动作还没有完成。兼容JMS1.0.2的产品期望XA交易分支能够遵循JTA的规范,以串行的次序执行,会认为任何重叠执行的交易分支都违反了JTA协议。因此,当发生重叠交易时,依照JMS的实现将扔出异常,除非JMS供应商提供非标准的实现作为变通。
进入WebLogic Server Adapter (WLSAdapter)
尽管有这些问题存在,想加入WebLogic 市场的第三方JMS供应商对于提供集成方案仍然具有很明确的目标。大部分的供应商通过包含适配器来弥补JMS 第八章的规则与WLS现有版本的“isws”特性之间的差异。适配器的实现非常引人瞩目,不仅在于它们保证了XA功能的稳定性,而且也在于它们如何提供一流的,可扩展的解决方案。
SonicMQ是先进的企业消息平台,从Sonic Software 到WLSAdapter的方案解决了WLS和SonicMQ之间的集成问题。本方案的实现也涉及到其它重
要的集成难题,包括:
1. 客户端自动连接和JNDI装载。
2. 在开发阶段测试异常处理逻辑时,促进错误的发生。
3. 为复杂的JMS结构提供稳定的设计模板。
XA交易集成
应用服务器提供XA交易功能且支持与第三方JMS的合作,必须具有下述能力:
1. 创建并管理JMS连接和会话。
2. 创建并管理XAConnection和XASession。
3. 启用XAResource。
WLS能够创建并管理JMS连接和会话,但无法创建XA交易和启用XAResource。为了解决这个问题,WLSAdapter对所有的XAConnectionFactories, XAConnection, XASession 和XAResource进行创建和管理。
WLSAdapter创建XASession时,它会同时在JVM内创建一个单独的XAResource 对象(称为singleton),在每个XA交易进行时与WLS的交易管理器联系。在JMS交易管理器内提供的实际的XAResource,由WLSAdapter创建,并以singleton注册,反过来将代理所有的WLS交易管理器调用合适的SonicMQ XAResource。适配器在内部管理所有的SonicMQ XA分支。在消息驱动bean(MDB)的情况下,WLSAdapter会对每个交易自动启用XAResource,而会话bean会通过WLS TxHelper,javax.transaction.Transaction txn=weblogic.transaction.TxHelper.getTransaction(),显式启用XAResource (通过直接调用启用方法:txn.enlistResource(myXAResource)。
这样做的效果相当于JMS适配器为WLS交易管理器提供了一个小型交易管理器作为单独的资源参与交易。由于针对WLS交易管理器的XAResource已能够获得,因此解决了前两个问题。
WLSAdapter解决第三个问题用的是实现BEA专有接口-MDBTransaction的方法,在其会话对象中,在MDB交易时利用associateTransaction()方法触发自动启用方式。由于方法是在适配器的会话对象中实现的,因此WLS不再扔出异常。
最后,WLSAdapter解决第四个问题是通过对XA交易分支进行管理以便确保它们的串行次序。当WLS允许交易分支重叠时它先将SonicMQ的异常存储在缓存中,并将重叠交易分支控制着不执行,直到前一个交易完成以后,再让下一个交易分支开始进行。异常被屏蔽,分支重叠被避免,XA交易与JTA规范达到一致。
利用SonicMQ的WLSAdapter,解决了所有WLS与XA兼容的问题,为企业类JMS提供了一个完整的遵从JTA全局事务协议的解决方案。
集成方面的其它挑战
运行阶段和开发阶段的考虑
引入适配器,为增强企业解决方案的稳定性,加入增值特性提供了一个机会。主要的考虑包括运行时针对代理或连接失败自动重新建立连接;为测试应用级异常控制提供工具(尤其是连接和交易级上的恢复逻辑)。
客户端自动重连
重建连接和错误恢复对任何大型的分布式应用来说都是非常重要的。WebLogic 和SonicMQ都提供了集群和重新连接的功能。图一是一个典型的WebLogic集群配置示意图,该集群拥有两台服务器。
图一 典型的集群配置
集群内的任何WLS都可以访问Topic A 和 Topic B。但是,主题(topic)必须提前创建,主题信息与本地一个专门的服务器相连。在事件实例A继续进行过程中,信息会被导往集群内的其它服务器,Topic A 就不再会被访问到了。
图二演示了WebLogic 集群与SonicMQ集群共同工作的情形,由于利用了WLSAdapter,因而具备了重建连接的功能。
在本例中,无论哪一个WLS实例失败,通过SonicMQ,所有的主题都保持有效。另外,如果任一个SonicMQ代理器失败,所有信息将被自动恢复到备份服务器或服务器上,主题信息并不会丢失。如果在SonicMQ内利用WLSAdapter,则主题能够被动态创建,信息也可以在JMS集群之内共享。
在第一个例子中(没有使用WLSAdapter),要想重新建立连接,则当代理器失败时,EJB中的消息产生者或者同步的消息使用者必须在应用逻辑内捕捉异常的发生,显式的重新建立连接,重新构建所有的会话对象。
WLS确实在MDB内重新建立了连接,但监听器无法重建,因此有可能丢失消息。由WLSAdapter提供的解决方案如下:
1. 对用户来说,连接失败被完全屏蔽。
2. 连接重建依赖于URL列表。
3. 确保会话对象以及消息的产生者和使用者都被重新创建。
由于连接失败和连接重建对用户和业务逻辑是完全透明的,因此开发人员在编写代码,管理连接重建时是完全自由的。
故障插入点
WLSAdapter能够插入故障点以便进行程序跟踪和分析。这样做的目的主要是着眼于解决开发阶段的棘手问题-集成测试,即引入可控制的,但是是实际的故障,以便测试异常捕捉路径。WLSAdapter 提供了两种类型的故障插入:连接失败故障和方法调用故障。
连接失败故障
连接失败故障使应用在指定的方法内暂停。使用这种方法,开发人员可以在应用执行过程中,在外部采取某个动作从而在指定地方起作用。
如,想测试连接失败或代理失败时应用的反应情况,可以随机地拔掉线缆或者关掉代理服务器。这样做虽然可以产生测试实例,但它们无法可靠地再现。利用SonicMQ WLSAdapter,能够在某个特殊的方法执行过程中,如:MDB中的onMessage()方法,强制连接失败发生,从而孤立故障点。当方法被调用时,适配器将使应用暂停,此时,您可以强制代理连接断开,模拟故障情况。当故障点被释放以后,应用的后续执行情况将揭示异常逻辑应付故障的情形。
方法执行故障
方法执行故障在设计思想上与前面的很相似,但它只强制特定的方法扔出一个异常,而不要求开发人员的干预(诸如杀死代理服务器或拔掉线缆等)。当设置了方法的故障点以后,程序在执行到指定的方法时,就会暂停;此时会出现选择:是让方法扔出异常还是继续正常执行。
有10种办法能够用以设置连接故障和方法故障。其中的5种是用于JMS方法,其它的用于XA交易。应用只需要在WLSAdapter中设置故障点,执行有问题的程序和方法即可,无需在应用代码中嵌入临时测试逻辑语句。表一列出了在JMS和XA中有可能设置故障点的方法。
在WebLogic使用故障点插入非常简单,只要将WLSAdapter包放入WebLogic 域启动的类路径(classpath),并在应用服务器的启动标志中加入下列内容:
-Dsonicsw.WLSAdapter.Test.DoFail=true
-Dsonicsw.WLSAdapter.Test.FailType=%1
-Dsonicsw.WLSAdapter.Test.FailPoint=%2
参数%1是“ConnectionDrop”或者是“MethodFailure”;参数%2代表表1中的某个方法。
表三
企业级设计模式
先进的交易设计实现模版可以作为增值特性包含在适配器包之中。使用JMS的企业级EJB通常会要求若干个bean之间以交易的方式进行交互。这些复杂的情形使得为保证稳定性而做的聪明构造和为扩展性而设计的会话缓冲池成为必要。
例如,一般的环境可能会要求MDB作为使用者对用于RFP的Pub/Sub 主题进行监听。当RFP消息到达时,它可能需要将文档经由实体bean存入本地数据库;会话bean将生成响应信息并经由点对点队列发送给请求者。在吞吐量很大的环境中,向外发送的队列可能会出于扩展性的考虑将会话bean放入缓冲池中。在这种情况下,MDB,实体bean,和会话bean都成为单个交易的组成部分,两个两个与JMS交易管理器进行交易。
WLSAdapter完全解决了围绕着企业级的这些问题。它将预制的代码设计样板包含在里面,这些样板支持多个bean之间进行交互。解决方案为消息的生产者和使用者展示了一个稳定的、轻便的、利用无状态会话缓冲池机制的环境。
未来展望
Sonic WLSAdapter中包含5个主要的JMS交易设计模式(参看图三),它们是:
1. 消息驱动bean
2. 消息驱动bean路由器
3. 消息产生bean
4. 消息使用bean
5. 消息使用bean路由器
图三
结论
在本文的第二部分,我们会描述在WLS中,利用SonicMQ和WLSAdapter作为JMS解决方案的部分设计模式的实现。具体的实现将会涉及到:
1. 消息驱动bean (与队列监听器)
2. 消息驱动bean (与主题监听器和连接重建)
3. 消息使用bean
4. 消息产生bean(与JMS交叉域和连接重建)
我们将对前述的例子使用多个bean之间利用RFI/RFP进行会话的组合设计模式。
说明:
提出了这么多问题,可能会有人问:WebLogic 是如何将JMS嵌入其中并运行的?它又是如何通过Sun的J2EE 1.3 CTS的?答案来自两个方面:第一,Sun CTS 只从API级别证实其遵从规范,并没有对实现进行规范,也就意味着很多内部功能是灵活的。这也引出了第二个答案:嵌入的JMS与WLS容器的其它部分共享交易管理器。由于只有一个交易管理器对交易进行处理,因此WLS能够在自己的环境下(以非标准的方式)进行所有的XA集成,同时又与CTS API级别的要求相符合。