在 SOA 分析和设计阶段进行全面的错误处理需求分析对于正确完成设计和实施服务至关重要。缺少具体的需求以明确出错处理场景,或者缺乏将这些场景纳入 SOA 分析及设计阶段的理解,都将导致在开发阶段致力于将设计服务放在首位,只要完成功能,走正确路径(不考虑出错场景)即可。这种方法往往藏有隐患,会导致项目超支,因为之后补加的错误处理方案会产生大量的返工甚至需要对某些组件进行重新设计。
本文探讨了多个与可重用服务设计相关的错误处理要点,提供了一个框架用以说明在 SOA 分析和设计阶段应该使用何种错误处理,另外也描述了一组最佳实践,以及如何将这些最佳实践应用到设计中以确保最终的服务得以最完整的设计和实施。
简介
不同于单一整体应用,在 SOA 环境中,错误处理已成为应用设计中一个非常重要的步骤,因为 SOA 应用集成了各种异构(跨各组织边界、厂商及合作伙伴 IT 资产)的 IT 系统。在分析和设计的初期就关注错误的处理分析,能够确保在不同的平台中为不同的模块提供适合的错误处理标准 / 准则。本文所罗列的是一般性的错误处理要点,也是架构师和设计师们在 SOA 方案设计中需要解决的。SOA 分析和设计任务大致可分为三大阶段:服务标识、服务规范、和服务实现,具体可参考 Ali Arsanjani 的面向服务的建模和架构。后续关于该话题的讨论所围绕的错误处理要点都适用于这三大阶段。
服务标识中的错误处理
服务标识的目的是为了确定某一侯选服务组合,使其能够识别可重用的服务组合。该阶段包含了对业务工件包(其中包括关键需求、业务目标、功能模块、业务流程分析模块、用例等)的分析。
错误类型
错误大致可分为两类:
- 可恢复性错误——可恢复性错误是指那些可通过恰当的可选执行路径来恢复用户程序的错误。这些错误是由于不遵守某一特定业务规则所导致的。
- 不可恢复性错误——这些错误是客户程序无法恢复的。此类错误是在运行时中由某些不可预期的错误产生的,诸如空指针、资源不可用等编程性错误。
业务错误的标识
分析整个业务工件包为发现与服务关联的业务错误提供了很多机会。假设已存在某资产正用于某业务服务,那些组件接口可用于发掘那些通过自上而下分析所不能发现的其他业务错误。所谓业务错误实际上是一种可恢复性出错。一旦服务组合进入了最后的定稿阶段,那么请从以下几个错误处理的方面来评估可重用服务:
- 业务错误场景——详细描述会标记某业务操作无效的条件。
- 错误概述——当某一业务错误发生时服务消费者收到的业务出错提示,它提供对业务出错的简单描述。
- 错误代码——可用于查询和某错误相关的附加信息的代码。
- 建议——给服务消费者的反馈,诸如有效输入、或显示有关出错的具体信息等等。
- 服务区域——标识某一服务区域,该区域可接收到与服务系统错误相关的所有通知。
这些定义了业务出错的属性既可以涵盖在服务合同中也可以按照需求打包进服务响应中。
流程错误恢复场景
- 标识新操作——业务流程(长流程)或者任何微流程(短流程)都需要根据各自服务在其流程中可能抛出的业务错误来加以分析。这种分析可以引导发现更新的操作,而这些操作在传统的自上而下的流程任务分解中是无法被发现的。
- 更新流程模型——服务操作模型 / 依赖性可随着在前一步中发现更新的操作而得到更新。
服务规范中的错误处理
服务规范阶段包含以下任务:定义输入及输出消息、服务和操作名称、模式、服务组合、非功能需求以及其他诸如同步 / 异步、调用方式等被标记出来作为服务的特征。
错误处理相关的特征
与错误处理相关的一般服务特征有:
- 有保障的交付——决定了某一服务是否要求有保障的 QOS(服务质量)交付类型。该需求帮助设计者们设计合适的异步消息处理设计模式,或者如果采用 Web 服务来实现的话使用可靠的消息处理机制。
- 监控需求——决定了是否需要为服务业务关键性错误建立事前监控。
- 错误映射 / 转换规则——建立由服务提供者所返回的错误代码 / 信息的转换规则,以及这些返回的信息该如何提供给服务消费者。就处理服务出错而言,标准的业务错误代码有助于应用程序更得心应手地使用这些服务。
- 更新处理流程——随着较新的操作发生或者在标识阶段处理业务错误时所发现的可选执行路径,现有的处理流程将得到进一步更新。
- 事务属性和边界——各种错误各具特色,例如系统出错与程序出错,这种错误的特性影响不同的运行时平台如何处理自动回滚。在某一流程中的事务属性和边界将根据发生在单个服务调用 / 事务时的错误进行分析。
错误的传递
可以使用多种方法来向服务消费者们传递错误,而其中非常重要的就是要给企业作出一个架构设计决定用以选择一个最为合适的传递方式。
两种最受欢迎的返回错误信息的方式就是使用 SOAP fault 或者定制化错误消息体。两种方式各有利弊,人们选择时大多基于现有的开发和运行时平台。使用面向 Web 服务的平台所实现的服务找到 SOAP fault 作为其必然选择是因为有大量基于 Web 服务工具的支持,而定制化错误消息体则更加适合那些使用传统的面向消息的中间件(MOM)平台所实现的服务。有关这个问题的进一步的探讨可参见 Boris Lubinsky 所做的比较。总而言之,鉴于客户工具在各种不同程度上的支持以及服务器对各种不同概要(profiles)的支持,不可恢复性的系统类错误更宜作为 SOAP faults 返回,而可恢复性的业务错误则更适合使用定制化错误消息体进行描述,因其能灵活和扩展地定义定制化错误模式(schema)。尽管如此,使用定制化错误消息体仍然要求服务消费者做额外的客户端处理程序来解析响应消息从而判断调用是否成功。
一般企业范围的自定义模式
通过标识元数据及一般模式来持续描述企业中出现的各类错误。该数据可包含常用的属性,这些属性包括日期、时间、错误代码、描述、严重级别、消息来源、相关 ID 等等。对于该元数据的全方面分析将十分有助于建立有效的服务监测。
服务实现中的错误处理
服务实现阶段是指服务模型影射于服务组件和运行时 / 部署模型时期。该步骤一般包括设计服务组件、分配组件至 SOA 各堆栈层、选择组件交互方式、运行时平台,以及制定架构设计决策 (ADD)。关于此话题的后续讨论将着重围绕一些最佳实践,其中将错误处理方案实施到典型的企业 SOA 堆栈三个层次中:业务流程或编排、中介 / 总线以及组件,如 **下图 ** 所示
业务流程 / 编排层的错误处理
该层所部署的组件实施业务流程或编排。以下是可用的错误处理要点:
- 错误处理器——错误处理器是解决编排向外调用过程中返回的错误的最受欢迎的方式之一。错误处理器在某一流程中与特定任务绑定,或者作为整个流程的一种全方位错误处理工具。当流程中有错误发生时,错误处理器就会被调用,由它实施更正的任务。补偿事务和手动回滚都设置了错误处理器,所以恰当的纠正措施可应用于处理流程错误。使用错误处理器时,不应将其用于可选执行路径上,而应该用于对流程抛出的错误进行恢复。
- 服务状态信息——流程编排场景通常包含调用多个服务。这些在流程内部所调用的服务可能会因多种严重程度等级(从信息、警告、错误到致命)的出错而终止。从每个调用中收集状态描述是很好的实践,例如将错误代码等返回到一个可重复的数组中然后原样返还给服务消费者。这样的做法使服务消费者能够判断整个流程是否包含由某些服务中流程所调用所引起的任何警告 / 错误。
- 阀值错误严重级别——定义错误严重级别阈值,并在服务编排中根据这些阈值设计容错级别。阀值级别可根据任意属性或某个定义错误的组合(如出错严重级别、定制状态代码等)来确定,而这些确定因素不能仅仅依靠 SOAP faults 来判断流程的失败。
服务 / 协调 /ESB 层的错误处理
企业服务总线 (ESB) 层是典型企业 SOA 堆栈的核心。该层支持所需的转换及路由能力独立于企业的可复用服务。该层组件通过使用恰当的消息和协议转换为各种提供商实现(如现有相关资产及基于合作伙伴或厂商的服务)提供了一种明确的接口。由协调组件完成的错误处理一般都包含将提供者错误结构转换成在业务域的上下文中明确定义的错误结构。这些组件也可以处理一些复杂的转换和错误的影射规则,这些错误由后台功能组件返回,在企业内部为服务消费者们提供了更为简单的错误信息。
- 转换提供者错误代码——不同的服务提供者会使用不同的语义来返回服务错误。范围涵盖很广,从流行的 SOAP faults 到相当专用的结构。适当的转换规则可应用于此,以便可重用的企业服务能使企业应用程序以更一致的方式返回错误,轻松解析和实施合适的处理器。
- 过滤敏感信息——当内部服务组件抛出致命错误时,堆栈跟踪往往包含敏感信息,比如所使用的协议、服务器 IP 等等。这一层将设立适当的过滤规则来过滤所有在堆栈里跟踪的敏感信息。当通过可信赖的网络传达服务响应时这一策略变得尤为重要。
- 捕获应用错误——服务组件所经历的任何技术性错误(如资源不可用或是一些运行时异常等)会转换成某种简单的技术错误消息。如果本地组件不记录这些出错,那么协调层可以将所有堆栈跟踪信息传递到日志,但却只是将通用文本消息返还给服务消费者并通知服务暂时不可用。
这一层所提及的许多出错处理的方案也可以应用于组件层。但是市场上有大量 ESB 和框架已经包含这些东西,其配置性和灵活性比起独立平台开发人员实现其功能组件实现方案要更佳。ESB 提供的出错处理仲裁关注点的分离使平台开发者们摆脱了必须应对各种各样出错处理方案的窘境,使他们把注意力更多地放在实施业务功能,提高生产力。
组件层的错误处理
这一层的组件出错处理包括处理异常操作的情况(如某一资源不可用或者运行时组件不按指令处理又或者背离逻辑)。组件需处理类似事件以通知用户程序,并且做适当的日志以便促进排除故障和服务监测。在 Java 编程语言中,类似事件的抛出称作异常,并且 API 提供了两种不同的异常:已检查异常和未检查异常。已检查异常继承自 Exception 类并用于处理可恢复性出错诸如业务出错场景。未检查异常作为运行时 Exception 类是理想的异常侯选处理不可恢复性出错,如资源不可用或者空指针。
组件层出错处理的第二个部分就是要做适当的日志。在离错误源发生最近的地方做日志是很好的做法。当组件抛出应用出错时,他们可以在组件边界内通过适当的接口记录异常,然后再抛出异常。使用关联性 id 来标识事件并将其传递给调用应用程序将可以通过链接不同平台日志的方式大大增强出错跟踪和监测。
事务回滚和补偿
设计合理的容错机制以维持流程中的 ACID(原子性、一致性、隔离性和持久性)特性是设计 SOA 解决方案的一大挑战。这些解决方案一般包含业务流程,可调用的服务可跨不同平台、多种交互模式及由不同的资源提供者提供。一个业务流程中所参与到的所有服务多半不是事务性的。一旦有某个特定的事务在某一流程中失效,就会有相应的恢复性措施用以维持数据的完整性。事务回滚和补偿事务是解决问题的两种方法。
事务回滚可通过一个事务监测器从而协调各事务来实施,前提是业务流程跨越一个限定域且所有资源都是事务型的。如业务流程更复杂些,无法完成业务流程不仅需要回滚,将数据返回至一致状态,而且需要流程调用一定的补偿事务(诸如发送警告,或在调用撤消操作来撤消前一步的服务调用等)。这远远超出了本文所论述的问题的范围。读者们可参考此空间中即将上传的 Web 服务标准:Web 服务协作(WS-C)和 OASIS Web 服务事务(WS-T)。
小结
本文提供了一些 SOA 架构技巧以用于从业务工件包中发现错误处理的需求以及在整个 SOA 分析和设计阶段如何分析这些需求。同时也提供了一些在 SOA(解决方案堆栈的)三层(如服务编排、协调及组件层)之中进行错误处理的最佳实践。
对各种错误处理要点的全面直接的分析有助于架构师们在设计和实施阶段、平台和 SOA 堆栈产品方面作出正确的决策。
关于作者
Hari Poolla 有着丰富的 SOA 实践经验,就职于位于美国中西部的一大型的保险金融服务公司。他主要关注于应用架构、BPM、解决方案设计、以及企业应用领域的集成与合作,专攻建立企业可重用服务。为企业 SOA 采用路线图及设计定制 SAO 解决方案发展理论提供专业咨询。他具有 IBM 的 SOA 解决方案设计师认证以及 Sun 认证的 Java2 平台企业架构师。他曾经参与电子移动基金 (EFT) 在各个不同行业构建和实施一个基于 SOA 的业务解决方案。你可以通过 hari_poolla@yahoo.com 与他联系。
查看英文原文: Error Handling Considerations in SOA Analysis & Design
感谢马国耀对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。
评论