分享

企业服务总线解决方案剖析,第 4 部分: 企业服务总线的实施策略与总线集成

 qrzhcd 2010-12-03

引言

在企业服务总线应用解决方案系列的前面三篇文章中,作者对ESB的技术特征,ESB在WAS6 SIBus上的实现,以及在WBI MB5上的实现分别作了较为详细的论述,相信大家都对ESB已经有了一定程度的理解。总而言之,ESB是SOA体系架构中的信息流动与交换的基础。ESB的参与主体是服务,总线提供了服务间消息的识别,转换与路由的载体。但是,看起来,读者可能还会有一定的疑惑,ESB首先是一种概念,实现的方案又很灵活,最终支持ESB的产品也很多,那么,前面介绍过的ESB实施方案与具体技术各自适用的场合有什么特点?基于不同实施方案的ESB又是如何互联的呢?本文将对上述问题加以总结。


IBM对ESB的产品支持

到目前为止,IBM专门支持ESB实施的主要有3种产品,WAS6 SIBUS,WAS ESB,和WBI Message Broker。这里按照他们出现的先后顺序简单地介绍一下他们的使用场合:

1) WBI Message Broker

最早提出Message Broker(或它的前身Event Broker)的主要目的,是针对中间件平台不同消息格式的自动转换与路由,支持Web Service(SOAP), MQ, JMS 等不同中间件平台的消息互联以及与现有系统的消息集成。因此,虽然Message Broker一开始主要是针对EAI的一种集成方案,你仍然可以从中看出Message Broker的设计初衷与我们现在的ESB的思想是基本一致的。尽管Message Broker出现的时候还没有明确的ESB概念,但是,随后IBM在SOA上投入了巨大的努力,作为SOA基础架构的ESB,也得到了非常的关注。Message Broker逐渐发展成为专门的ESB实施工具,而且依托完善的MQ消息平台,它对ESB的支持是重量级的,是目前构建ESB最强大的产品。确实,理论上大多数常见类型的消息都可以通过WBI Message Broker加入到SOA的实施场景中。而且,更重要的是Message Broker是真正适合复杂企业环境的ESB实施方式,它的成熟性与性能都是几个方案中最好的。唯一的不足是,如果应用在不很复杂的企业应用环境中,会略显笨重。而它使用的ESQL语言,由于不是基于开放标准的,也会对使用者的学习曲线有一定影响。

2) WAS6 SIBus

我们前面已经提及SOA架构与面向消息的中间件之间密不可分的关系。为了更好的支持SOA, IBM重新开发了内嵌在WAS应用服务器中的消息服务实现。因此,从WAS6 以后的内嵌消息引擎不再是原来的MQ的简版,而是一种功能更强的更稳定的消息平台- WPM(WebSphere Platform Messaging)。它是一个纯JAVA的实现,符合JMS的规范,而且提供了很多扩展。能够很好的同时支持面向服务和面向消息两种编程模式。因此,能够将服务与消息很好的整合在一起。SIBus是一种依托WAS6 应用服务器平台的ESB实现,支持Web Service, JMS 和MQ的消息互联与转换。它的应用场景应该是基于WAS的环境中,面向Web service与JMS类型的企业服务。它的问题主要是开发的难度比较大,由于没有很好的开发工具的支持,开发者需要有较丰富的J2EE/EJB的开发经验,而且还需要通晓WAS6 SIBus的相关API与配置,这无疑限制了SIBus的进一步发展。

3) WAS ESB

WebSphere ESB是 IBM 正式发布的独立ESB产品。它目前所能覆盖的平台只有WAS。看起来与SIBus有些相似,但实际上它发布的目的主要是补充WBI Message Broker。我们前面讲过,WBI Message Broker实施的场景是复杂的企业IT架构,但是一般规模的企业可能对采用这种昂贵的解决方案有所顾虑。那么在这种环境下,小规模的ESB解决方案,WAS ESB是性价比更好的选择。但是,WAS ESB将更倾向于提供只涉及Web服务的总线,这与Message Broker的广泛适用性有一定差距。WAS ESB对SIBus,如果单从体系结构的角度他们都基于WAS的WPM,象一对孪生兄弟。他们最重要的区别在于WAS ESB提供了基于SCA的开发模式和完备的开发工具,并且提供了预先定义的元中介(Mediation Bean)。这样用户通过工具WID (WebSphere Integration Developer),可以采用拖拽/配置的方式简单地开发中介的信息流, 实现ESB不再是复杂的任务。而SCA(Services Component Architecture)组件对用户屏蔽了底层的实现细节,WPM或SIBus中介句柄(Mediation Handler)对用户来说是不可见的。关于WAS ESB中的SCA开发模式,笔者将另外撰文,这里不再赘述。总而言之, WAS ESB可以被视为ESB实施的简化版,适用于不需要Message Broker复杂性的相对简单的环境。它相比SIBus而言,具有开发界面友好的优势,但由于采用SCA封装底层的服务,可以想见在它的早期版本可能会带来性能上的一定损失。


图 1:WAS ESB与 WBI Message Broker的比较
图 1:WAS ESB与 WBI Message Broker的比较

这是一张关于WAS ESB与WBI Message Broker关系的预测图,希望大家能从中得到感性的认识。针对不同的场景和开发者的技术经验,采用更合理的设计方案。


SIBus与Message Broker的集成

根据我们前面的讲解,无论采用哪一种ESB解决方案,ESB的各个总线之间应该是可以互联的。至少采用IBM产品所开发的ESB总线都因该能够顺利地集成在一起,这样ESB的设想才能成立。用户在SOA和ESB上的投资能得到有效的保护,这也是SOA倡导的核心思想-重用。单纯用SIBus或Message Broker构建的同类ESB总线,它们之间的交互方式我们在这里就不再讨论了,欢迎大家阅读WAS的信息中心(infocenter)找到答案,技术上的实现并不困难。比较难办的是SIBus(或WAS ESB)与WBI Message Broker如何实现互联。下面我们将就这一问题加以讨论。

在本系列文章的第二和第三部分中,我们已经分别介绍了两个实例,这里我们将在他们的基础上延伸出一个新的案例场景,实现SIBus的总线与Message Broker 总线的互联。本样例首先包含一个的零部件价格查询模块,某制造企业所需要的零配件可能来自各个厂商,也有可能是自己制造的,同时,它所制造的零件也可能被它的内部用户或者外部用户来查询。由于零件的价格变化比较频繁,所以这些价格的查询需要是即时的价格。这一零件价格查询的样例已经在本系列的第二部分中以WAS6 的SIBus的方式上实现。同时,在这家企业的订单请求处理系统中,企业中的订单管理系统接收到客户的订单请求后,首先到库存管理系统中检查当前库存能否满足订单的要求,如果不能满足则需要到生产制造系统中去安排生产,最后向用户发出订单确认。在本系列的第三部分中,订单系统在WBI Message Broker上实现。我们现在设计这样一个场景,用户在查询订单价格的时候,可以直接选择,当某零件是自己制造的且库存为零的时候,向订单子系统直接发出订单请求。这是一个单向的服务调用,订单的生产状态被放到一个队列中供查询。

这样一个案例涉及两个ESB总线的互联。实质上我们要考虑的是两个ESB底层消息中间件如何进行不同格式的消息转换以及不同体系的消息目的地地址如何相互定位。


SIBus与MQ的消息集成

我们在Message Broker中实现了一个消息流,其中集成了两个生产系统暴露出的订单请求的Web服务。一个是公司内部的甲地的制造企业的生产产品的Web服务接口,而另外一个则是公司内部的乙地的制造企业的订单请求的Web服务接口。而产品的订单请求具体是到甲厂还是乙厂生产,则取决下订单时所携带的路由信息。

Message Broker的消息流处理的是MQ的队列的消息,因此SIBus与Message Broker的互联实质上只是SIBus与MQ的互联。SIBus只会与WBI Message Broker的消息流的入队列和出队列交互。SIBus将订单请求放到Message Broker的入队列中,而Message Broker会将消息处理完后放到出队列中。因此在我们这个场景中,我们需要做的就是在用户查询自己的零件的价格时,如果该零件的库存量为零,就需要通过SIBus向Message Broker部署的消息流的入队列发送一条消息。并且通过读写Message Broker处理完放入到其MQ出队列中的消息查询所下订单的状态。


图2:SIBus与MB之间连接时的业务流程
图2:SIBus与MB之间连接时的业务流程

Websphere 6支持服务集成总线(SIBus)与Websphere MQ的互联,通过两者的互联,可以实现消息在SIBUS与MQ平台之间信息流的互通,而用户则无需考虑其中的消息格式的转换和寻址。

实现SIBus与MQ互联,需要做的主要工作是在SIBus和MQ中配置与对方通信的相应配置。由于SIBus与MQ是两个单独的产品,所以它们之间的通信需要在配置时使用相同的名称来达到识别的目的。

在SIBus上需要定义外部总线,消息引擎的MQ链接等。其中的消息引擎的MQ链接是关键之处,其发送方通道的配置告诉SIBus如何找到Websphere MQ的队列管理器,而接受方通道则是从MQ接受消息。

在Websphere MQ中的配置相对来说则更易理解,因为MQ中的配置其实就是与远程队列管理器的配置一样。在MQ看来,SIBus上的消息引擎似乎就是一个远程主机上的MQ队列管理器,通过在MQ上定义发送方通道和传输队列,就可以实现两者的连接。如果需要从MQ上发送一个消息到达SIBus上只需在MQ上定义一个远程队列。远程队列的作用就是将消息映射回SIBus上定义的本地队列中。

下面分别介绍在SIBus与MQ中需要做的配置,以及在配置完成后如何定义队列使的消息可以实现在SIBus和MQ之间自由发送。详细的配置步骤会在样例下载中有安装文档说明,这里只是介绍重要的概念。


SIBus中的配置

1)首先需要在SIBus中定义外部总线,需要注意的是必须将"路由定义类型"选为"直接,MQ链接",这说明了外部总线的类型。当需要在Websphere中互联SIBus时就需要定义外部总线。这里我们虽然不是SIBus之间的互联,但是为了和Websphere之外的MQ连接,也需要定义外部总线。在外部总线上我们可以定义属于其的外部目标,而这个外部目标将扮演MQ中的队列在SIBus中的代理。下面我们在配置消息传递引擎上的MQ链接时,需要使用这个外部总线名。

2)定义消息传递引擎,把服务器作为总线成员添加后,总线上就会有对应的消息传递引擎。消息传递引擎会实际负责与MQ通信的处理。我们需要在消息传递引擎中创建"Websphere MQ链接"来设置其与MQ互联的参数。

选择"LOCALBUS"的"其他属性"=>"消息传递引擎"。单击引擎名,选择"其他属性"=>"Websphere MQ链接",一共有四个步骤需要完成。分别详细说明如下。

步骤1、链接名称设置为"BusToMQ",外部总线选择"FOREIGN_BUS",队列管理器名称"QM_TheBus",单击"下一步"。

链接名称是一个可选的参数,可以自由命名。但是外部总线名称必须选择在此之前创建的外部总线,例中为"FOREIGN_BUS"。队列管理器的名称也很重要,前面说过,消息传递引擎在MQ看来就类似一个远程的MQ,而MQ与SIBus的通信方式与普通的远程主机上的MQ的通信的配置并没有什么不同。既然消息传递引擎模拟MQ,那么我们就需要定义队列管理器的名称。例中为QM_TheBus,这个名称在后面MQ的配置仍然会发挥作用。它必须与MQ中定义的发送方通道的传输队列的名称一致。它也是在MQ中定义一个远程队列时所映射到的SIBus上的本地队列的队列管理器的名称。


图 3:设置一般Websphere MQ链接属性
图 3:设置一般Websphere MQ链接属性

步骤2:发送方通道 WebSphere MQ 链接属性。发送方通道和接收方通道成对地起作用。该通道将成为用于将消息从总线发送到 WebSphere MQ 的连接。它需要与我们的MQ的队列管理器所使用的名称、主机名和端口相匹配,以接收来自总线的消息。缺省情况下,队列管理器使用端口 1414 接收传入的消息。由于我们的样例中MQ与SIBus存在于同一台主机上,因此主机名为localhost。这也是Message Broker所部署的消息流所在的主机名。

需要注意的是这里定义的发送方MQ通道名必须与后面MQ配置中定义的接受方通道名一致。在没有启用安全性的情况下,传输链选择如图所示的OutboundBasicMQLink


图4:设置发送方通道Websphere MQ链接属性
图4:设置发送方通道Websphere MQ链接属性

步骤3:接受方通道的名称必须与MQ中定义的发送方通道的名称设置一致,输入"MQToBus"。

步骤4:其他所有的选项都使用缺省选项,保存之。


MQ中的配置

MQ中的配置主要是两个通道,一个是用来接受SIBus的消息传递引擎发送过来的接受方通道,其名称必须与SIBus中消息传递引擎的发送方通道名称一致。另外一个是用来向消息传递引擎发送消息的发送方通道,需要首先定义一个传输队列,并且设置远程主机的地址和端口。

1) 创建传输队列

在Websphere MQ资源管理器的队列中新建一个本地队列,名称设置为"QM_TheBus",使用类型选择为"传输"。

2) 定义MQ发送方通道

在Websphere MQ资源管理器中选择高级=>通道,选择新建发送方通道。

  • Channel Name:MQToBus(该名称必须是在定义 MQ 链接上的接收方队列时所使用的名称)
  • Transmission Protocol:TCP/IP
  • Connection Name:运行 SIBus(端口)的计算机的主机名。对于缺省的独立的 WebSphere Application Server 安装,该值为 localhost(5558)。样例中为5559,可以在Websphere的端口中查到该SIB_MQ_ENDPOINT_ADDRESS 端口的值。
  • Transmission Queue:QM_TheBus。

图 5:设置MQ发送方通道
图 5:设置MQ发送方通道

3)定义接受方通道

同样在高级=>通道中新建一个通道,这次选择接受方通道。将通道名称设置成SIBus中定义的发送方通道的名称"busToMQ",传输协议选择"TCP/IP"。


从SIBus向MQ发送消息

现在SIBus与MQ互联必需的两者之间的配置已经完成了。为了使订单请求能够从SIBus上到达MQ,我们需要在SIBus上定义一个远程目标(Foreign Destination)。这个远程目标是Message Broker的MQ入队列在SIBus上的代理。发送到SIBus上的这个远程目标的消息将会通过SIBus上的消息传递引擎和MQ的接受方通道最终达到MQ的队列管理器上的队列中。订单消息到达这个队列后,因为是Message Broker部署的消息流的入队列,Message Broker会取走这个消息,随后做处理,处理后的消息会存放在Message Broker定义的出队列中。例中MQ的队列管理器为WBRK_QM.。

1) 在总线的"其他属性"=>"目标",点击进入,选择新建,目标类型选择"外部"。

2) 设置属性

  • 标识:ForeignQueue@WBRK_QM(必须是WBRK_QM队列管理器上真实存在的队列ForeignQueue,若不存在需要首先创建这个队列)
  • 总线:FOREIGN_BUS(外部总线,该外部总线通过消息传递引擎链接到MQ上的WBRK_QM队列管理器)

图6:在SIBus中定义映射到MQ中队列的外部目标
图6:在SIBus中定义映射到MQ中队列的外部目标

从MQ向SIBus发送消息

Message Broker处理结束的订单状态的消息到达MQ出队列后,我们需要将它发送到SIBus上。为了完成这个任务,需要分别在SIBus上定义队列目标和在MQ上定义远程队列。SIBus上的队列目标的创建与外部目标的创建过程类似,只是目标类型必须选择"队列"而不是"外部"。SIBus上的队列(例中为LocalQueue)创建成功后,我们就可以在MQ的队列管理器(例中为WBRK_QM)定义一个远程队列映射到SIBus上的队列目标LocalQueue。为了与Message Broker消息流的处理集成起来,这里在MQ中定义的远程队列也必须同时是在Message Broker中的消息流的出队列。

1)在WebSphere MQ队列管理器中选择 WBRK_QM队列管理器,扩展Queue,右键选择New=>Remote Queue Definition

2)输入或设置以下值

  • Queue Name: ForeignQueue
  • Remote Queue Name: LocalQueue(必须是SIBus上的同名的本地队列)
  • Remote Queue Manager Name: QM_TheBus(必须是创建MQ链接时设置的队列管理器的名称)
  • Transmission Queue Name: QM_TheBus(传输队列的名称)

图7:在MQ中定义映射到SIBus中的队列目标的远程队列
图7:在MQ中定义映射到SIBus中的队列目标的远程队列

Message Broker中的消息转换

前面讲述的是如何在两个不同的策略实现的ESB上做寻址,但是当消息到达Message Broker实现的总线时,为了能够调用Message Broker的消息流中集成的制造厂的订单请求Web服务接口,我们需要对消息的格式进行转换。

Message Broker中对于消息的处理有很好的语言支持,也就是ESQL,通过它我们可以很方便的根据MQ的消息体中的内容,构造新的SOAP消息。在Web服务返回后,我们需要根据返回的SOAP消息体构建新的MQ消息。

消息的转换的处理流程如下图所示。上方的消息流程是完成路由到甲或乙制造厂的功能。最下方的消息流是订单请求路由到乙制造厂的处理流程。BJMQ2Http计算节点完成MQ的消息到HttpRequest1集成的乙制造厂的Web服务的SOAP请求消息的转换,而BJhttp2mq则完成的是对SOAP返回消息到MQ消息的转换。


图8:MB中的订单总线完整的消息流
图8:MB中的订单总线完整的消息流

在开发从MQ消息请求制造厂的订单请求Web服务时,需要注意的几个问题是

1) MQ的消息头

为了能将Web服务的返回的SOAP消息重新构造成MQ的消息,我们需要在MQ的消息转换成SOAP消息保留MQ的头消息。在ESQL中通过将MQ的头消息保存到环境中可以达到这个目的。

SET Environment.MySavedMQMD = InputRoot.MQMD;

2) Message Broker中如何集成Web服务的调用

在Message Broker中提供了一组内嵌的节点可以集成Web服务的调用,HttpRequest节点就是一个用来配置集成Web服务请求的节点。在HttpRequest节点的属性中可以设置甲或乙制造厂的订单请求的Web服务的URL,如下图所示:


图9:设置HttpRequest节点的Web服务地址
图9:设置HttpRequest节点的Web服务地址

3) 在ESQL中使用XMLNS域处理消息格式的转换

在我们的场景中为了实现自解析而不需要定义消息集的目的,我们设定了HttpRequest和消息流中的MQ的域是XMLNS。XMLNS域对带命名空间的XML格式消息可以实现自解析。这里的转换工作我们使用ESQL语言完成,构建消息的过程必须参照特定的Web服务的SOAP的请求的描述。使用ESQL语言处理XMLNS域的消息与普通的XML域的不同,主要在命名空间的处理上。自解析的XML消息在Message Broker中会解析成一颗消息树,但是在SOAP的请求消息中会有很多的命名空间,这是我们需要处理的额外内容。这些命名空间通常包括 "http://schemas./soap/envelope/"等,以及我们的场景中的Web服务定义的命名空间"http://csdl.ibm.com"。请参阅在Message Broker Toolkit 的帮助文档中ESQL中关于XMLNS的部分。我们场景中的MQ和SOAP消息之间的转换的ESQL的代码在附带的样例下载中。


小结

到这里,SIBus与WBI Message Broker的集成工作已经完成。在我们的场景中,不同策略实现的ESB的互联发生在当用户查询自己生产的零件的价格并且发现零件库存为零。这时会往SIBus上的外部目标写入订单请求消息。通过互联配置,订单请求消息会到达MQ的队列中。

Message Broker的消息流根据消息的内容路由到甲或乙两个不同的制造厂。Message Broker的消息流会将MQ的消息转换成SOAP的请求消息后,请求甲或乙两个不同制造厂的提供的订单请求接口。而订单请求的状态返回也是SOAP的返回消息,再转换成MQ的消息后,将会放到MQ的出队列中。而MQ出队列的消息通过互联的配置又路由回了SIBus中。

回顾一下我们所做的主要工作在于如何在SIBus和MQ中配置与对方的通信,因为是相互独立的软件,所以经常遇到必须将某些名称设置为一致的情况,这是读者在实际配置时必须要注意的一点。由于篇幅的关系,随文可以下载的样例中包含了更加详细的配置说明过程。


参考资料

作者简介

张军,IBM SOA Design Center 工程师,对J2EE、WebService, SIBus以及WBI Message Broker有着丰富的实践经验。

李珉,IBM SOA Design Center 高级工程师,技术经理,曾领导WAS6 SIBus的测试工作,对ESB的技术发展一直有所关注。

刘朝俊 IBM SOA Design Center 工程师。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多