SOA 最佳实践:BPEL 指南

第 2 部分:使用 BPEL 构建 Web 服务网络
作者:Yves Coene 和 The Hoa Nguyen

欧洲航天局使用 BPEL 作用域、BPEL 域和 Oracle BPEL 流程管理器 API 构建易于合作伙伴使用的 Web 服务网络的案例研究。


本文相关下载:
 Oracle BPEL 流程管理器和 Designer

 查看完整的“BPEL 指南”索引

受不断成熟的 Web 服务标准的鼓舞,越来越多的组织正在协作环境中使用 Web 服务。BPEL 正快速成为为实现企业间协作而编排这些 Web 服务的平台。BPEL 为构建在线市场或协作网络的公司提供了引人瞩目的好处,即基于标准的方法和松散耦合的流程集成。

而 Web 服务提供的激动人心的新功能却隐藏着某些风险。在许多情况下,如果在设计时未解决某些技术和管理难题,则合作伙伴关系将会破裂或集成成本飙升:

  • 合作伙伴必须事先进行充分的协商,约定根据特定标准开展业务。传输协议、交互目的、消息格式以及业务约束必须实现清晰地通信。
  • 连接网络必须是一个简单的过程;协作网络主要通过不断壮大取得成功。
  • 用户必须在运行时轻松地找到业务服务,否则将在很大程度上无法实现面向服务体系结构 (SOA) 这一承诺。(服务信息库在这方面很有用。)如果开发人员无法轻松地找到和重用服务,则这些服务本质上就算不存在。
  • 合作伙伴应能够实时监控 Web 服务。最终用户应能跟踪特定订单的进度,并且贸易合作伙伴应能诊断业务流程中的特定瓶颈。
如果协作网络在托管环境中运行,这些难题将变得更为棘手。在该模型中,合作伙伴将他们原有应用程序提供的功能公开到 Web 服务中,并将此 Web 服务发布到集中的信息库中。主机负责编排复杂的业务流程,后者反过来利用合作伙伴的 Web 服务。

在 BPEL 指南的这一部分中,我将把欧洲航天局 (ESA) 项目(来自 Spacebel s.a. 的小组参与了该项目)作为一个案例分析,介绍与这些挑战相关的体系结构注意事项。此外,我还将介绍该项目如何利用 BPEL 作用域、BPEL 域和 Oracle BPEL 流程管理器 API 构建一个“易于合作伙伴使用的”协作网络。

 

ESA 网络概述

 

ESA 已着手制定一个战略性计划,旨在完全基于开放标准创建一个 BPEL 驱动的服务提供商协作网络。该网络称作服务支持环境 (SSE) 网络,它组合第三方的地球观测 (EO) 和地理信息系统 (GIS) 服务,提供增值的复合型服务。SSE 是一个不断壮大的网络,目前包括遍布 9 个不同国家/地区的 20 多个合作伙伴。

 

如图 1 所示,SSE 是一个支持 BPEL 的网络的简单实现。ESA 充当中介,它使用各种 Web 服务标准(如 SOAP、WSDL、WS-Addressing、WS-Inspection 等)为不同合作伙伴之间基于流程的协作提供支持。该网络在集中星型拓扑环境中运行:服务提供商使用 Oracle BPEL Designer 将不同类型的地球观测和 GIS 服务集中到一个信息库中,从而创建了一个不断扩大的服务目录。

 

图 1 SSE 体系结构

 

SSE 提供执行以下任务所必需的基础架构
  • 承载和管理充当可用服务目录的中央信息库
  • 在中央目录内部注册和搜索服务
  • 在 Oracle BPEL 引擎内部执行短期和长期的业务流程
  • 使合作伙伴能够使用 Oracle BPEL 流程管理器控制台监控 Web 服务的执行
最终用户通过浏览可用服务目录请求特定服务。SSE 根据请求调用相关的业务流程。该业务流程调用 Web 服务(运行在服务提供商处)来完成请求。

SSE 支持同步和异步的交互模型。ESA 广泛使用 Oracle BPEL 流程管理器 API 来为提供商和最终用户提供最大程度的灵活性和易用性体验。

 

设计 Web 服务网络

 

开放标准正在不断改变集成的规则。BPEL 提供了一个以流程为中心的跨企业集成方法,因此可以使用 BPEL 流程流定义合作伙伴集成。SOA 与 BPEL 的这一组合为构建松散耦合的协作网络提供了一个前所未有的良机。

 

集中星型(SSE 采用的方法)是一个广泛使用的网络拓扑,组织通过它与各种合作伙伴建立连接。网络也可以采用单向对等模型。这种情况下,每个合作伙伴都为 Web 服务安全性和供应提供了一个平台。

 

现在,我们来看网络设计的四个方面:
  • 设置接口关系
  • 简化合作伙伴支持
  • 创建集中的服务注册表
  • 为合作伙伴和最终用户提供自助监视功能
设置接口关系。协作网络设计从定义参与规则开始。这些规则指定在业务流程中交换的消息、这些消息的交换顺序以及该消息的物理属性。要正确通信,所有合作伙伴都必须能够回答以下问题。
  • 交互的目的 — 是请求报价还是订单?
  • 消息格式 - 消息是如何编码的?
  • 词汇 — 应如何构造消息,以便其他各方可以理解和处理它们?
  • 业务约束 - 应在多长时间内响应请求?
  • 通信渠道 - 是否应把消息加密?
为帮助合作伙伴回答以上问题,ESA 公布了一个 接口控制文档来定义这些术语。本文档正式确定了在多个 ESA 赞助的项目中建立、改进和验证的技术集成规则。 基于消息的 SOAP(通过 HTTP 或 HTTPS 实现安全通信)是 SSE 服务器与服务提供商之间采用的通信协议。(对于本文档,我们将分析 WS-Security 的用法。)Web 服务定义语言 (WSDL) 是唯一一个绑定了所有实体的接口协定;服务提供商必须创建一个 WSDL 文件,用于描述它的 SOAP 接口并使其他合作伙伴可以访问该接口。WSDL 文件中包含的某些信息是固定的,但必须提供以下信息:
  • 根据选定的交互模型(搜索、RFQ、订购)选择的操作
  • 服务的物理位置
  • 服务 XSD 模式的导入
为便于服务、一致性和消息转换的比较,ESA 要求使用 XSD 模式表示 XML 有效载荷。SSE 还要求使用主 XSLT 文档来确保表示层中的一致性。必须按如下所示在每个服务中导入模板样式表:
                               
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:oi="http://www.esa.int/oi">
<!-- Import statements -->
<xsl:import href="./SSE.xsl"/>
<!-- Apply the template for the root element from SSE standard template -->
<xsl:template match="/">
<xsl:apply-imports/>
</xsl:template>
...

                            
xsl:apply-imports 使用从 SSE 样式表中导入的模板规则处理根节点。注册该服务时,服务提供商提供 XML 模式、WSDL 和 XSLT 文件的 URL。SSE 强制使用文档样式的 SOAP。该方法允许使用 XML 模式对输入服务和服务输出的数据进行详细的指定并验证传入和传出的消息。

 

ESA 采用的方法为打算构建一个合作伙伴数量有限的 Web 服务网络的公司提供了一个便捷解决方案。随着网络规模的增长,将需要引入新的消息格式、通信规则、安全性以及传输机制。

 

简化合作伙伴的参与。任何网络的壮大都离不开合作伙伴的轻松参与。下列因素将对此过程产生很大的影响。
  • 与集线器的集成 - 合作伙伴如何创建和提交他们的 Web 服务?集线器能否支持不同的传输协议?
  • 流程管理 - 不同合作伙伴流程之间是否有清晰的界限?合作伙伴能否修改它的业务流程而不影响整个网络的可靠性?能否使用元数据定义即时生成流程?
SSE 通过降低对服务提供商的技术要求成功稳固了与其合作伙伴的联系。ESA 通过分发合作伙伴连接软件、划分开发平台以及自动代表合作伙伴生成流程流实现了该目标。

 

例如,为加快集成流程的速度,ESA 分发了 SSE Toolbox,这是一个在 SSE 与服务提供商的现有系统间充当接口的免费工具包。基于 Sun Java Web Services Developer Pack 的 SSE Toolbox 提供了一个支持各种后端集成机制(如 FTP、文件交换、JDBC、调用 Java API、HTTP 等)的 XML 脚本语言。它还自动生成注册服务所需的 WSDL 文件。

 

不同的合作伙伴将多个服务提供给中央信息库。开发和部署环境的划分使合作伙伴间的更改互不影响。SSE 通过在 Oracle BPEL 流程管理器中使用 BPEL 域有效地利用了划分功能。BPEL 域使开发人员或管理员能够将 Oracle BPEL 流程管理器的单个实例划分为多个虚拟 BPEL 沙箱。BPEL 域由一个 ID 标识,并由一个口令保护。当服务提供商在 SSE 上注册时,将调用 Oracle BPEL 流程管理器 API 自动创建一个 BPEL 域保存服务定义文件。

以下是一个 createDomain 方法示例:

                               
/**
* Create new domain space for a service provider to hold her/his services workflow
* definitions files in
     *
* @param domainName The Id to identify the domain
* @param password The password used to login to the corresponding domain
* @exception RemoteException System communication error
* @exception WorkflowException Thrown if any error happens on the server that prevent the delete
     *
     */
public void createDomain(String domainName, String password)
throws RemoteException, WorkflowException{
if(ml.isDebugEnabled()) ml.debug("Enter createDomain(domain = " + domainName + " password = " + password);
      /**
* check if the being created domain exist?
       */
      
try {
                Locator locator = new Locator(domainName, password);
                ml.info("Stop creating domain:" + domainName + " because it has already existed.");
                throw new WorkflowException("1019");
                
} catch (com.oracle.bpel.client.ServerException e) {
                ;
      }
try {
//obtain the domain admin password from the system configuration SSE.properties file
String domainAdminPassword = SystemConfigurationInfo.getProperty(WorkflowConstant.BPEL_DOMAIN_ADMIN_PASSWORD);
ServerAuth auth = ServerAuthFactory.authenticate( domainAdminPassword, "localhost" );
if(ml.isDebugEnabled()) ml.debug("obtain authentication ok");
// Create server object ... this is our service interface
          //
Server server = new Server( auth );
// Domain id is "newDomain", the password is "myPassword"
if(ml.isDebugEnabled()) ml.debug("create server instance ok");
          //
                  Map domainProperties = new HashMap();
                  domainProperties.put( Configuration.DATASOURCE_JNDI, SystemConfigurationInfo.getProperty
(CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI));
                  domainProperties.put( Configuration.TX_DATASOURCE_JNDI, SystemConfigurationInfo.getProperty
(CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI));
                  
                  if(ml.isDebugEnabled()) ml.debug("create domain - ds jndi property key/value: 
" + Configuration.DATASOURCE_JNDI + "/" + SystemConfigurationInfo.getProperty
(CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI));                       
                  if(ml.isDebugEnabled()) ml.debug("create domain - tx_ds jndi property key/value: 
" + Configuration.TX_DATASOURCE_JNDI + "/" + SystemConfigurationInfo.getProperty
(CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI));
server.createDomain(domainName, password, domainProperties);
                            
          
                if(ml.isDebugEnabled()) ml.debug("Enter createDomain(domain = " + domainName + " password = " + password);

} catch( com.oracle.bpel.client.ServerException se ){
ml.error(se.getMessage());
if(ml.isDebugEnabled()) se.printStackTrace();
throw new WorkflowException("1018", se.getCause());
      }
    }

                            
在下面 runBuildScript 方法的实现中,通过一个 Ant 构建脚本访问 Oracle bpelc 函数。 runBuildScript 方法调用一个 Ant 项目文件,后者随后调用 bpelc 编译和部署服务提供商的 BPEL 流程。
                               
/**
* execute the ant script to build an Oracle BPEL process that implements the workflow.
* The script also deploys the workflow to the service domains.
* All input information is provided under the props at the input param.
* @param props Contain all necessary properties used to build/deploy the workflow BPEL process
* @throws WorkflowException
     */
private void runBuildScript(String buildFilename, Properties props) throws WorkflowException{
if(ml.isDebugEnabled())ml.debug("Enter runBuildScript(buildFileName = " + buildFilename +
", properties = ...");
try {
Project project = new Project();
project.init();
File buildFile = new File(buildFilename);

if (!buildFile.exists()) throw new WorkflowException("1015");
if(ml.isDebugEnabled()) ml.debug("ant build file:" + buildFile.getAbsolutePath());

ProjectHelper.configureProject(project, buildFile);
//prepare logger for the project build
PrintStream out = System.out;
BuildLogger logger = new DefaultLogger();
logger.setMessageOutputLevel(Project.MSG_DEBUG);
logger.setOutputPrintStream(out);
logger.setErrorPrintStream(out);
project.addBuildListener(logger);

//set project properties
Enumeration keys = props.keys();
while(keys.hasMoreElements()){
String key = keys.nextElement().toString();
project.setProperty(key, props.getProperty(key));
            
          }
// test 
//excute default target
project.executeTarget(project.getDefaultTarget());
                  if(ml.isDebugEnabled())ml.debug("Exit runBuildScript(buildFileName = " + buildFilename +
                                  ", properties = ...");
        }
catch (Exception ex) {
ml.error(ex.getMessage());
if(ml.isDebugEnabled()) ex.printStackTrace();
throw new WorkflowException("1002",ex.getCause());
        } 
  }

                            
在 Web 服务网络设计中,应考虑使用 BPEL 域为所有相关各方划分流程设计和部署平台。以下是一些可能的应用:
  • 将单个 Oracle BPEL 流程管理器实例划分为多开发人员环境。这种情况下,域 ID 通常标识拥有该域的开发人员。
  • 将单个 Oracle BPEL 流程管理器实例划分为开发环境和 QA 环境。这种情况下,域 ID 可能为“test”和“QA”。
  • 将单个 Oracle BPEL 流程管理器实例划分为一个可以由多个部门或合作伙伴使用的环境。这些情况下,域 ID 是部门或合作伙伴的名称。
创建中央服务信息库。定义了网络关系后,合作伙伴便可以免费加入并提供他们的服务。当然,发布和搜索这些服务的功能是 SOA 平台的一个基础功能。

 

在该流程中,合作伙伴将他们的 Web 服务发布到一个中央信息库,有关该服务的所有信息都在这里进行管理。这个中央框架提高了服务的可重用性,最大限度地降低了定位服务所需的工作量和时间。没有中央信息库将导致不一致和混乱。这反过来会降低网络的灵活性和开放性。

SSE 网络频繁使用中央 Web 服务信息库;合作伙伴使用 Web 服务检查语言 (WSIL) 发现可用服务。服务提供商可以通过选择相应的 WSDL 文件重用现有的 Web 服务(由网络中的其他提供商提供)。可以在 Oracle BPEL Designer 工具配置文件 UDDIProviderList.xml 中添加 WS-Inspection URL http://services.eoportal.org/inspection.wsil 来完成此任务,如下所示。

<provider>     
<description>ESA SSE Portal</description>     
<type>wsil</type> 
<inquiryURL>
http://services.eoportal.org/inspection.wsil
</inquiryURL>  
</provider>
位于服务提供商处的 Oracle BPEL Designer 连接到 SSE 服务器并使用 WS-Inspection 协议发现可用服务及其 WSDL 文件。连接到 WS-Inspection 服务器后,将显示所有可用服务列表,如图 2 中所示。

 

图 2 可用 SSE 服务列表

 

对于每个服务,将提供相应的 WSDL 文件和简短的文字描述。可以通过选择 WSDL 文件为该服务添加一个合作伙伴链接。构建流程流后,可以使用 BPEL 控制台将其部署在 SSE 门户上。(在它的下个版本中,SSE 将实现 UDDI 注册表与 Oracle BPEL 的集成。注册新服务时,还将在此 UDDI 注册表中自动注册该服务。该集成将简化使用外部工具的服务发现,目前仅当这些工具支持 WS-Inspection 时才能发现服务。)

尽管您不必建立服务信息库即可构建 SOA 并获得它的众多好处,但从长远来看,信息库是不可或缺的。如果服务的作用域只是一个项目,则架构师不用信息库也能处理。但大多数企业都拥有各种服务和合作伙伴,并且这些服务和合作伙伴的大部分都在不断变化。

提供自助式监视。在多方参与业务流程的协作网络中,对业务流程执行情况的监视非常关键,因此可以将围绕业务流程的关键性能指标与服务级协议相联系。(例如,加入网络的关键要求之一可能是确认两小时内的报价请求。)监视业务流程可以更好地获知特定业务流程实例执行的时间、出现延迟的原因以及如何为未来事务修复此问题。

 

应向合作伙伴和最终用户提供该级别的诊断。通过创建自助式环境,合作伙伴和最终用户可以跟踪他们的单个流程,从而减轻中央监视框架检测到的问题。

 

可以使用 Oracle BPEL 控制台监视和调试业务流程(参见图 3)。ESA 和服务提供商利用 BPEL 控制台跟踪正在运行和已经完成的 BPEL 流程实例数量、流程实例的平均持续时间(从而细分流程中消耗的时间)以及文本格式的流程实例审计线索,从而使合作伙伴可以查看中间结果。

 

图 3 使用 Oracle BPEL 控制台监视业务流程

 

此外,订购了特定服务的最终用户可以跟踪其订单的状态。可以使用 Oracle BPEL 流程管理器 API 在 BPEL 控制台的外部显示该信息。建议服务提供商在他们的 BPEL 流程中使用有意义的作用域名称;在运行时,门户使用 IInstanceHandle.getStatus() API 提取当前 BPEL“作用域”的名称向最终用户显示该进度的信息。

作用域 按层次结构组织,一个复杂的业务流程可以分为几个作用域。它们为活动提供了行为上下文。通过在 BPEL 流程中使用有意义的作用域名称,合作伙伴可以跟踪“短期”和“长期”业务流程的状态。

 

例如以下 getOrderSubstatus 方法的实现。该方法使 ESS 合作伙伴可以使用在 bpel 文件中执行的作用域的名称获取 BPEL 流程实例的当前状态。
                               
* call the Oracle BPEL API to get current status of the workflow instance, corresponding to
* the ordered supplied at the input
* @param ordered The order identified
* @param workflowId The workflow name (or Id) that is processing the order stage.
* Normally, there are two stages of an order:send(process)rfq and send(process) order
* @param domain The domain that the order workflow belongs to
* @param password The password used to login to the workflow domain
* @return the current status of the workflow instance - particularly, it is the name of the current
* active scope in the workflow BPEL file. 
* @throws RemoteException
* @throws WorkflowException
 */
public String getOrderSubstatus(String ordered, String workflowId, String domain,  String password)
        throws RemoteException, WorkflowException 
 {
                if(ml.isDebugEnabled()) ml.debug("Enter getOrderSubstatus(ordered = " + ordered
                         + ", workflowId = " + workflowId + ", domain = " + domain + ", password = " + password);
                String status = "";
                try {
                                
                        Locator locator = new Locator(domain, password);
                        IinstanceHandle instance = locator.lookupInstance(ordered + "_" + workflowId);
                                
                        if( instance.isComplete() )  status = "Completed";
                        else status = instance.getStatus();
                                
                        return status;
                } catch (com.oracle.bpel.client.ServerException e) {
                        // TODO Auto-generated catch block

                        ml.error(e.getMessage());
                        if(ml.isDebugEnabled()) e.printStackTrace(); 
                        throw new WorkflowException("1016", e.getCause());
                }
                        
}

                            
结论

 

ESA 在构建其整个协作网络时始终没忘其灵活性。接口关系的灵活定义简化了网络的采用并促进了网络的发展。BPEL 域的采用提供一个独立的工作区,从而为服务提供商提供了广泛的灵活性;服务提供商可以修改他们的业务流程且不会影响网络的稳定性。BPEL 作用域已经使 ESA 可以从细节上跟踪即时流程的状态。该网络还可代表服务供应提供商自动生成 BPEL 流程流。所有这些因素渐渐地使该网络更易于合作伙伴使用,并最大限度地降低了合作伙伴的前期投资。

 

但还有一些网络设计领域本文并未涉及,如分布式事务管理、安全性以及贸易合作伙伴管理。随着 B2B 网络规模的扩大,BPEL 可以在编排专用流程方面处于领先地位。例如,Oracle 集成 B2B 产品(可以与 Oracle BPEL 流程管理器交互操作)解决了公共流程编排、握手协议支持(RosettaNet、ebXML、EDI、HIPAA)、消息格式处理(MIME、SMIME、AS2、XMLDSig)和贸易合作伙伴管理(认可、服务级协议、合作伙伴协议)。

 


Yves Coene Yves Coene 当前在 Spacebel s.a.(位于布鲁塞尔)担任项目经理。他在航空软件项目(如 Ariane 5、International Space Station、F16 MLU)和欧洲航天局的各种其他项目方面具有 15 年的工作经验。自 2001 年以来,他和他的团队一直在意大利的 Frascati 负责 ESA 的 SSE 项目。

 

The Hoa Nguyen 当前在 Spacebel s.a.(位于布鲁塞尔)的 SDC 子公司担任高级软件工程师。他的主要兴趣是 J2EE、Web 服务以及使用 BPEL 进行工作流开发。自 2001 年以来,他一直是 Spacebel 的 SSE 项目小组的主管工程师之一,此外他还在 ESA 负责 SSE 软件发布以及 SSE 软件现场安装。

将您的意见发送给我们