级别: 中级 Brian Hulse, 软件工程师, IBM
Callum Jackson, 软件工程师, IBM Fenglian Xu, 软件工程师, IBM
2009 年 9 月 01 日 本系列文章介绍了 WebSphere ESB V6.2 及其相关工具 WebSphere Integration Developer 中的新特性和增强特性,包括传输协议绑定、数据绑定功能、中介原语(mediation primitives)和声明式流控制。第 2 部分描述服务网关和 Service Policy 特性。
简介
 | |
点击如下链接,查看本系列更多对 WebSphere ESB V6.2 新特性的介绍:
更多关于 WebSphere ESB 的技术资源,请参考:
|
|
本系列文章描述 IBM® WebSphere® Enterprise Service Bus V6.2 的新特性。第 2 部分介绍服务网关模式,并展示如何为 Web 服务创建服务网关。
什么是服务网关?
服务网关(service gateway)是一种实体,可以接收任何消息、执行通常的处理(例如记录消息或者为消息添加头部),然后将消息路由到目的地。
这样的定义又引起服务网关分类的问题 —— “通常的处理” 是否包括修改消息的主体? WebSphere ESB 有两种类型的服务网关:
- 动态服务网关(主体不可知)
- 这种网关模式只修改消息的头部信息。
- 静态服务网关(主体可知)
- 这种网关模式可同时修改消息主体和头部中的信息。
在本文的后面,这两种模式将被转换成 SCA 模式,以实现这两种网关。
对 WebSphere ESB 编程模型的增强
将对服务网关模式的支持集成到 WebSphere ESB 需要对编程模型进行一些扩展。本节将描述这些增强。
新的中介原语
WebSphere ESB 中介原语是可重用的构建块,应用程序开发人员可以用它们来构建中介流。服务网关支持中实现了两个新的中介原语:
DataHandler 原语
DataHandler 原语可用于将一种消息结构转换成另一种消息结构。这个原语不同于之前的 XSLT、BO Mapper 和 Message Element Setter 等转换原语,它用于 wire 格式(例如 JMSTextBody)与业务对象之间的转换。
另一个新的转换原语将一种业务对象结构转换成另一种业务对象结构。
顾名思义,DataHandler 原语让中介开发人员在 WebSphere ESB 中使用定制的 DataHandler 将消息主体从一种格式转换成另一种格式。
然后,中介开发人员可以推迟输出的消息的解析,只在 Mediation Flow 组件中在需要时才完成解析。编写 JMS 中介时就是如此。可以通过 JMS Text DataBinding 配置导入和导出,JMS Text DataBinding 将入站消息的内容放入到一种通用格式中。在 Mediation Flow 组件中,可能需要对主体进行操纵,这时需要将消息从协议格式转换成业务对象,以便其他原语访问和操纵消息主体。
和处理其他中介原语一样,WebSphere Integration Developer 提供将属性和终端与 DataHandler 原语关联的工具,以便定制 DataHandler 的行为。DataHandler 属性视图可用于配置两种动作:
图 1. DataHandler 细节属性面板

DataHandler 原语有以下属性:
- DataHandler configuration —— 表明原语将使用的 dataHandler 类或配置。单击 Browse 打开 DataHandler configuration 窗口,选择一种有效的配置。
- Output message field refinements —— 这个表提供与 SetMessageType 原语相同的功能,但是被嵌入到 DataHandler 原语中。中介开发人员可以通过它将 SOM 的弱类型字段断言为具体类型。SetMessageType 原语在运行时不会完成任何处理(除非启用了验证),而这些断言则对于 DataHandler 原语的处理非常关键。DataHandler 原语的输入和输出消息可以不同,因此在这种情况下 DataHandler 原语必须生成全新的输出消息。如果 Target XPath 字段值所标识的 Xpath 位置包含有消息的一个弱类型结构,那么它需要理解在这个实例中该弱类型的结构应该是什么。在上面的图 1 中,输出终端有一个在
/body/message 指定的 anyType 元素。
对于 /body/message 有一个断言,将类型定义为 {http://com.ibm.wbiserver.gateway/schema}TextBody。因此,当选择 Target XPath 时,可导航到 /body/message/value。
Action —— 有两种动作受支持:
- 从本地数据格式转换为业务对象 —— 该动作调用指定 DataHandler 的 transform 方法。如果 SMO 包括一个以逗号分隔的字符串值,而必须将它解析成特定的 BO,那么可以使用该动作。
- 从业务对象转换为本地数据格式 —— 该动作调用指定 DataHandler 的 transformInto 方法。如果必须将 BO 转换成以逗号分隔的字符串,可以使用该动作。
Source XPath —— 表示对象在被传递到 DataHandler 的源 SMO 中的位置。例如:/body/operation1/input1/value。
Target XPath —— 表示目标 SMO 的位置,其中存储 DataHandler 输出。目标 SMO 被定义为输出终端的类型。DataHandler 原语有一个输入终端、一个输出终端和一个失败(fail)终端。
图 2. DataHandler 中介原语

表 1. DataHandler 终端
| 终端类型 | 名称 | 描述 |
|---|
| Input | in | 该终端接收传入的消息 | | Output | out | 当 DataHandler 完成转换时,该终端被触发 | | Fail | fail | 当原语遇到意外失败时,该终端被触发 |
Type Filter 原语
Type Filter 原语提供查询实例消息的功能,以确定它是否属于某种已配置的类型。要了解更多信息,请参阅
本系列第 1 部分。
新的绑定功能
服务网关模式是跨整个 Mediation 模块实现的,并不仅限于 Mediation Flow 组件。其中增加了一些新的绑定功能:
服务网关接口
V6.2 新增了服务网关接口,该接口由 WebSphere Integration Developer 提供。它可以接收所有传入服务网关的消息,无论消息的类型是什么。如果很多自动化步骤依赖于这个接口的存在,那么在创建任何服务网关时,都必须使用该接口。
图 3. 服务网关接口

乍一看来,服务网关接口的弱类型字段用于存放实际业务对象,该业务对象是在请求经过常规的具体类型绑定处理后生成的,然而事实并非如此。服务网关收到的任何消息将被包装到一个协议级业务对象(例如用于 Web 服务的 TextBody)中,后者被放在 anyType 消息字段中。之所以使用弱类型字段,是为了允许一个单一接口处理多种类型的请求,即 JMS、MQ、HTTP 和 Web 服务请求:
图 4. 服务网关接口可能的断言

如图 3 所示,服务网关接口有两个操作:requestOnly 和 requestResponse。
requestOnly 消息处理单向(one-way)消息请求,而 requestResponse 则处理双向(two-way)消息请求。
消息绑定支持
服务网关模式支持传入系统的所有 JMS 和 MQ 消息。为了支持这些消息类型,提供了一个服务网关数据绑定和用于每种协议的函数选择器。数据绑定确定入站消息的类型,并生成 5 种内建 JMS 业务对象类型之一的业务对象:
- JMSTextBody
- JMSBytesBody
- JMSMapBody
- JMSStreamBody
- JMSObjectBody
每当使用服务网关接口生成 Export 或 Import 时,都应该使用服务网关数据绑定。当前预定义的 JMS 数据绑定只能转换到这几种业务对象类型之一,而服务网关数据绑定则可以转换到所有 5 种类型。
服务网关函数选择器提供一种内建的机制,以确定入站消息是单向还是双向的。函数选择器是确定操作类型的惟一机制。用户可以随意创建和实现他们自己的函数选择器。默认情况下,JMS 函数选择器在消息头部属性中查找指定的 replyTo 队列,如果找到该队列,则将请求认定为双向操作。如果没有找到该字段,则认定为 “单向” 操作。而 MQ 函数选择器则查询 MQ 消息描述符(MQMD)中请求的 MsgType 字段,如果它被定义为 MQMT_REQUEST,则将请求认定为双向的,否则,如果它被设为 MQMT_DATAGRAM,则将操作认定为单向的。
HTTP 绑定支持
与消息绑定一样,WebSphere ESB V6.2 中提供了用于 HTTP 绑定的数据绑定和函数选择器。HTTP 服务网关数据绑定判断内容类型是否为 text/*,如果是,则将消息的主体放入 HTTPText 业务对象中。否则,使用 HTTPBytes 业务对象。
HTTP 协议本身没有任何机制来判断入站消息是单向请求还是双向请求,这使得函数选择器的处理复杂化。一个解决方案是将一个 operationMode=oneway 参数附到 URL 上。例如,如果收到下面的 URL:
http://www.anywhere.com/serviceGatewayA,那么函数选择器认定请求为双向的。但是,如果 URL 为:
http://www.anywhere.com/serviceGatewayA?operationMode=oneway,那么函数选择器认定请求为单向的。
Web 服务绑定支持
Web 服务绑定在服务网关模式中也受支持。这里将数据处理器和函数选择器功能添加到 JAX-WS 绑定,并创建一个服务网关数据处理器和函数选择器。Web 服务绑定中的新支持如下图所示:
图 5. Web 服务绑定函数选择器和数据处理器支持

Web 服务数据处理器以相同的方式处理所有的消息,将 Web 服务绑定中原始的 XML 数据直接放入到 TextBody 业务对象结构中。这意味着,业务对象中存放的数据没有经过解析,在某些情况下这样可以取得性能优势,因为不必将数据放入具体业务对象中。但是,缺点是如果不用 DataHandler 原语处理消息,实际上不可能访问消息的主体。
Web 服务函数选择器采用与 HTTP 函数选择器相同的方式确定操作是单向的还是双向的。
用于服务网关的工具加速器
在 WebSphere Integration Developer V6.2 中,增加了一个新的模式向导,用于帮助生成和配置服务网关工件。通过该向导可以创建动态和静态服务网关,下一节将使用该向导创建一个服务网关。
实现服务网关
实现服务网关分为三个步骤:
- 确定消息的服务请求类型
- 确定网络可寻址端点,以便将请求转发到那里
- 完成网关所需的通常的处理
首先,要确定服务请求类型,有很多方法:
- WS 地址信息
- SOAP 动作
- SOAP 头部
- URL 信息 —— 例如,如果网关的端点是
http://anywhere.com/serviceGateway,可以将服务名作为参数添加到它上面:
http://anywhere.com/serviceGateway?serviceName=serviceA。
标识符在该类型的消息的特定服务网关中必须惟一。
现在已确定标识符,接下来必须将它转换成网络可寻址端点,以便将消息转发到那里。有很多方法可以使用:
- 使用 Endpoint Lookup 原语的 WebSphere Service Registry and Repository —— 可以使用 User Properties 将服务标识符传递到 WebSphere Service Registry and Repository。
- 使用策略和 Policy Resolution 原语的 WebSphere Service Registry and Repository —— 通过使用策略附件文档上的 gate 条件中的服务标识符,可以应用不同的中介策略,每个中介策略描述一个不同的端点。第 3 部分将描述这个专题。
- DB Lookup 原语 —— 使用一个 DB 表,将服务标识符映射到实际的端点位置。
- 定制代码 —— 编写定制代码将服务标识符映射到实际的端点位置,以便集成到第三方系统。
最后需要完成服务网关的通常的处理,这取决于所需的功能。这一步可以很简单,例如在画布上放置一个日志记录原语,也可以较复杂,例如需要使用中介原语访问和操纵消息的主体。
服务网关的实现模式
服务网关有两种中介模块实现模式:动态服务网关和静态服务网关。
图 6. 动态服务网关的 SCA 实现

- 多个客户机发送服务请求到同一个端点,该端点是通过一个 export 绑定公布的。
- 使用服务网关接口以及 Web 服务、HTTP、JMS 或 MQ 绑定配置 export 绑定,并定义服务网关数据处理器/数据绑定和函数选择器。
- 使用服务网关将中介流组件定义为一个接口和引用。任何通常的处理都在此阶段完成,例如记录服务请求。
- 使用服务消息对象中包含的信息确定服务的目标地址。
- 使用服务网关接口以及 Web 服务、HTTP、JMS 或 MQ 绑定配置 import 绑定,并定义服务网关数据处理器/数据绑定和函数选择器。
- 服务返回响应,在此阶段同样完成通常的处理,例如记录消息。
第二种模式是静态服务网关,该模式在 SCA 中表示如下:
图 7. 静态服务网关的 SCA 实现

- 多个客户机发送服务请求到同一个端点,该端点是通过一个 export 绑定公布的。
- 使用服务网关接口以及 Web 服务、HTTP、JMS 或 MQ 绑定配置 export 绑定,并定义服务网关数据处理器/数据绑定和函数选择器。
- 使用服务网关将中介流组件定义为一个接口和引用。任何通常的处理都在此阶段完成,例如记录服务请求。在此阶段需要访问消息的主体,因为要使用一个 filter 原语将请求分解成多个部分。
- 然后,将每种消息类型传递到一个 DataHandler 原语,后者将协议包装器业务对象转换为具体业务对象,使下游的原语可以修改消息的主体。
- 使用转换原语,必要时修改消息。
- 使用特定的服务接口配置 import 绑定,选择需要的任何相关的数据处理器/数据绑定和函数选择器。
- 服务返回响应,经过对消息的处理后,使用 DataHandler 原语将具体响应业务对象转换为协议包装器业务对象。
创建第一个服务网关
本节展示如何创建一个动态服务网关,该服务网关将记录所有经过系统的消息。该场景以一家图书订购公司为基础,它具有 2 个基本的 Web 服务:
- Book Dispatching 服务 —— 发送消息到仓库,要求将图书发送给客户。
- Billing 服务 —— 用客户的信用卡支付购书费用。
图 8. Logging 服务网关的架构

由于本文主要关注服务网关,最终的服务包含在附带的项目交换文件中,而关于它们的行为的详细信息则没有提及。要测试这些服务,可使用 Web Service Explorer。本节中开发的服务网关使用前面描述的 URL 方法确定服务的身份,如上面的图 8 所示。
为了消除本文中的依赖性,可使用定制的 Java™ 代码完成从服务标识符到可寻址端点的映射。在第 3 部分,该场景将被扩展为通过中介策略从 WebSphere Service Registry and Repository 提取端点。
您应该熟悉 WebSphere Integration Developer 中应用程序框架构建的基本概念,尤其是中介开发。
- 启动 WebSphere Integration Developer,获得一个新的工作区。
- 导入项目交换文件 ServiceGatewayEndServices.zip。
- 选择 File => Import。
- 选择 Other => Project Interchange。
- 选择 Project Interchange file 并单击 Finish:
图 9. 导入的示例服务

- 创建一个新的名为
BookOrderGateway 的动态服务网关。
- 选择 File => New => Service Gateway。
- 对于 Service Gateway 名称,输入
BookOrderGateway,并单击 Next。
- 选择 Dynamic 选项并单击 Next。
- 如前所述,路由逻辑将用 Java 代码编写以简化依赖,日志记录将写到标准的 WebSphere ESB 数据库。为此,
选择 Write my own logic 和 Log messages in a database,并单击 Next:
图 10. 为网关选择路由和日志记录选项

- 后端的 Web 服务被生成为 SOAP 1.1 服务;选择 Web Service (SOAP 1.1/HTTP) 并单击 Finish。这将生成一个新的中介模块,装配图如下所示:
图 11. 向导创建的初始服务网关

- 双击 BookOrderGateway Mediation Flow Component,这样将装载 Mediation Flow Editor。
- 由于两个后端服务都是双向操作,因此只需要实现 requestResponse 操作。requestOnly 流需要一个小小的修复,以免在部署时出现问题。选择 RouteMessage custom mediation 并删除它。此外,将 LogMessage 原语连接到 CallOut 节点,如下图所示:
图 12. 单向操作修复

- 现在,考虑双向流,选择 requestResponse 操作:
图 13. 向导自动生成的中介流

- 对于服务网关,第一个任务是获取服务标识符,这可以直接在 RouteMessage 定制中介中完成,但是为了将来的可扩展性,这个逻辑将被分离到专用的原语中。
- 首先,创建一个新的业务对象,用于存放服务标识符:选择 File => New => Business Object。
- 对于 Module,选择 BookOrderGateay,并输入业务对象的名称:
ServiceIdentification。
- 单击 Finish。
- 添加一个名为 ID 的字段,其类型为 String,选择 Save 保存文件。
图 14. Service Identification 业务对象

- 添加
ServiceIdentification 业务对象作为 Transient 上下文。
- 展开 Palette 的 Transformation 区。
- 选择 Message Element Setter 原语,将它放到画布上。
- 将该原语重命名为
ExtractServiceIdentifier。
- 删除 Input 节点与 LogMessage 原语之间的连接。
- 将
ExtractServiceIdentifier 连在两者之间,如下图所示:
图 15. 将 Message Element Setter 原语连接到流中

- 选择
ExtractServiceIdentifier 原语,在属性面板中单击 Add。
- 填入详细信息,如下图所示:
图 16. 添加/编辑属性

- 最后一步是用 RouteMessage 原语实现路由逻辑,这一步需要获取临时上下文中的值,并将它转发到相关服务上。下面的代码假定后端服务在默认端口 9080 和本地机器上运行。如果这些值不正确,那么需要定制代码。将以下代码复制到原语中:
String port = "9080";
String hostname = "localhost";
String URI = "http://"+hostname+":"+port+"/";
String serviceIdentification =
((commonj.sdo.DataObject)smo.getContext().getTransient() ).getString("ID");
if(serviceIdentification.equals("billing"))
{
URI = URI + "BillingServiceWeb/sca/BillingExport";
}
else if(serviceIdentification.equals("dispatch"))
{
URI = URI + "DispatchingServiceWeb/sca/DispatchExport";
}
com.ibm.websphere.sibx.smobo.TargetAddressType targetAddress =
com.ibm.websphere.sibx.smobo.ServiceMessageObjectFactory
.eINSTANCE.createTargetAddressType();
targetAddress.setAddress(URI);
smo.getHeaders().getSMOHeader().setTarget(targetAddress);
out.fire(smo);
|
- 在 Mediation Flow Editor 中保存修改:单击 Ctrl + S。
- 启动内建的 WebSphere ESB 或 WebSphere Process Server Test Environment,部署所有 3 个应用程序:
BillingService、
DispatchingService 和 BookOrderGateway。
- 测试服务:
- 在 Business Integration Navigator 中展开后端服务项目:Billing Service => Web Service Ports。
- 右键单击 BillingExport_BillingHttpPort,并选择 Web Services => Test with Web Service Explorer。
- 当前选择的端点将把请求转发到实际的服务。要进行重定向,可单击 Endpoint 区旁边的 Add,并输入:
http://localhost:9080/BookOrderGatewayWeb/sca/BookOrderGatewayExport?serviceName=billing 或
http://localhost:9080/BookOrderGatewayWeb/sca/BookOrderGatewayExport?serviceName=dispatch,为服务的配置定制 URL。单击 Go:
图 17. 更新 Endpoint 信息

- 选择操作,填入相关细节,并单击 Submit。
结束语
- 动态服务网关
- 接受多个客户机请求,并对消息头部执行通常的处理,然后通过一次导入将消息转发到不同的后端服务。
- 静态服务网关
- 接受多个客户机请求,并对消息的头部和主体执行通常的处理。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 完整的 Service Gateway 项目 | ServiceGatewayDynamicComplete.zip | 32 KB | HTTP |
|---|
| 本文的后端服务 | ServiceGatewayEndServices.zip | 19 KB | HTTP |
|---|
参考资料
作者简介  | |  | Brian Hulse 是英国 IBM Hursley 软件实验室 WebSphere ESB 团队的一名高级软件工程师。他在 Hursley 从事软件开发已有 20 年,其中最后 5 年在 SOA 领域工作。 |
 | |  | Callum Jackson 是位于英国赫斯利的 WebSphere Enterprise Service Bus 部门的一名软件工程师,他从 2005 年开始从事产品领域的工作。此前他在 ISSW 从事电信行业的 SOA 应用程序开发工作。 |
 | |  | Fenglian Xu 博士 是在 英国的 IBM Hursley 软件实验室的在 WebSphere Enterprise Service Bus 开发团队的一名软件开发人员。 她专长于 WebSphere MQ JMS bindings,WebSphere Application Server 和 WebSphere Enterprise Service Bus。她曾经工作于许多不同的 IT 公司,包括中间件和应用程序,以及 UK eScience 实验项目 GEODISE,其涉及到工作流和 SOA。 她于 1989 年在中国获得了西安交通大学的应用数学和软件工程的学士学位,并于 1998 年在英国获得了南安普敦大学的计算机科学的博士学位。 |
对本文的评价
|