IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  SOA and Web services  >

深入理解 SCA 动态调用

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

样例代码


级别: 初级

菅 骁翔 (jianxx@cn.ibm.com), 软件工程师, IBM

2009 年 5 月 25 日

服务组件体系结构(Service Component Architecture,SCA)是下一代编程模型,此编程模型提供了动态调用模式。用户可以在运行时指定 SCA 绑定地址以调用不同的服务,从而达到动态调用的效果。本文深入阐述了如何在 SCA 编程模型中使用动态调用方式,并分析了动态调用的特点、局限性及其解决方案。读者从本文中能够了解 SCA 运行时如何处理动态调用,从而灵活在具体场景中使用 SCA 动态调用。架构师可以使用此信息作为参考,从而设计更为灵活的面向服务的体系结构(Service-Oriented Architecture,SOA)。

引言

SCA 作为一种新的服务组件模型,提供了一种统一的与语言无关的调用方式,从而使客户可以把不同的组件类型,例如 POJO、EJB、业务流程等通过标准的接口来封装和调用。WebSphere Process Server (WPS)将 SCA 作为构建面向服务体系结构(Service Oriented Architecture, SOA)系统的编程模型,提供了基于 SCA 的业务流程管理和系统集成功能。SCA 编程模型中的静态调用方式已被大家所熟识,本文将介绍 SCA 编程模型中的动态调用方式,并以一些简单的例子来说明具体的使用方法。





回页首


SCA 动态调用编程模型概述

在 SCA 编程模型中,最基本的组成元素和构建单位就是服务组件。我们在服务组件中实现业务逻辑,并把它组合起来构成一个完整的应用。SCA 编程模型将服务接口与实现分离,每个服务组件通过接口提供给其他服务调用的入口,通过引用来调用其它的服务组件。无论接口还是引用,其调用规范都遵循 WSDL 或 Java 接口。

一个或多个具有内在业务联系的服务组件可以被放置在一个服务模块中,服务模块之间或服务模块与外部系统之间通过导入和导出来进行相互调用。

在传统的静态编程模型中,我们通过连线的方式将引用与提供服务的组件连接起来,从而确定服务组件间的调用关系。但在很多场景下,我们希望能够在运行时再决定被调用的服务组件。这个时候,我们就需要使用 SCA 动态调用模型。

根据被调用的服务组件是否和调用者在同一服务模块内,我们可以将调用的场景分为两类:

  • 同一服务模块内的 SCA 动态调用
  • 不同服务模块间的 SCA 动态调用

同一服务模块内的 SCA 动态调用

在静态编程模型中,同一服务模块中的 SCA 组件通过连线(Wire)连接,从而确定组件间的调用关系。而在动态编程模型中,我们可以不使用连线,直接选择目标服务进行调用。

在图 1 中,服务组件 Component1 本来被连接到服务组件 Service1,服务组件 Component2 的引用未连接到任何服务组件。通过动态调用模型,我们能够在运行时选择服务组件 Service2 作为服务组件 Component1 所调用的服务,并能灵活选择服务组件 Service1 或 Service2 作为服务组件 Component2 所调用的服务。


图 1. 同一服务模块中的动态调用
同一服务模块中的动态调用

不同服务模块间的 SCA 动态调用

在 SCA 编程模型中,服务模块通过服务导出(Export)将服务提供给其它服务模块或外部系统。在静态调用编程模型中,我们只能在服务模块中添加服务导入(Import),并使用连线(Wire)将服务调用者与服务导入连接起来,从而调用其它服务模块中的服务。在动态调用模型中,我们有以下两种调用方式来调用其它服务模块中的服务。

首先,我们可以通过服务导入进行动态调用。在图 2 中,Component1 原本通过 Import 与 Module2 中的 Export1 相连,从而调用 Service1。通过动态调用,我们可以使 Component1 在运行时改为调用 Module3 中的 Export2。在这一场景中,Component1 与 Import,以及 Import 与 Export1 中间的连线并不是必须的,即我们只要有一个与 Component1 上的引用接口一致的服务导入,就可以利用这个服务导入进行动态调用。


图 2. 通过服务导入进行动态调用
通过服务导入进行动态调用

其次,我们还可以不经过服务导入直接进行动态调用,这一模式被称为纯动态调用 (Pure Dynamic Invocation)。在图 3 中,Component1 并未与任何服务导入相连接,只需要保证 Component1 上的服务引用与 Export1 和 Export2 的接口一致,我们就可以在运行时通过动态调用方式灵活选择所调用的服务。


图 3. 纯动态调用
纯动态调用




回页首


如何定义服务地址

SCA 动态调用主要是通过对 WS-Addressing 的支持,将消息寻址信息在运行时传入,从而达到在运行时决定被调用方的动态调用效果,即 SCA 动态调用。我们需要首先了解服务提供者的地址。下面介绍 SCA 中的服务地址定义。动态调用的场景分为服务模块内和不同服务模块间,在这两种场景中,服务地址的定义方式也不同。

同一服务模块内的服务地址定义

对于同一服务模块中的动态调用,服务地址定义的格式为:<moduleName>/<serviceName>

例如:图 1 中的 Service1 的服务地址为 Module1/Service1,Service2 的服务地址为 Module2/Service2。

这里的被调用者可以是服务组件,也可以是服务导入,因此 serviceName 为被调用的服务组件名或服务导入名。

不同服务模块间的服务地址定义

对于不同服务模块间的动态调用,提供服务的模块需要定义服务导出 (Export) 才能被服务调用方调用。根据调用协议的不同,SCA 编程模型对服务导出定义了不同的绑定 (Binding) 类型,而对于不同的绑定种类我们需要采用不同的服务地址定义格式。

SCA 绑定

SCA 绑定的 URI 规则为:sca://<moduleName>/<exportName>

Webservice 绑定

由于 Webservice 绑定支持 SOAP/HTTP 和 SOAP/JMS 这两种方式,Webservice 绑定的 URI 规则也分为两种。

SOAP/HTTP 的 URI 规则为:

http://host:port/<module name >/sca/<export name >

SOAP/JMS 的 URI 规则为:

jms:/queue?destination=<destinationName>&connectionFactory=<factory>&targetservice=<service>

JMS 绑定

JMS 绑定的 URI 规则为:jms:jndi:<qname>?jndiConnectionFactoryName=<cfName>

MQ 绑定

MQ 绑定的 URI 规则为:wmq:/msg/queue/<qname>

HTTP 绑定

HTTP 绑定的 URI 规则为:http://<url>

JCA 绑定

JCA 绑定的 URI 规则为:jca:jndi:<cf_name>





回页首


如何进行 SCA 动态调用

有了服务地址的定义,在 SCA 动态调用模型中,我们可以通过 SCA 提供的 EndpointReference API 来进行动态调用,或利用中介流 (Mediation flow) 进行动态调用。

利用 SCA EndpointReference API 进行动态调用

SCA 编程模型中使用 com.ibm.websphere.sca.addressing.EndpointReference 类来描述一个符合 WS-Addressing 规范的端点引用(Endpoint Reference)。我们可以使用 EndpointReferenceFactory 来创建一个 EndpointReference 实例,并设置相应的地址。通过服务调用方组件已有的引用和该 EndpointReference 实例得到的服务对象来调用地址所指定的服务提供方组件。

对于模块内的动态服务调用和模块间的纯动态服务调用,我们可以通过以下代码片断得到一个能够调用服务提供者的服务对象,完成服务调用:


清单 1. 调用服务提供者的服务对象代码
// Reference name
String refName = <ReferenceName>;
// Create an EPR and initialize it
EndpointReference epr = 
EndpointReferenceFactory.INSTANCE.createEndpointReference();
epr.setAddress(<EndpointAddress>);
// Get the service passing in reference name and initialized EPR
Service service = (Service) ServiceManager.INSTANCE.getService(refName, epr);

对于模块间通过服务导入的动态调用,我们还需要设置导入名称和导入类型:


清单 2. 模块间动态调用相关设置
// Reference name
String refName = <ReferenceName>;
// Create an EPR and initialize it
EndpointReference epr = 
EndpointReferenceFactory.INSTANCE.createEndpointReference();
epr.setAddress(<EndpointAddress>);
epr.setBindingType(<BindingType>);
epr.setImport(<ImportName>);
// Get the service passing in reference name and initialized EPR
Service service = (Service) ServiceManager.INSTANCE.getService(refName, epr);

需要注意的是,当 refName 定义的引用接口为 Java 接口时,我们可以直接得到一个具有该 Java 接口的服务对象;当 refName 定义的引用接口为 WSDL 接口时,我们只能得到一个 Service 接口的服务对象。

基于中介流的 SCA 动态调用

除了 SCA EndpointReference API,我们还可以利用中介流(Mediation Flow)来完成 SCA 动态调用。在中介流中,所有流转的数据都被封装为 SMO(Service Message Object)。SMO 中的 SMOHeader 包含了 Target 属性和 AlternateTarget 属性,这两个属性都定义为 TargetAddressType,包含了 address、bindingType 和 import 的定义。我们可以通过 Endpoint lookup、Message element setter、XSL transformation、Database lookup 或 custom primitive 来设置这两个属性。中介流在 Callout 节点会根据 SMOHeader 中的 Target 属性与 AlternateTarget 属性动态调用属性中地址所指向的服务。

与 SCA EndpointReference API 类似,对于模块内的动态服务调用和模块间的纯动态服务调用,我们只需要设置 Target 属性和 AlternateTarget 属性的 address 信息。对于模块间通过服务导入的动态调用方式,我们还需要设置 bindingType 和 import 信息。


图 4. SMOHeader 中的 Target 属性与 AlternateTarget 属性
SMOHeader 中的 Target 属性与 AlternateTarget 属性

需要注意的是,我们必须在 Callout primitive 中选择 Use dynamic endpoint if set in the message header 选项,否则中介流将不会使用 SCA 动态调用。


图 5. 设置 Callout primitive 以支持 SCA 动态调用
设置 Callout primitive 以支持 SCA 动态调用




回页首


SCA 动态调用中的限制

通过上面的介绍,我们已经对如何进行 SCA 动态调用有了初步的了解。我们只需要对不同的服务提供者定义好各自的服务地址,就可以通过 SCA EndpointReference API 或中介流进行动态调用,从而在运行时灵活选择被调用的服务。下面介绍 SCA 动态调用模型中的一些限制,确保我们能够正确的使用 SCA 动态调用。

纯动态调用对绑定协议的限制

对于纯动态调用模式,只能通过调用 SCA 绑定或 JAX-RPC WebService 绑定的服务导出。如果要调用其他绑定方式的服务导出,我们只能选择通过服务导入来进行动态调用。

纯动态调用对 QoS 的限制

在 SCA 编程模型中,我们通过在接口 (Interface)、引用 (Reference) 和实现 (Implementation) 上添加服务标识 (Qualifier),对 QoS 进行控制。在纯动态调用模式中,调用方与被调用方式间的 QoS 信息无法更改,只能采用默认的 QoS 设置。如果需要在动态调用中自主设置 QoS 信息,例如让被调用方加入调用方的事务,我们也必须采用通过服务导入的动态调用方式,在服务导入上添加需要的 QoS 信息。





回页首


结束语

本文介绍了 SCA 编程模型中动态调用方式支持的场景,如何定义服务地址,以及如何通过 SCA EndpointReference API 或中介流来进行动态调用。最后进一步介绍了 SCA 动态调用中对于纯动态调用模式的一些限制。

本文附带的样例程序中包含了利用 SCA EndpointReference API 和中介流进行动态调用的示例。其中 Callee 模块为被调用的服务模块,POJOCaller 模块示范了模块中的动态调用、利用服务导入和未利用服务导入的模块间动态调用。MFCCaller 模块示范了利用中介流进行模块间动态调用。

如果希望对 SCA 动态调用方式有更深入的了解,请参阅附录中的材料。






回页首


下载

描述名字大小下载方法
本文代码示例dynamicInvocation.zip40 KBHTTP
关于下载方法的信息


参考资料

学习
  • SCA 专题:本专题为您为总结了和 SCA 相关的内容和资源,包括入门介绍、开发技巧等内容。通过这些内容的学习,您将对 SCA 有一个更加深入的了解。

  • WebSphere Process Server 信息中心:关于 WebSphere Process Server 中对动态调用的技术文档。

  • 使用服务组件体系结构构建 SOA 解决方案,第 2 部分:组装 SCA 组件:本文介绍了使用 WebSphere Integration Developer 组装服务组件体系结构组件的上下文中的引用和连线。

  • SCA(Service Component Architecture)编程模型入门:本文将介绍 SCA 编程模型中的基本概念,并以一个简单的例子来说明它的一些基本用法,期待能够抛砖引玉,并为读者以后深入了解 SCA 打下基础。

  • SCA 应用程序开发:本文将从概念和理论上介绍 SCA,并说明它如何简化使用面向服务的体系架构(Service-Oriented Architecture,SOA)所构建的业务应用程序的设计和集成。

  • SCA 规范介绍 :服务组件体系结构(Service Component Architecture,SCA)是一组规范,描述了用于使用面向服务的体系结构来构建应用程序和系统的模型。在这里,您可以找到和它相关的一些官方文档和开发手册。

  • 利用 WID 及 WPS V6.2 开发基于 JAX-WS 绑定的 SCA 应用 :本文将通过示例向您介绍如何使用 WID V6.2 及 WPS V6.2 开发、配置基于 JAX-WS 绑定的 SCA 模块,以及如何通过管理控制台设置 JAX-WS 绑定连接、拆离策略集及指定策略集绑定。


获得产品和技术


关于作者

菅骁翔任职于 IBM 中国开发中心,目前从事 WebSphere Process Server 的开发工作。




对本文的评价








IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款