在 SOA 环境中管理流程和服务依赖关系
背景
您知道 BPEL 流程依赖哪些服务吗?如果使用了不同版本的 BPEL 流程,二者之间的依赖关系很快就会变得更加复杂。如果我们将 BPEL 流程调用的企业服务总线 (ESB) 服务考虑在内,依赖性管理的复杂度将提升。复杂度使得部署和测试耗时、困难且易于出错。
通常我们最后使用 Microsoft Visio 建模工具来手动描绘依赖关系,并在流程每次更改后忙于更新依赖关系。这是一个阻碍面向服务的体系结构 (SOA) 基础架构敏捷性的主要羁绊,SOA 体系结构的设计旨在实现业务流程的敏捷更改。
在这一技术说明中,将向您介绍如何成功地改善构建流程,以及实现流程依赖关系图的自动生成。
我们的挑战是为客户实施一个 Oracle SOA 套件示范项目,该项目包含许多 BPEL 流程,并引用众多 BPEL 子流程和 ESB 服务。最后我们使用了十来个 BPEL 流程和 ESB 服务(它们定义为公共服务,在服务注册表上共享)以及其他专有 BPEL 流程和 ESB 服务。
首先,我们决定为项目所有服务创建一个基于 Ant 的部署,将 BPEL 流程(包括执行它们的测试用例)部署到不同环境 (测试、集成、生产) ,并通过基于 Ant 的方式将 ESB 服务也部署到这些环境。计算机电子书籍免费下载
要求
完成首个项目版本后,我们有一些要求:
,
当一个 BPEL 流程或 ESB 服务更改后,我们不想部署项目的所有服务。所以我们需要将以项目为中心的部署转变为以公共服务为中心的部署方法。
在部署 BPEL 流程时,所有依赖关系的 (专有) 子流程和 ESB 服务也将自动部署。
为防止覆盖特定版本的流程,只有服务器未部署该版本的流程时才进行部署,覆盖将导致所有实例流信息丢失。
在部署期间应自动创建所有流程和服务依赖关系的可视化图形,不需另外维护这些信息。可视化图应该如下所示。
悬而未决的问题
针对这些新要求,我们提出了以下问题,并做出以下解答:
问题:来自流程和服务依赖关系的信息存储在哪里?需要增加更多信息以创建完整的依赖关系图吗?
答案: BPEL 流程调用的所有服务都存储在 partnerLinkBinding 标记的 bpel.xml 文件中。对于调用的 BPEL 流程、版本信息也以编码编入 URL 中。例如: 计算机电子书籍免费下载
<property name="wsdlRuntimeLocation">
${domain_url}/CustomerAccount_BES/1.3/CustomerAccount_BES?wsdl
</property>
要部署的当前版本的 BPEL 流程可以在 build.properties 文件中找到。对于 BPEL 流程的版本维护,我们只需要更改 build.properties 文件中的 rev 属性。
为区分公共和专有 BPEL 流程,bpel.xml 文件内客户端的合作伙伴链接提供了一个新属性“type”,其值为“public”或“private”,如此处所示:
<partnerLinkBinding name="client">
<property name="wsdlLocation">CustomerAccount_BES.wsdl</property>
<property name="type">public</property>
</partnerLinkBinding>
问题:有可以动态生成依赖关系图的工具或框架吗?
答案:有,一个开放源工具 Graphviz (www.graphviz.org) 可从文本格式的输入文件生成图形。
问题:引用其他 BPEL 流程的选项有哪些?
答案:选项有:
引用默认版本
引用具体版本
引用 UDDI 服务键 (带或不带经编码的版本信息)
问题:如何能实现所有这些新的部署要求?
答案:使用自定义 Ant 任务可以最好地实现这些新部署要求。
开始工作
问题都得到了圆满解答,下面我们着手创建一个自定义 Ant 任务。在 Ant 任务中将解析 bpel.xml 文件。对于找到的所有 partnerLinkBindings 标签,将以递归方式开始解析对应的 bpel.xml 文件。除了解析,还将从每个找到的 BPEL 项目的 build.properties 文件中提取版本属性(“ref”)的当前值。递归解析的挑战之一是跳过循环的依赖关系。
我们在 bpel.xml 文件中新推出的“type”属性和递归解析实现了我们以服务心中的部署的所有需求。
更棒的是,我们使用 Graphviz 解决了依赖关系图的自动生成问题。为达到此目的,我们要将从递归 bpel.xml 解析中得到的所有依赖关系合并为一个 XML 文件,如下所示。 计算机电子书籍免费下载
<?xml version="1.0" encoding="UTF-8"?>
<BPELSuitcase>
<BPELProcess id="Resource_BAS_SetForAccount" src="http://www.oracle.com/technology/tech/soa/soa-suite-best-practices/Resource_BAS_SetForAccount.bpel">
<partnerLinkBindings>
<partnerLinkBinding name="client">
<property name="wsdlLocation">Resource_BAS_SetForAccount.wsdl</property>
<property name="type">public</property>
<property name="version">1.2</property>
</partnerLinkBinding>
<partnerLinkBinding name="RemoveFromAccount">
<property name="wsdlLocation">Resource_BAS_RemoveFromAccount.wsdl</property>
<property name="version">1.5</property>
</partnerLinkBinding>
...
</partnerLinkBindings>
</BPELProcess>
<BPELProcess id="Resource_BAS_RemoveFromAccount" src="http://www.oracle.com/technology/tech/soa/soa-suite-best-practices/Resource_BAS_RemoveFromAccount.bpel">
<partnerLinkBindings>
<partnerLinkBinding name="client">
<property name="wsdlLocation">Resource_BAS_RemoveFromAccount.wsdl</property>
<property name="type">public</property>
<property name="version">1.5</property>
</partnerLinkBinding>
<partnerLinkBinding name="CheckAvailability">
<property name="wsdlLocation">Resource_BES_CheckAvailability.wsdl</property>
<property name="version">1.1</property>
</partnerLinkBinding>
...
</partnerLinkBindings>
</BPELProcess>
<BPELProcess id="Resource_BES_CheckAvailability" src="http://www.oracle.com/technology/tech/soa/soa-suite-best-practices/Resource_BES_CheckAvailability.bpel">
<partnerLinkBindings>
<partnerLinkBinding name="client">
<property name="wsdlLocation">Resource_BES_CheckAvailability.wsdl</property>
<property name="type">public</property>
<property name="version">1.1</property>
</partnerLinkBinding>
...
</partnerLinkBindings>
</BPELProcess>
...
</BPELSuitcase>
使用 XSLT 将合并的 XML 文件转换为目标格式 (.dot), 这一格式可作为 Graphviz 生成程序的输入,以生成 PNG 图像,如下所示:
digraph structs {
node [shape=record,fontname="Arial",fontsize="10"];
edge [fontname="Arial",fontsize="8"];
rankdir=LR;
labeljust=l;
"Resource_BAS_SetForAccount_1_2" [shape=record,label="{Resource_BAS_SetForAccount}|{1.2|public}",
fillcolor=yellowgreen,style=filled];
"Resource_BAS_RemoveFromAccount_1_5" [shape=record,label="{Resource_BAS_RemoveFromAccount}|{1.5|public}",
fillcolor=yellowgreen,style=filled];
"Resource_BES_CheckAvailability_1_1" [shape=record,label="{Resource_BES_CheckAvailability}|{1.1|public}",
fillcolor=yellowgreen,style=filled];
"Resource_BAS_SetForAccount_1_2" -> "Resource_BAS_RemoveFromAccount_1_5" [decorate=true,label=""];
"Resource_BAS_RemoveFromAccount_1_5" -> "Resource_BES_CheckAvailability_1_1" [decorate=true,label=""];
}
由以上 DOT 文件生成的依赖关系图形如下所示:
在方框中显示了服务名称、版本和类型。方框颜色指明了服务类型。在该图中,我们有三个公共(绿色)服务。本文开头的图中还显示了 ESB 服务 (白色) 和 BPEL 服务 (桔黄色)。
为各个公共 BPEL 流程生成理想的图之后,我们要实施相关流程的自动部署。对于这一以服务为中心的部署,我们使用了之前生成的流程列表。针对列表中的每一个流程调用标准部署目标。为防止覆盖服务器上的现有流程版本,只有服务器上没有当前版本的流程时才会调用部署目标。
可以通过打开到流程 WSDL URL 的 HTTP 连接,然后检查返回的状态代码来确定是否有特定流程版本(HTTP 状态 200 ? 已经部署, HTTP 状态 404 ? 尚未部署)。 计算机电子书籍免费下载
我们自定义的 Ant 任务(包含递归解析)、PNG 图像生成以及以服务为中心的部署的输出如下所示:
...
[mkdir] Created dir: /MyProject/Resource_BAS_SetForAccount/doc
[bpeltask] ** STARTING DeployWithDependencesTask **
[bpeltask] Resource_BAS_SetForAccount-1.2
[bpeltask] ** PARAMETER **
[bpeltask] dotfilename: doc/bpel-recursiv-all.dot
[bpeltask] dotfilenamepublic: doc/bpel-recursiv-public.dot
[bpeltask] deploytarget: deploy
[bpeltask] deployment: true
[bpeltask] overwriting: false
[bpeltask] stoponalreadydeployed: false
[bpeltask] ** RESOVLING RECURSIVLY ALL bpel.xml FILES **
[bpeltask] [Resource_BAS_SetForAccount-1.2]
[bpeltask] [Resource_BAS_SetForAccount-1.2, Resource_BAS_RemoveFromAccount-1.5]
[bpeltask] [Resource_BAS_SetForAccount-1.2, Resource_BAS_RemoveFromAccount-1.5, Resource_BES_CheckAvailability-1.1]
[bpeltask] ** WRITING CENTRAL bpel.xml FILE **
[bpeltask] ** TRANSFORMING DOT FILE **
[bpeltask] ** SERVICE DEPLOYMENT **
[bpeltask] ========================================================================
[bpeltask] SERVICE ALREADY DEPLOYED (HTTP/1.1 200 OK) 'Resource_BES_CheckAvailability' in version '1.1' http://localhost:8888/orabpel/default/Resource_BES_CheckAvailability/1.1/ Resource_BES_CheckAvailability?wsdl
[bpeltask] ========================================================================
[bpeltask] ========================================================================
[bpeltask] SERVICE ALREADY DEPLOYED (HTTP/1.1 200 OK) 'Resource_BAS_RemoveFromAccount' in version '1.5' http://localhost:8888/orabpel/default/Resource_BAS_RemoveFromAccount/1.5/ Resource_BAS_RemoveFromAccount?wsdl
[bpeltask] ========================================================================
[bpeltask] ========================================================================
[bpeltask] SERVICE NOT YET DEPLOYED (HTTP/1.1 404 Not Found) http://localhost:8888/orabpel/default/Resource_BAS_SetForAccount/1.2/ Resource_BAS_SetForAccount?wsdl
[bpeltask] STARTING SERVICE DEPLOYMENT of Resource_BAS_SetForAccount in version 1.2
[bpeltask] ========================================================================
...
结论
可自动生成依赖关系图的以服务为中心的部署实现了我们所有涉及 SOA 基础架构透明性的需求。因为部署完全基于 Ant,我们也可以将它用于我们 Luntbuild 的晚间和生产构建工作(持续构建环境)。
为支持客户的 SOA 治理,我们将在客户的 wiki 中公开我们的公共流程及其文档,以及生成的依赖关系图,如此处所示:
在服务注册表中查找检索当前注册的公共服务的版本时会动态生成 wiki 页。wiki 页中的图提供了到源信息库 (Subversion) 的链接,其中包含了文档和我们公共服务的注册版本的实际大小图。点击缩略图可以通过 WebDAV 从 Subversion 中检索对应的