规格化消息路由从JBI组件(服务殷勤或绑定组件)接收消息交换ME并将其路由到适当的组件进行处理。[This mediated message-exchange processing model decouples service consumers from providers, and allows the NMR to perform additional processing during the lifetime of the message exchange.]
本章中使用WSDL2.0中的术语而不是WSDL1.1。
本节介绍NMR架构中的几个关键概念。NMR的目标是[The goal of the NMR is to allow components acting as service producers and consumers to interoperate with one another in a predictable fashion, using WSDL-based service descriptions as the sole source of coupling between them. This is key to allowing mix-and-match assembly of components, creating the basis of integration solutions and a services infrastructure.]
WSDL [WSDL 2.0, WSDL 1.1]为JBI组件交互提供了基本的模型和描述机制。WSDL提供了一个基于XML消息交换操作的抽象服务模型,该模型可以通过提供特定的绑定信息(将抽象模型映射到实际的通信模型和端点[WSDL 2.0 bindings] 的特定的协议信息)进行扩展。
JBI扩展应用了WSDL的抽象消息模型,可以把NMR看作是一个抽象的WSDL消息系统基础平台[infrastructure],绑定组件和服务引擎在这个平台上提供和使用WSDL定义的服务。
WSDL定义了一项服务提供者和消费者之间的消息交换操作,消息交换参与者依照各方都能够理解的一种消息交换模型进行操作。一组相关联的操作称作“接口”,该接口的实现称作“服务”。一个服务具有一个或多个端点,每个端点通过一种特定的绑定(消息通信协议)为外部系统访问该服务提供入口。
所有的这些WSDL概念都被JBI用于APIs和SPIs中构建服务模型。
JBI引擎和绑定组件可以扮演服务消费者,服务提供者或两者兼之的角色。服务提供者通过端点(endpoint)提供WSDL描述的服务;服务消费者通过开始调用特别操作的消息交换使用服务。服务(service)实现了WSDL的接口,WSDL接口是通过交换抽象定义的消息来描述的一组相关的操作。
因为服务消费者和服务提供者之间通常只共享抽象的服务定义而不是具体的端点信息,所以两者之间是松耦合的。这种结构使得服务提供者的具体实现(如特定协议)对服务消费者来说是透明的。
一个WSDL接口可以具有多个服务实现,服务消费者在查找实现了某个接口的提供者时,可能查找到多个实现了该接口的服务提供者(服务和相关联的端点)。
JBI使用“规格化(normalized)”消息的概念描述服务消费者和提供者之间的交互。一条规格化消息由如下三个主要部分组成:
规格化消息通过抽象WSDL消息类型定义为组件间的交互提供了互操作。
传输通道是绑定组件和服务引擎与NMR之间通信使用的双向通信管道。传输通道构成了服务消费者,提供者和NMR之间的交互契约,即API接口。服务消费者使用传输通道开始服务调用,服务提供者使用传输通道从NMR接收服务调用。既能发起调用服务,又能接收服务调用的组件使用同一个传输通道完成这两种功能。
以一个绑定组件接收JBI系统外部的服务消费者请求为例,当接收这种传入的服务调用请求后,该绑定组件通过其传输通道与NMR交互时必须扮演服务消费者的角色(在此场景中,绑定组件可以看作是一个服务消费者代理)。
每个组件都具有唯一的一个传输通道,因此传输通道的实现必须支持在多线程环境下的并发使用。
运行时激活是服务提供者激活其提供的实际的服务的过程,在该过程中,服务提供者将其实际的服务注册到NMR,使得NMR可以将调用路由到该服务。端点激活分为两步:
向NRM声明一个服务端点是绑定组件或服务引擎向NMR注册一个端点名称的过程。在NMR中声明的端点名称必须有相应的元数据信息详细描述该端点的注册,这部分详细信息在作为组件接口一部分的SPI中进行了详细的描述。
服务调用指服务消费者和服务提供者之间的一个端对端交互的实例。尽管无法在JBI中定义一套完整的服务调用模型,但是JBI实现必须支持如下列表中的交互模式:
上述提到的消费者和提供者角色可能由绑定组件或服务引擎来扮演。当一个绑定组件扮演一个服务消费者的角色时,也就说明存在一个外部的服务消费者;同样的,当一个绑定组件扮演服务提供者角色时,也就说明存在一个外部的服务提供者。当以任意一种角色使用服务引擎时,说明该服务引擎是一个内部参与者。
WSDL 2.0预定义扩展[WSDL 2.0 Extensions]定义了一个消息交换模型(MEP),JBI使用该模型定义消费者节点和提供者节点之间的交互。该模型根据消息类型(normal或fault)和消息流向定义。
MEPs总是站在提供者的角度来理解。例如,在请求回复交互模式中, MEP的定义是in-out,站在提供者的角度来看,请求(Request)是输入(in),回复(Response)是输出(out)。从服务消费者的角度看,消息流的方向正好相反,但是NMR在与服务消费者交互过程中使用的MEP总是从服务提供者的角度来说的。当处理WSDL MEPs时,这是一种惯用的处理方式。In-Out模式示意图如下所示:
如上图所示,第一条消息(请求)是从消费者发送到提供者,从提供者的角度看其方向是输入(in)。第二条消息(回复)是从提供者到消费者,即输出(out)。这些交换是按给出的序列执行的,从提供者的角度这种交换首先是输入一条消息(in),跟着是输出(out)一条消息,因此这种交互模式命名为输入输出(in-out)模式。
消息交换(ME)用作承载构成服务调用一部分的规格化消息的“容器(container)”。ME不仅封装了其实现的消息交换模型中的输入(in)消息和输出(out)消息,它还包含了这些消息的元数据信息以及正在进行的消息交换的状态信息。消息交换代表了JBI本地服务调用的一部分。下表说明了服务调用和消息交换模型之间的关系:
服务调用(Service Invocation) |
消息交换模式MEP (提供者角度) |
One-Way |
In-Only |
Reliable One-Way |
Robust In-Only |
Request-Response |
In-Out |
Request Optional-Response |
In Optional-Out |
表 2 Service Invocation to MEP Mapping
图One-way Service Invocation Between two Service Engines
上图描述了两个本地服务引擎间的单向服务调用:SE1作为一个服务消费者,通过创建并初始化一个包含了消息请求的in-only消息交换调用所需要的服务操作。如上图中的连接线流向所示,SE1将该消息交换实例发送到NMR。
NMR根据该消息交换实例决定由哪一个服务提供者提供该消息交换请求的服务操作,并将其传输给选定的提供者。该对象流转过程从上图NMR和SE2 之间的连接线可以看出。
需要注意的是该图示并不意味着调用方必须在交换完成之前阻塞当前线程的执行。调用方在发送和接收消息时,可以是事件驱动[as shown in the activity diagram, advances the engine’s internal state without necessarily tying up thread resources.]
图SE Invokes Service Provided by Remote JBI Instance: Robust In with Fault Normalized
以下内容描述了上图所示的处于两个不同的JBI环境中的服务引擎之间的可靠的单向调用逻辑。需要注意的是规范中未规定如何联合两个分离的JBI实例,该例中两个JBI实例之间通过BC1和BC2提供的通信协议使得两者作为远程的消费者和提供者而相互可见,并不存在影响两者之间调用执行的特殊关系。
SE1构建并初始化了一个可靠的单向(robust-in)消息实例,并发送到NMR(在构建ME实例的过程中,NMR为该实例设定了一个唯一标识“X”)。NMR选择合适的服务提供者,并将消息交换以可靠的单向消息模式发送给BC1。BC1按照其所实现的协议需求封装消息请求,并将该请求发送给服务提供者,在本例中,恰好是另一个通过BC2发布了一个服务端点的JBI实例JBI2。
当JBI2实例中的BC2组件接收到请求以后,该组件构建一个可靠的单向消息交换实例(“Y”)并发送给NMR。JBI2实例中的NMR选择合适的服务提供者并将消息交换实例(“Y”)发送给该提供者即SE2。
SE2接收实例“Y”,处理完成以后,SE2可能选择返回一个故障消息说明发生了一个应用级别的错误。在本例中,SE2可以使用实例“Y”返回故障消息,沿着请求流向的反向路径最后通过消息交换实例“X”到达JBI1实例中的SE1组件(在此MEP中,存在一个“done”响应信息会沿着相同的路径传递,为了清晰未在图中显示)。
以下内容描述了上图所示的JBI实例中的服务引擎与JBI系统外部的一个远程服务提供者之间的请求/响应调用。
服务引擎SE创建并初始化一个in-out模式的消息交换实例并发送到NMR,由NMR决定哪一个服务提供者应当处理该调用。在本例中,BC组件被选中,BC接收到该消息交换(in-out模式),将其反规格化(denormalize),然后通过通信协议发送到外部的服务提供者。外部提供者处理消息请求,返回适当的信息(正常的回复或者是应用处理层级的错误消息)。BC组件规格化该回复,讲求封装到消息交换,然后发送到NMR,最终返回给消费者SE。
端点,在WSDL2.0中指代一个可以通过特定协议访问的特定的地址,用于访问特定的服务。JBI使用这个概念表示两种不同类型的端点:
绑定组件在内部端点和外部端点之间建立映射,例如,绑定组件提供的内部端点可以映射到外部服务提供者发布的端点。
在JBI中,端点可以通过三种不同的方式进行引用:
a) EPR构建(EPR creation):一个组件希望在消息中提供回调地址时,必须能够构建适当的EPR。
b) RPR解析(EPR resolution):一个接收EPR的组件必须能够解析该EPR(也就是将其转换成可用的端点)以便于将消息交换发送到适当的端点(通常是外部服务提供者)。
消息交换的生命周期很短,不能够在系统停止或崩溃时保留。由消费者和提供者组件提供的错误恢复逻辑必须处理这类错误案例。能够使JBI支持可恢复性的可靠的消息交换需求将在JBI2.0中进行考虑。
下表是JBI使用的WSDL2.0中定义的消息交换模式。每种定义包含一个故障处理规则,用于[which specifies which message in the exchange is created (or replaced) to convey a fault from one participant to the other.],能够与WSDL1.1等同的操作也同时在表中列出。
Pattern Name |
Message Sequence |
Fault Rule |
WSDL 1.1 Operation |
In-Only |
in |
none |
One-way |
Robust In-Only |
in |
on in |
- |
In-Out |
in, out |
replaces out |
Request-response |
In Optional-Out |
in, out |
on in or out |
- |
表 3 JBI Standard Message Exchange Patterns (from WSDL 2.0)
规格化消息是JBI消息交换ME中的消息。本节定义了规格化消息,同时讨论了JBI中处理该类消息的模型。
消息的规格化指的是将协议与业务上下文信息以可传输的方式存储起来的过程。NMR处理的所有消息都是规格化的,规格化是一个双向的过程:
规格化消息包含两个不同的部分:上下文和载荷。
规格化消息提取并未规定消息载荷的处理方式。消费者可以根据特定上下文需求自由选择消息载荷的处理方式。例如,一个高性能的绑定组件会考虑使用“拉”模式的解析器或原始字节流来序列化消息载荷;另一方面,一个转换引擎可能需要将整个消息载荷加载道内存中表示成XML的DOM树以便于查询。
规格化消息的消息载荷一定是XML,对于非XML(包括二进制数据)的数据通过使用JAF(Java Activation Framework)将这些数据作为规格化数据的附件。