捕捉和分析接口特征,第 2 部分: 集成特征参考指南

本系列文章共分两部分,第 1 部分 将讨论集成特征的定义,以及如何以最佳方式利用它们来降低风险,同时提高解决方案的集成方面的设计效率。第 2 部分将提供有关集成特征本身的具体参考信息,确保充分明确地理解各项特征的意义、重要性和用途。 本文来自于 IBM WebSphere Developer Technical Journal 中文版

Kim J. Clark, IT 专家, IBM

Kim Clark 是一名来自英国的 IT 专家,目前在 IBM Software Services for WebSphere (ISSW) 工作。他在 1993 年开始从事 IT 行业,自 WebSphere Process Server 第一次实现后,就一直担任各种项目的技术主管,并经常撰写和发表有关 SOA 设计的文章。他拥有伦敦大学的物理学学位。


developerWorks 投稿作者

Brian M. Petrini, 高级 IT 架构师, IBM

Brian PetriniIBM Software Services for WebSphere (ISSW) 的一名集成架构师和顾问。他在 WebSphere Process Server、WebSphere Enterprise Service Bus、WebSphere Adapters 和 WebSphere InterChange Server 方面有很深的造诣。他自 1999 年以来一直致力于集成产品的客户实现,并且经常撰写和发表最佳实践方面的文章。他的专业是电子与计算机工程。



2012 年 4 月 19 日

简介

理解接口特征是理解系统如何彼此交互的基础。尽管某些集成规范(例如协议、数据格式、参考架构和方法学)时常会有变化,但系统间的集成特征始终大体保持相同。

表 1 给出了完整的接口特征集合。

表 1. 接口特征核心集合
A. 功能定义E. 完整性
A. 功能定义E. 完整性
B. 技术接口F. 安全性
C. 交互类型G. 可靠性
D. 性能H. 错误处理

本文基本上就是这些集成特征的一份参考指南,本系列的 第 1 部分 介绍了这些集成特征。对于某一项特征,本文提供了以下信息:

  • 描述:简单解释或问题,描述了特征的含义。
  • 示例:展示如何捕捉此特征的实际示例。
  • 您需要了解的信息:额外的信息,用于更加深入地量化特征,或者提及捕捉特性所涉及到的某些细节。
  • 关注的原因:简要说明这种特征的重要之处,以及如果未能捕捉到此项特征可能产生的后果。

上表中列出的每一项接口特征单独看起来都非常重要。或许还有更多特征需要捕捉,但这里所展示的特征的重要性得到了反复的证实。文中展示的所有特征都对集成设计有着显著的影响,并对复杂性和风险的预测有着重大影响。这些特征是根据所涵盖行业的数量、多种不同的技术解决方案的多年顾问经验确定的。有必要说明的是,这些特征中的每一种特征都负责一种项目紧急情况,如果未能在正确的时间、以正确的明确度捕捉到特征,就会发生这样的项目紧急情况。

本文将接口特征整理为主题组,使读者更易于解释、牢记和解析这样的信息。


A. 功能定义

主体数据对象

描述:主要数据对象(有时也称之为实体)的名称,这些对象可通过此接口上的可用操作交换至后端系统。

图 1. 展示主体数据对象的上下文图示
图 1. 展示主体数据对象的上下文图示

示例:后端系统可以管理大多数数据对象,例如 Customer、Order、Invoice 或 Product,因此这些就是可通过其接口使用的主体数据对象,如图 1 所示。

您需要了解的信息:这些对象属于逻辑对象,因此通常可以对比其中存储的内容。您还需要确定这些实体的所有权是否明确;举例来说,系统公开的接口是此数据的主数据还是副本?因此,实体的名称最好是从企业用于改进一致性的全局业务字典(或对象模型)中获取的。

关注的原因:在您的项目中,始终存在从概念角度上很好地认识应在各种系统内的全局数据模型中的何处发现实体的需求。如果实体出现在多个系统中,您可以迅速发起讨论,以谁拥有企业内给定数据段的 “主数据” 为中心开展讨论,并考虑此实体是否存在对应的数据同步战略。

操作/函数

描述:最终,您需要了解可在后端系统上执行或者可由各后端系统执行的特定活动,这些活动用于履行业务流程中的每一个步骤。这就构成了可由您任意处置的 “活动” 列表,如图 2 所示。

图 2. 操作粒度示例
图 2. 操作粒度示例

示例:履行一个业务流程所需的操作可能包括:submitApplication、getQuote、createCustomer、sendConfirmationLetter。请注意,操作名称通常应尽可能采用简单的动词 + 名词对形式的表达方法。

您需要了解的信息:在 “完美” 的 SOA 中,您能够在单独一个服务注册库中找到所有这些操作。但实际上,在注册库中只能找到其中的部分操作。对于其他操作,您需要研究后端系统的接口文档(如果可用)。您往往会发现,后端系统上的操作的粒度级别与您所希望获得的粒度级别截然不同,如图 2 所示;甚至有可能更糟,它们甚至有可能根本不存在。

关注的原因:这是最重要的完整性检查之一。如果操作不可用,那么您就必须创建操作。在某些时候,甚至连数据也是不可用的。同样重要的是,向下钻取到特定的操作将为您展示后端系统接口提供的活动粒度与涉及这些活动的业务流程所需的活动粒度是否相同。如果粒度不同,那么就相当于为您提供了一条早期预警,提醒您需要构造或编排,而这提高了工作的复杂性。

读取或更改

描述:操作是否造成底层数据的状态更改?后端系统内存储(或者由后端系统操作)的数据是否因操作而发生更改?如果答案是肯定的,就代表操作属于更改操纵。如果答案是否定的,就代表操作属于读取操纵。

示例:对于称为 CRUD(创建/读取/更新/删除)的传统逻辑操作,更改指的是创建、更新或删除。如果您仅仅是检索数据,而未更改状态,则属于读取操作。

您需要了解的信息:这种特性往往是从操作或函数名称或描述推导而来的,但不能提供确定性。必须独立评估每一项操作。举例来说,getAddressForContact 操作似乎必然属于读取操作。然而,请考虑这样的情况,如果系统是警察局专用系统,联系人的类型是警方卧底。出于安全性方面的原因,系统很有可能需要审计每一次读取,以便使您了解谁正在请求警方卧底的地址。审计跟踪记录意味着在这种上下文中,这样的操作实际上属于更改。

关注的原因:这种特征对其他特征有着重要的冲击效应,它对所用的集成模式也有极大的影响。读取操作在设计方面可能较为简单,举例来说,它们通常不需要事务(但是存在一些特殊情况,如 事务性 特征中所述);它们具有隐式的无状态特征,需要审计的可能性更低,而且往往适合更低的安全性级别。然而,它们也有可能具有同等或更高的复杂性;举例来说,假设操作使用是请求-响应式的,那么就需要某种关联。它们可能具有更短的响应时间要求(因为它们往往是由图形用户界面使用的),通常有着更高的吞吐率,使用更频繁,这带来了性能增强的需求,例如缓存。

请求/响应对象

描述:在使用这种操作时,您需要发送哪些数据?会获得哪些返回数据?

示例:最初,您可以简单地修饰操作名称,创建完整的方法签名,如图 2 所示。举例来说,getLoanQuote(LoanDetails, Customer) 将返回 LoanQuote。然而,最终,您将需要完整地指定请求和响应对象,需要细化至其属性级别,此外还要考虑其任何子对象的属性,如表 2 所示。

表 2. createCustomer 操作的请求和响应对象的简单指定示例
请求
Customer.firstName强制。客户的名字。< 32 个字符。
Customer.secondName强制。客户的姓氏。< 32 个字符。
Customer.dateOfBirth强制。客户的出生日期,格式为 mm/dd/yyyy。
Customer.address.addressLine1强制。客户地址的第一行。< 32 个字符。
Customer.address.addressLine2可选。客户地址的第二行。< 32 个字符。
其他
响应
Customer.referenceNumber始终返回。对客户的惟一引用,格式为 Cnnnnnnn,其中 nnnnnnn 是一个惟一编号。

您需要了解的信息:如果这些对象获取自一个包含全部可能属性的一般(或全局)对象模型,那么您还需要了解这个特定操作中使用了哪些属性,以及它们是否是强制的。这可能难以表达。距离来说,XML 架构通常用于指定 SOA 中的数据模型,它使您能够指定属性是强制的还是可选的,但对于一个给定对象来说,仅可指定一次。在本文撰写之时,XML 架构并未提供指定一个对象针对特定上下文的使用限制的方法。

特别需要注意多基数对象(数组/列表)。举例来说,在数据更改操作中,一个列表意味着什么?考虑以下,所提供的列表与现有列表部分重叠的情况。随后您是否需要将其转换为一个列表合并过程,涉及创建、更新和删除操作的组合?

最后,您需要考虑对象中使用了哪些惟一引用和枚举值,在提供方以外,这些信息通常未知或不可用。

关注的原因:如果您未达到这样的深度,就无法确保流程每一步中的所有必要数据均可用。如果不具备接口请求/响应对象的具体知识,您就无法设计从请求方的数据模型到接口数据模型之间的必要映射。这一点的重要性往往被低估,许多项目都受阻于具体设计,因为项目相关人员未能真正理解数据。

此外,对于业务流程流的验证而言,了解在调用特定操作时向后端系统发送了哪些数据、从后端系统接受了哪些数据是关键所在。否则您将无法保证拥有在每一个阶段有序执行后续举措时所需的全部数据。最初,您可以在实体级别考虑这个问题,但很快就会发现有必要深入探究个别属性的级别。距离来说,如果一个关键数据段(可以是一个复杂对象的一个属性,例如一个 “订单” 内一个 “订单行” 中的 “合作伙伴产品代码”)未出现,那么您就无法再次调用 "processOrderFromPartner"。如果没有这个数据段,流程流就会完全失效,需要额外的系统呼叫,甚至可能出现更糟的情况,需要人为干预,之后流程才能正常工作。


B. 技术接口

传输机制

描述:请求方用于为此接口连接到系统的传输机制。一个传输机制就是接口用于将数据从请求方传输至提供方再反向传输的媒介。您可能会提出这样的问题:“是什么承载着请求方与提供方之间的数据?”

示例:HTTP、IIOP、WebSphere MQ、TCP/IP。

您需要了解的信息:共有两种主要传输类型,如下文和图 3 所示。必须首先理解这些差别,之后才能讨论整体交互类型是线程阻塞还是同步

图 3. 两种最常见的传输类型
图 3. 两种最常见的传输类型
  • 非阻塞(消息传递)传输:一种消息传递传输,例如 IBM® WebSphere® MQ 等,支持请求方直接将消息放置在附近的消息队列中。这种方式之所以被视为非阻塞式,原因在于请求方仅需等待消息放置在队列中,随后即可自由地执行其他工作;换句话说,它并未 “被阻塞”。此时,提供方甚至可能不可用,请求方无疑对提供方所在的位置毫无概念。提供方可以在任意时间、按照任意顺序来处理消息。基于消息传递的交互中始终存在多个事务。利用基于消息传递的传输是实现多种较为先进的集成模式时所必不可少的。消息传递提供了请求方与提供方之间的出色解耦。
  • 阻塞(同步)传输:HTTP 等同步传输会在调用的处理过程中保持请求方与提供方之间的信道开放。请求方将等待来自提供方且包含数据的响应,或者至少是确认请求已经得到满足的确认响应。提供方必须立即处理调用。如果请求方和提供方能参与全局事务,并且传输具有事务协议,那么在单独一次事务中就有可能完成阻塞请求。采用同步传输时,请求方与提供方之间的耦合程度相对来说较为紧密。

您可能难以区分传输机制和协议。举例来说,此处的一个复杂问题就是一个接口的传输机制可能被视为另一个接口的协议。对于 SOAP/HTTP 来说,SOAP 是协议,而 HTTP 被视为传输机制。然而,在 REST 交互中,HTTP 可能会被视为协议本身,而 TCP/IP 作为传输机制。再进一步深入考虑,对于指定为仅使用 TCP/IP 的接口来说,TCP 实际上是协议,而 IP 是传输机制。您是否感到迷惑不解?大多数人都会感到迷惑。这里并不需要过于精确地区分;只需找到一个与协议和传输机制相关的有意义的术语,并保证其对大多数特征用户有价值即可。通常情况下,通过接口建立连接时需要的两个主要功能分别是相关协议和传输机制(例如,SOAP/HTTP、RMI/IIOP 或者 XML/MQ)。

关注的原因:传输机制的差异是您在集成过程中需要克服的第一道阻碍。如果不能找到一种通用的传输机制,您甚至无法连接两个系统。因此,它是我们据以标准化的第一项特征,我们将利用这项特征来提高 SOA 风格的服务的可重用性。随着 web 的普及,大多数现代请求方均可轻松利用 HTTP 传输等技术。如果提供方所提供的传输机制难以理解,那么您很有可能需要一种传输切换集成模式。您需要了解您的中间件能否轻松在这些协议之间切换,或者您是否处于一个未经证实的领域之中。

协议

描述:协议实际上就是请求方与提供方之间就如何、何时通过传输机制向彼此发送数据以及数据在另一端应如何加以解释等事项达成的共识。如果在传输机制的基础之上使用了协议,那么用于控制消息会话的是哪种协议?

示例:某些交互可能根本没有协议。使用 XML 通过 WebSphere MQ 传输的一种简单的单向交互就没有正式的协议。然而,这种交互也是非常受限的。而 Web 服务需要更为正式的交互风格,提高其可扩展性和可重用性。Web 服务常用的协议是 SOAP。SOAP 提供了一种请求和响应消息的结构,使之能够被视为相同交互的一部分,并且使之能够承载额外的数据,例如附件等。协议还定义了可用于指导应如何解释消息的标准标头,这些标头是可扩展的,因而可在其基础之上构建进一步的协议;例如 WS-Transactionality、WS-Security 等。简而言之,协议使得通过传输层承载更为高级的交互成为可能。

图 4. 一个系统的多种不同技术接口。
图 4. 一个系统的多种不同技术接口。

您需要了解的信息:如图 4 所示,一个系统可以提供多个技术接口,每个接口均适合特定的需求。接口在技术上的差异往往显而易见,因为它们采用不同的 “协议、传输机制、数据格式” 组合。较为不明显的是,某些接口可能不会公开全部主体数据对象。图 4 展示了这些方面。

请注意,REST 并未显示为协议。这是因为 REST 是一种广受欢迎的交互 “风格”,但您仍然需要选择一种协议来实现它;通常是 HTTP,但并非必需使用 HTTP。有关风格的更多细节,请参见 交互类型

关注的原因:标准化的协议能提高可重用性。SOAP 用于为大多数 SOA 服务提供消息交换包装,因为它拥有定义良好的结构,而且大多数平台如今都有支持它的协议栈。当然,不常见的提供方协议意味着需要一种协议交换集成模式,这提高了解决方案的复杂性。

数据格式

描述:这是数据的 “连接格式”。请求方应如何传输供其在接口中使用的数据?

示例:

  • 数据是作为文本还是作为二进制内容传输的?
  • 如果是文本,那么使用的是什么代码页(例如,UTF-8、Unicode、EBCDIC、ASCII、7 位、8 位或 16 位、多字节字符等)?
  • 数据是如何表示的?举例来说,如果是文本,那么是 XML、JSON、分隔符,还是 CSV?
  • 如果是二进制,那么其结构是如何定义的(例如,COBOL copybook、结构体等)?
  • 独立数据字段又是怎样的?货币采用怎样的格式(例如 "$123456.00")?各国采用的表示方法可能各有不同(例如 "£123,456.89"、"€123.456,89")。请注意逗号和点号的不同使用方法。
  • 日期格式又是怎样的?日期的格式差异较大;举例来说:"2010-10-17T09:34:22+01:00"、"2011.06.08.14.33.56"、"2011 年 8 月 30 日,星期二"。

您需要了解的信息:根据过度简化的样例数据假设一种格式的简单性过于轻率。一种简单的示例就是逗号分隔值 (CSV)。观察一个简单的样例行,如下面这个展示国家代码的样例行:

"UK, "GB", "+44"

您可能会认为它与 “分隔的” 字符串相同,但使用逗号作为分隔符,使用引号包围各段数据。但实际情况要更加复杂。查看以下这个按照特定顺序表示数据的示例:

"Size 2 Screwdriver", PAID, PART12345678, 24, $5.59, "Mr Smith, West Street, Big City"

请注意格式的细节。举例来说,如果您仅仅使用一个分隔数据处理程序,寻找逗号,那么可能会不正确地将末尾的地址拆分为三个独立字段。此外,并非所有数据字段均使用了引号;在这个例子中,仅有文本字段中存在空格或逗号时才使用引号,而数字均未使用引号。显而易见,解析 CSV 数据比解析分隔的数据更为复杂;与您在集成解决方案中可能会遇到的多种格式相比,这只是一个非常简单的示例。

关注的原因:XML 和 JSON 这两种文本格式是最适合可重用服务接口使用的格式。对于请求方来说,较为不常用的格式可能难以解析或创建,这就带来了数据处理程序集成模式的需求。必须全面理解需要处理的全部格式变体。同样,您可以看到 SOA 标准化一切方面的好处,例如标准化企业范围内的数据格式,从而提高服务的可重用性。


C. 交互类型

请求方与提供方之间的完整交互是怎样的?多种特征用于理解如何通过传输机制执行交互。图 5 展示了基本的交互类型。

图 5. 基本交互类型
图 5. 基本交互类型

(a) 和 (b) 中的交互类型实际上就是传输层原始用途所提供的交互类型,因此它们与图 3 所示基本相同。但 (c) 会按照更为复杂的方式使用传输机制。(稍后您将看到更为复杂的交互类型。)

  1. 即发即弃,非阻塞式传输:使用了一种消息传递式传输。请求是单向的,将数据发送给提供者,但无响应。请求方仅需等待传输接收到消息,即非阻塞式。
  2. 请求-响应,阻塞式传输:使用同步传输。请求方需要响应数据,必须等待提供方响应。在请求之时,提供方必须可用,必须立即处理请求。
  3. 请求-响应,非阻塞式传输:使用了一种消息传递式传输。请求方仅需等待传输接收到消息;随后即可自由地执行其他工作。然而,它必须提供一种方法,以便稍后从响应队列接收消息;并且必须能够将此与原始请求相关联。

请求-响应或即发即弃

描述:您是否希望有一条响应确认活动已发生,并且可能提供返回数据(如图 5 中的 (b) 和 (c) 所示)?或者您是否正在将一项活动排队,以便保证它在稍后的时间发生(如图 5 中的 (a) 所示)?

示例:

由于对于请求方而言,请求和响应消息可以轻松关联,因此使用 SOAP/HTTP 的 Web 服务通常用于请求-响应式交互,如图 5 中的类型 (b) 所示。HTTP 还有着仅需极少的配置即可连接请求方和提供方的优势。

即发即弃调用往往是通过 WebSphere MQ 之类的传输机制实现的,这使它们能够利用消息传递传输机制提供有的保障的交付,确保请求最终能被接收到。然而,不应假设采用消息传递作为传输机制的调用即自动属于即发即弃交互类型。消息传递同样能能够用于请求-响应。在图 5 中,(a) 和 (c) 均使用了消息传递,但它们分别属于即发即弃和请求-响应。

您需要了解的信息:有时,您可以通过其他特征得出此项接口特征的答案:

  • “读取” 类型的请求从定义上来说就是请求-响应式的,因此这种调用的目的在于 “读取” 响应数据。
  • “更改” 类型调用可以是任意风格,具体取决于它们是简单地存储一条请求,并通过响应确认请求已收到(即发即弃);还是在响应之前执行完整的变更处理(请求-响应)。

Web 服务也可用于执行一种即发即弃类型的交互,其响应仅仅是一条确认,实际处理独立执行。图 6 中的高级交互类型 (d) 展示了这种情况。

图 6. 高级交互类型
图 6. 高级交互类型
  1. 请求及确认,使用阻塞式传输:使用同步传输。提供方必须出面接收请求,但仅提供一条确认,表示活动将在稍后执行。这与即发即弃相似,请求方所需要的实际业务任务将在确认返回之后执行,但这种传输的耦合程度更为紧密。
  2. 请求-响应阻塞调用方 API,使用非阻塞式传输:这是多种传输类型的混合。一种消息传递传输机制用于与提供方通信,但请求方利用同步 API 与消息传递交互。许多消息传递传输机制都提供了这种类型的 API,旨在简化请求方与消息传递层的交互。提供方可以随时处理消息,但请求方将进入阻塞及等待状态。
  3. 通过回调执行的请求-响应,使用阻塞式传输:同步传输机制(例如 HTTP)用于为请求和回调提供两个独立交互。每个交互都是独立阻塞的,但会在收到确认时立即释放锁。这与非阻塞式请求-响应类似,但请求方和提供方采用更为直接的交互方式。

有关交互模式的更广泛的观察,请参见 企业连接模式:利用 IBM 的企业服务总线产品实现集成解决方案

关注的原因:请求-响应调用意味着需要等待后端系统,或者至少需要关联其响应。这些交互类型中的每一种都在过期和响应处理机制方面有着关键的设计含义。相比之下,即发即弃仅需要传输层的快速响应,但您必须接受这样一种设计考虑事项,即您所请求的活动可能尚未发生——实际上,此类活动可能永远不会发生,而无论怎样,您都不会得到通知。

线程阻塞或异步

描述:在操作执行时,请求方是否不得不等待?编程接口是否允许其发起活动并独立获取响应?您关注的是整体交互是否锁定,而不仅仅是底层传输机制,因此这并不像图 3 展示的概念那样简单。

示例:阻塞式传输 HTTP 是请求-响应 SOAP 协议请求最常用的传输机制;在这种情况下,它属于线程阻塞类型 (b),如图 5 所示。然而,可以通过其他更有创意的方式使用 HTTP,例如图 6 中的类型 (d) 和 (f),从请求方的角度来看,整体交互类型是非阻塞式的。尽管传输本身会暂时阻塞请求方,但它并不会阻塞整体交互。

基于消息传递的请求/响应交互始终具有保证不被锁定的容量。然而,它们是否被锁定取决于请求方如何编写消息传递 API 的代码,实际上,或许应该说是请求方可以使用哪些 API。图 6 中的交互 (d) 展示了一种混合方式,尽管确实使用了基于消息传递的非阻塞式传输机制,但其中的请求方在整个交互过程中始终被阻塞。

关注的原因:应该说,非线程阻塞式交互能够更有效地进行伸缩;正如其定义所表示的那样,它们占用的线程资源更少。然而,从将请求与响应相关联的角度来看,这类交互也会带来复杂的挑战。错误处理可能更为复杂,因为无法在单独一个端到端事务中予以执行。

成批或独立

描述:接口是处理独立业务活动,还是一次获取并同时处理一组活动?

示例:系统间的早期集成是通过提取一个包含与来自一个系统的多个业务活动相关的数据的批处理文件,并使用另外一个批处理文件内的批处理代码来实现的。这些批处理操作仅定期执行,例如,每天一次,在月末执行一次等。许多此类接口仍然存在,在某些情况下,仍然是处理大量数据的最有效的方式。

现代接口往往在个别活动的层面上工作,支持实时执行系统间的数据操作。至此为止,这一节的大部分内容均讨论了构建于 SOAP/HTTP 或 WebSphere MQ 基础之上的接口,并且假设它们处理个别事件,这符合实际情况。然而,在偶然的情况下,这些接口实际上也要承载批处理负载。举一个简单而常见的例子,即 submitOrder(Order),它用于处理来自一名客户的一份订单。设想一下,如果设计目的是传递一家店铺提交的一批订单,以便与总部通信,例如 submit(OrderList [])。实际上,使用 submit(OrderBatch) 的可能性更大,其中的 OrderBatch 包含成批的 OrderList ,还包括应用于整批订单的各种数据。基于消息的传输同样往往用于批处理。在处理大批数据对象时,消息传输无疑比 HTTP 这样的传输机制更有优势。

关注的原因:批处理彻底改变了接口的特征,从错误处理、事务性一直到性能,此外还包括所需的模式和执行工作所需的工具。现在有一些特殊工具可以用于处理采用块的形式的大量数据,称之为提取转换加载 (ETL),IBM InfoSphere® DataStage® 就是这样的一个例子。这些工具的特征与逐个事件执行处理的工具截然不同。如果主要需要的是批处理工作,那么就应该优先考虑 ETL 工具,而不是 ESB(企业服务总线)或通常用于处理个别事件的基于流程的工具。然而,使用 ESB 功能来将成批交互转化为个别活动或者反向转换可能更为适宜。

消息大小

描述:使提供方能够轻松接收同时保证提供方仍然能够满足其服务水平协议的消息大小。是否存在协定的最大大小限制,或者至少存在被视为不当的大小,或者存在阻止或拒绝较大消息的可能性?

示例:接口用于管理大型对象的部分方法包括:

  • 拒绝全部超过 100K 的消息,以确保服务不会因恶意的 “大型对象” 攻击而停止。
  • 接收大小为 10KB 的典型消息,但经过测试可接收 1Mb 的消息,用以确保处理已知存在但较为少见的较大消息。拒绝超过 1Mb 的消息。
  • 提供一种添加附件的机制(例如在电子邮件中,以及 SOAP),用以确保能够独立识别和处理大型对象。
  • 允许通过 “分块” 发送大型对象——将对象拆分为易于管理的块,这些块可以在另一端重新组合,以便将独立消息的大小保持在较低的水平上。采用这种做法时,如果有充足的资源可用,即可并行处理对象。
  • 提供一种 “流式处理” 功能,使对象能够通过一个开放连接持续发送,使整个对象始终不会显示为单独一个对象。这与分块相似,但请求方和提供方处于相对较为直接和持续的通信之中。

您需要了解的信息:在提出新的请求方需求时,您应该始终牢记这句话:能做不代表着一定应该去做。仅仅是因为一个接口能够接收 10Mb 的消息并不意味着您就应该将这视为常规使用场景。

除非系统专门设计用于管理大型对象,否则 10Mb 的消息将必须保存在系统内存之中,更糟糕的是,在系统中传递这样的消息时,很有可能会创建此类消息的副本。考虑由 JVM(Java 虚拟机)执行的内存管理,™ 如果有许多 10Mb 的对象通过系统传递,那么内存管理程序将越来越难找到连续的空间间隙,因此对象将不得不分成碎片,JVM 的速度将被拖慢,这种情况就像是硬盘中存储的文件支离破碎时硬盘的处理速度降低一样。

必须承认,新请求方将成为现有请求方群体的一部分。如果要获得不间断的优秀服务,它们就必须都能与接口良好配合。如果它们有着截然不同的需求,就应该开诚布公地加以处理,而不是尝试通过现有接口勉强处理。

关注的原因:新请求方在使用一个接口时,其使用方式可能与该接口之前的使用方式看似相同,但所传送的消息可能要大得多。一个常见的例子就是在过去的小文档中突然包含图片。这会给提供方的内存和 CPU 以及任何集成组件带来显著的影响。端到端地传递大型消息的一种常见的替代方法就是利用 Claim check 集成模式,如图 7 所示,保留大型对象,仅在接口上传递此类对象的引用。

图 7. "Claim Check" 模式
图 7. Claim Check 模式

D. 性能

性能相关的接口特征的主要用途有两种:

  • 治理:您要如何了解接口的性能能否满足其服务水平协议 (SLA)?您要如何了解一个请求方是否 “过度使用” 了一个接口?您需要能够监视使用情况,您需要具备可据以评估监视信息的阈值,您需要了解在超出阈值时英向谁发出警报。
  • 容量规划:就其现状而言,接口是否有能力在引入新请求方式进行扩展?您需要能够预测接口的未来使用情况,并在需要增加容量时提供恰当的警报。

性能相关特征为您提供了关键的非功能指标,如果没有这些特征,在早期分析阶段将无法迅速察觉到这些指标的限制。

响应时间

描述:通过此接口发出一条请求并收到一条响应之间的持续时间。

示例:这通常表示为单元内的平均响应时间,例如每秒请求数,如图 8 左侧所示。

图 8. 展示响应时间和吞吐量和顺序图
图 8. 展示响应时间和吞吐量和顺序图

您需要了解的信息:理想情况下,提供响应时间数字时应考虑到幅度范围和并发性。顺序图难以表现这些因素,但我们还是要简单加以介绍。

响应时间的幅度范围(或差幅)与平均值的重要性相当,甚至比后者更加重要。必须考虑响应时间的差幅或概况,而不应仅考虑平均值。举例来说,假设平均值是 5 秒,大多数请求都在 2 至 7 秒的范围内;另外一种情况下,平均值同样是 5 秒,其中极少数的响应花费了高达 50 秒的时间,但其他大部分时间均在 1 秒之内,这两种情况的意义截然不同。

并发性本身是一种独立的特征,我们将在 后文 进行讨论,但请注意,顺序图无法很好地表现并发性或并行处理。图 7 中的示例暗示着一次仅出现一条请求。然而,大多数接口都允许并发请求,在衡量响应时间和吞吐量数字时,必须考虑到这种因素。举例来说,可以说一个接口提供了以下响应时间特征:

平均响应时间 = 3 秒,95 % 的时间,处理 10 条并发请求。

关注的原因:请求方可能对 GUI(图形用户界面)响应度、线程限制或事务超时有所要求,如果响应时间缓慢,这些方面会受到负面影响。

吞吐量

描述:在一个有关时间段内能够处理的请求数量。

示例:图 8 的右侧给出了一个示例,其吞吐量大致为每分钟 30 条请求。正如之前在响应时间部分中提到的那样,本例假设提供方未提供并行性,因为顺序图中难以展示并行性。(更多相关信息请参见 并发性 一节。)其他时间单位也同样常用,例如每小时 10,000 条记录、每秒 10 条请求等。

您需要了解的信息:尽管吞吐量通常是按照一个时间段内的请求数量测量的,但也可能会产生误导,因为您真正需要了解的是持续(或连续)的吞吐量容量。例如,您或许能够在 2 秒内对一个接口发出 50 条请求。这是否代表着吞吐量就是每秒 25 条请求?这有可能是一个负担不了的工作负载,提供方或许不得不在内部排队处理请求。可能需要 5 秒钟的时间才能全部处理完成。如果您不是将其视为请求速率,而是响应速率,那么就可以得到更为真实的数字。就本例而言,5 秒内 50 条请求比每秒 10 条请求更为真实。

时间段应与接口的使用情况和类型相关。一个人类用户实时使用的接口可能需要按照每秒请求数量为单位进行测量,而基于文件的交互可能要按照一个小时内可以读取和处理的一个文件内的记录数量来测量。

切记,每小时 6000 条请求并不一定代表着每分钟 100 条请求。您需要了解何时是峰值时段(例如,营业时间、午餐时间等)。您的系统是否允许 “稍后赶上”,还是始终需要保持巅峰负载?

关注的原因:仅仅是因为您能够按照每秒 100 条请求的速度调用一个即发即弃接口,并不意味着提供方就一定能够按照这样的速度处理它们。它们可能会排队。在请求-响应接口中,如果您长期超出吞吐量,那么提供方可能会耗尽资源,最好的情况下也会导致错误响应,最糟糕的情况会使提供方彻底宕机;在 “服务拒绝” 攻击中就会发生后面的一种情况。如果您希望接口提供可预测的行为,那么就需要正确理解其容量。

总量

描述:较长时间段内的总量。总量 (volume) 是一个足够长的时间间隔内最大容量的测量指标,这个时间间隔内包含因维护、中断和资源共享的容量周期变化所导致的差异。

示例:应至少间隔几天的时间来测量总量(流入,每天 10000 条记录);甚至可以采用几个月或一年的时间间隔(例如,每月 100 万条记录)。您需要关注负载的概况,有时也称之为廓形 (shaping),举例来说,在白天,您每分钟可以处理 1000 条请求,但在夜间,由于 CPU 被批处理占用,因此每分钟只能处理 50 条请求。

您需要了解的信息:这项指标更常在观察请求方需求时捕捉,用以确认提供方能够满足整体需求。提供方的最大容量是通过将可用性与吞吐量相结合而得出的。

关注的原因:总量在容量规划中极为重要,使您能够迅速了解通过现有基础架构能否满足新请求方的需求。解决方法可以非常简单,例如为提供方添加 CPU,或者为网络增加带宽。然而,它也可能意味着架构的根本性重构,您需要尽早注意到这种情况。

并发性

描述:同时可处理的请求数量。

示例:图 9 展示了提供方如何一次性并行处理多个事务。在本例中,您的并发性是 3。

图 9. 一段时间内的并发/并行事务
图 9. 一段时间内的并发/并行事务

这可能是一项硬性限制,由您可以在接口上发起的连接数量约束,就像是 JDBC 中一样;也可能是一项软性限制,即提供方不断接受新请求,但在您超出提供方可用于处理的并发线程数量时,性能将显著降低。

下面给出了两种截然不同的接口,以及如何为每一种接口定义并发性:

  • 一个 JDBC 接口允许通过接口对提供方发出不超过 10 条并发请求。其他请求将被拒绝。
  • 一个基于 WebSphere MQ 的接口根据最大队列深度允许总计 1000 条请求,但提供方的线程仅能每次处理 20 条请求。在这里,您的并发请求最大数量是 1000 条,但可负担的并发请求数量仅为 20。

您需要了解的信息:在第二个例子中,您看到了最大并发性与可负担并发性之间的显著差异。对于基于吞吐量的接口使用,您应该更关注可负担并发性;而对于基于响应时间的场景,您应该更关注响应时间概况,即便超出可负担并发性也是如此,在可能存在短暂的负载峰值的基础之上,您可能希望了解响应时间是否仍能保持在可接受的水平上。

关注的原因:如果您的请求方需要的并发性超出了提供方当前能够提供的并发性,那么您可能就需要引入一种存储并转发模式,用以排队传入的请求,并给调用方留下存在更高并发性可用的印象,就像上面的第二个示例所展示的那样。这能简化调用方的错误处理,但如果排队的请求数量较多,可能会明显拖慢响应时间,如果响应出现不合理的延迟,这实际上也会增加错误处理的复杂性。相反,如果相对于偶然出现的错误,有保障的快速响应时间更为重要,那么就需要实现一种并发性限制,用以确保有限的资源始终不会超载。

您还可能需要考虑利用负载平衡来在可用资源间分布请求,以便实现所需的并发性。如果执行了复合,那么可能需要利用一定的并发性来处理并行模式,例如分散/聚合,用以在合理的时间段内聚合多条请求。可用并发性能否处理这样的额外负载?


E. 完整性

验证

描述:请求方必须遵循哪些数据验证规则,才能保证一条请求被接受?

示例:强制要求的字段、特定字段的数据格式、字段内部验证规则、枚举值、必须存在的引用/标识符/键等等。

关注的原因:理想情况下,验证是作为请求-响应交互模式的一部分执行的,这使请求方能够获知这些已知的异常情况,并立即处理问题。

如果接口是即发即弃型接口,那么验证仅可在接收到请求之后执行。在这种情况下,请求方非常有必要关注验证规则,并理解即便请求已经明确被接受,仍然存在失败的可能。

可能有必要在集成层中为请求添加预先验证,用以确保捕捉到请求方仍然存在的无效数据。

批处理即发即弃接口(例如 EDIFACT 和 BACS 等接口)也有着复杂的验证规则。在两种即发即弃情况中,都需要采用一种离线错误处理模式,这本身就有可能涉及到复杂的独立交互模式。

事务性

描述:接口提供了怎样的事务支持级别?术语事务表示组织在一个事务之中、作为一个工作单元的一组活动始终保持全部完成或全部未完成,无折中的情况。事务应符合四项主要需求,可简称为 ACID:

  • 原子性:事务执行的活动作为整体,全部完成或全部未完成。
  • 一致性:事务必须仅采用一致的信息。
  • 隔离:来自两个或多个事务的过程必须彼此隔离。
  • 持续性:事务做出的变更必须是永久的。

这是一个易于理解、记录较多的主题,因此这里不再过多陈述。然而,尽管这是一个较为简单的概念,但在理解事务的准确范围时,仍然涉及许多重要的细节,特别是在考虑交互风格、协议和传输的不同排列组合时。

示例:最常用的事务系统就是数据库。因此,JDBC 等接口标准支持请求方控制事务性操作。这是同步媒介上的事务协议的典型特征,如图 10 中的示例 (a) 所示。

图 10. 使用同步传输机制的请求-响应接口上的事务
图 10. 使用同步传输机制的请求-响应接口上的事务

另外一个例子就是作为 SOAP/HTTP 通过 Web 服务进行的典型交互。在常见的使用情况中,SOAP/HTTP 协议并不是事务性的,因此事务范围类似于图 10 的示例 (b)。可以通过 WS-Transactionality 等补充性标准引入事务性,但考虑到 Web 服务的使用环境(例如,在面向服务架构内公开可重用的服务)通常有必要在请求方与提供方之间实现极为松散的耦合,因此很少需要采用这种做法。

图 11 展示了即发即弃交互的情况,至少涉及两个事务。一个事务由请求方发起,用于将消息置入队列,另外一个事务由提供方发起,用于获取并处理消息。

图 11. 使用消息传递传输机制的即发即弃接口上的事务
图 11. 使用消息传递传输机制的即发即弃接口上的事务

在考虑通过消息传递传输的请求-响应时,可以在图 12 中看到,事情变得更加复杂。至少包含三个事务,通常情况下,提供方会进一步细分事务 2。在这里,有必要考虑错误处理。提交了事务 1 之后,如果未在合理的时间内收到来自提供方的响应,请求方会做些什么?请求方无法了解它请求的活动是否已经执行。这项活动可能因临时系统中断而暂时挂起,也可能存在较为严重的问题,因此无法得到处理,例如请求中缺失数据等。请求方如何才能在继续下一步之前要求得到活动已执行的确认?它们是否应该这样要求?

图 12. 使用消息传递传输机制的请求-响应接口上的事务
图 12. 使用消息传递传输机制的请求-响应接口上的事务

作为练习,您可以观察图 12 中讨论的内容,考虑图 6 的示例 (b) 所示的混合交互会增加怎样的复杂性。

您需要了解的信息:将一个接口称为事务性接口可能有许多不同的含义:

  • 内部事务性:一条请求带来提供方内的一个工作单元。如果您得到了并非数据内部事务性系统返回的错误,那么如何才能了解调用是否将保持了数据的一致状态?在现代系统中,通常至少可以假设这种级别的事务性,但如果后台技术位置,那么仍然值得提出这样的问题。
  • 可调用事务性:与单独一个系统之间的事务可由调用方控制,可能与对同一系统的其他请求相结合,提交/回滚选择由请求方做出。这需要 JDBC 等事务协议。这是图 10 的示例 (a) 的最低要求。
  • 潜在的全局事务参与者:可参与跨多个提供方的两阶段提交事务。提供方和协议必须支持 XA-compliance。假设例如图 10 中的示例 (a) 这样的交互必须并入一个已经包含了请求方状态更改的事务,或者必须与其他后端系统合并,那么这就是最低要求。这方面的一个例子就是对一个或多个后端系统做出请求的自动处理引擎。
  • 事务性排队:请求事务性地将工作置入一个队列,以便在独立的事务中进行后续处理。当然,这是通过消息传递传输机制进行的交互的典型特点。利用消息传递传输机制的优势之一就是使请求方无需建立与提供方之间的事务连接。现在,它们只需要了解如何通过消息传递传输机制事务性地进行通信。然而,如前文所述,这也会带来额外的复杂性。

一般而言,事务性仅与更改数据的操作相关。读取操作通常不需要(也不关注)事务性,尽管在某些少见的情况下,此类操作确实需要事务性,例如 “为更新而进行读取”,此时记录刻意使用读取操作锁定,以使其在后续更新中保持一致的状态。另外一个示例就是读取审计,如 隐私 一节所述。

关注的原因:应该清楚,为了充分理解实现的复杂性,对事务行为的理解极为重要。如果一个接口无法为请求方的目的提供恰当的事务性接口,那么就存在导致数据处于不一致状态的故障的风险。可能还需要更为复杂的错误处理集成模式,例如补偿。

也有一种相反的观点。通过接口提供的事务性几乎总是会导致某种提供方资源锁定。事务性接口意味着请求方能够控制锁定保持开放的时间长度。这可能是一种不恰当的耦合级别,在提供方基本不了解请求方时更是如此。因此,您可以故意选择不实现全局事务参与,以便减少不当耦合,并凭借对于这种战略的认识管理错误。

有状态性

描述:成功执行一个调用序列所必不可少的,特定于请求方的某些有上下文的状态设置。

示例:JDBC 接口是有状态接口的常见示例。JDBC 连接本身必须显式设置,因此如果您要避免每次创建新连接的高昂开销,事务之间就要保留一个有状态的连接上下文。此外,所有事务都必须显式启动和结束(提交),即便最简单的操作也需要通过连接发出三条独立的请求,在整个过程中都要保留有状态的事务上下文。在 Java EE 这样的应用程序容器中,这种连接和事务管理可由容器处理,因此可能对编程人员不可见;可以说,即便个别请求使之看似有状态,但完全由容器管理的整体事务本身并无状态。然而,重要连接会话上下文的有事务性仍然存在。

在 JDBC 事务处理过程中保留的部分事务状态与底层数据锁定有关。任何导致跨多个请求保留数据开放锁的交互,或者在任何底层资源上保留锁的交互都应视为是有状态的。

相比之下,典型的简单 Web 服务请求通常不是有状态的。跨请求方和提供方之间多次调用的任何中介均不会保留连续的连接或上下文。每个请求都是完全独立发生的。如果保留了任何形式的连接状态,则它将保留在非常低的级别上,而且对请求方完全不可见。

您需要了解的信息:通常的做法是将对一个数据库的多条请求包装在一个数据库存储过程之中。这种做法的原因之一就是减少有状态交互的数量。当然还有其他一些原因,包括提高性能,以及将特定于数据的逻辑保留在数据所有者手中。

关注的原因:有状态接口的主要缺点就是它与提供方的工作紧密耦合,并且对于请求方来说,使用起来更加复杂。此外,有状态接口往往可能以浪费(可能是偶尔浪费,也可能不是)提供方资源的方式使用;例如,不必要地长时间保持连接或事务开放。有状态接口也会导致可伸缩性问题,因为请求方需要通过一个了解会话上下文的路径做出全部调用,这必须使用某种形式的会话状态复制或传播。解决这种问题的方法之一就是强制连接 “粘着”,使会话中的所有请求均返回相同的端点,但这同样增加了耦合,牺牲了可用性。明智的做法通常是使用复合包装独立调用,使请求方仅能看到单独一个粗粒度的请求。出于上述所有原因,在以解耦和可伸缩性为重的 SOA 中使服务有状态是一种非常糟糕的做法。

当然,有状态接口也有一些优点。由于交换双方均保留上下文,因此每次请求中需要传递的信息更少,性能也更高。由于上下文可以采用数据悲观锁定形式,因此能够确保多次请求间的数据不会发生变化,使得一致地执行多次更新更为轻松。有些时候,在特定设计的上下文中,一定程度的折中也是有意义的,例如降低可伸缩性能够提供错误处理简单性方面的明显优势。

事件序列

描述:请求是否必须按照与其接收顺序相同的顺序处理?

示例:一个 “客户创建” 请求必然不能晚于针对相同客户的 “客户更新” 请求,否则更新就会失败,并发生 “无法找到客户” 异常。例如,在图 13 中,包含 “创建一名客户” 和 “为一名客户添加一个地址” 的业务活动的消息置于一个队列之中。为了提高性能,允许多个执行线程从队列中获取工作,使得各独立线程能够同时执行活动。

图 13:事件序列丢失导致的错误示例
图 13:事件序列丢失导致的错误示例

如果您的客户活动均被不同的线程获取,并且并行处理,那么添加一个客户地址的活动就很有可能事变,因为客户尚未创建。这些活动(事件)发生了顺序混乱。

您需要了解的信息:事件序列通常仅与往往基于队列的非线程阻塞式传输相关,存在消息提前于其他消息的风险。在从用户接口发出通常需要保留顺序的请求时,往往会使用同步线程阻塞式传输,使请求方每次仅能做出一个调用。然而,随着越来越多支持用户并行执行多项任务的用户接口的引入(使用 Ajax 等技术),时间序列的重要性将不断提高。

关注的原因:如果次序至关重要,您就需要保证保留序列。有多种模式可实现这一目标,包括谨慎的单线程处理相关请求,以及引入重新排序模式。

幂等性

描述:如果相同的请求发出了两次,那么是否会达到相同的效果,还是会产生附加效果,例如重复?如果一个接口是幂等的,那么两个或多个相同的请求应得到与第一个请求相同的效果。

示例:假设您在一个接口上有一项操作,使您能够提交抵押贷款申请书。如果您连续使用相同的数据调用了这项操作两次,那么会发生怎样的情况?它是否会:

  • 产生重复的抵押贷款申请书?如果是,那么这个接口就不是幂等的,请求方必须注意这种风险。对于这个示例,这可能是接口的一种不当行为,因为相同数据的两份抵押贷款申请书从业务角度上来讲毫无意义。
  • 导致第二个请求出错(重复提交)?在这种情况下,操作在功能上是幂等的。您需要考虑如何检测重复内容。申请书内是否存在可在两次请求间对比的主要数据(例如,申请人姓名和生日)?如果是,那么如果请求的其他部分存在不同的数据,应该怎样做?您应该如何处理这种情况?上面的错误消息可能不再是完全正确的。
  • 两次调用均成功,但实际上仅处理了提交的第一份申请书?在这种情况下,操作在功能和行为上均是幂等的。在这个场景中,只有发现请求完全相同时,这种方式的行为才是有效的,否则您将误导用户认为第二份请求中不同的数据实际上也得到了处理。

显而易见,在上面的例子中,重复提交必定有错误。然而,实际情况并非总是如此。假设通过在线书店订购图书。一名代替学生购买图书的管理员可能会在很短的时间跨度内合理地做出多次完全相同的购买。

您需要了解的信息:如果您能够从请求方到提供方地全面实施真正的事务性,那么通常就不需要担忧因重试而产生的重复,但正如事务性一节所述,这并非总是可能实现的,或者并非始终必要。如果存在任何非事务性缺口,那么请求方就有可能收到错误,使交互的成功 “存疑”,重试可能会导致非幂等接口出现重复。

关注的原因:为了对请求方(或者说,实际上是集成层)设定恰当的错误处理,必须了解一个接口的幂等性,确保在做出多次相同的请求时能够得到正确的结果。

幂等性在 SOA 中尤为重要,因为 Web 服务通常不会设置为事务性。这对请求-响应式基于队列的交互来说,也是一种常见的风险。如果未接收到响应,请求方应如何获知请求是否已被提供方接收到?即便已经接收到,它又是否得到了正确的处理?幂等性的管理绝非可有可无。

如果重复的请求可能会造成问题,那么您就需要在提供方或者集成层引入幂等性。多种相关技术通常依靠证明一条请求的惟一性来实现此目的。例如:

  • 惟一数据:一个只能使用一次的事务 ID。
  • 时间跨度:同一天内对相同年度保险费的两次付款很有可能是重复的。

F. 安全性

安全性考虑事项是接口需求中最常被忽视的一个方面。从功能上来讲,一个接口在较为简单的环境中可能看似表现完美,一个项目可能会在忽略即将出现的复杂性的情况下推进。安全性的加强可能极度复杂,需要多方面的工作,包括重新搭建基础架构和环境、重新设计、重构和重新测试海量代码。您可能会发现,一个在其他所有方面均表现完美的接口从安全性的角度来看完全站不住脚,这会导致在后续阶段创建一个全新的接口。

身份/身份验证

描述:为了确保仅有经过许可的用户和系统才能发出请求、为确立授权(下一节 将介绍更多相关内容)、为审计所执行的活动,身份必不可少。有两种关键类型的身份与接口相关:请求用户身份和请求系统身份。接口可能需要一个身份、两个身份,也可能不需要任何一个身份。

示例:

请求用户身份:接口如何识别 “谁” 执行了活动。例如:

  • 会话/连接所知的身份,例如在基本 HTTP 身份验证或 JDBC 连接中。
  • 协议(例如 SOAP WS-Security)以令牌的形式附带的身份(例如,SAML 或 LTPA)。
  • 在消息正文的其他字段中附带的身份,自主开发的安全性机制中通常采用这种形式。

请求系统身份:接口是否了解调用方系统的身份?例如:

  • 系统间由显式配置的证书认证的 HTTPS 信道。
  • 消息标题或正文中附带的调用方系统标识符。
  • 防火墙控制的系统间 IP 访问;您可能不知道系统的身份,但您知道它必然来自您信任的一台机器。

您需要了解的信息:对用户/系统声称的自身身份进行验证的方法通常超出了接口本身的范围,但它是解决方案的更广泛安全性架构的关键验证组成部分。

关注的原因:您必须确认调用方系统拥有由其支配的相关身份,传输协议和任何集成层都必须能够通过可信的机制传播这些身份。

这些身份需要是与提供方的安全域相关的身份。在简单的情况中,您实际上可以为所有请求硬编码单独一个用户 ID,但这可能会在审计跟踪记录中产生误导。如果是这样,那么就需要考虑采用更为复杂的联合身份管理机制,以便将请求方系统域中的用户身份转换为提供方域中的用户。

授权

描述:接口应如何确认一个身份是否具备执行所请求的活动的授权。

示例:在简单的情况中,可以将授权硬编码到请求方应用程序中,使之仅能做出允许它做出的请求。从安全性的角度来看,这显然并不理想,而且完全部适用于更广泛的重用场景,例如 SOA。

授权机制通常特定于所调用的系统,因此可能依赖于传播用于与其允许执行的角色对比的身份。这方面的一个示例就是 Java EE 系统中出现的授权,例如 EJB 方法中的授权。

一种替代方法是将授权委托给一个独立组件,例如 IBM Tivoli® Access Manager。显然,这有着支持集中管理授权的优势。然而,与任何集中相同,则也意味着部署应用程序所需的技能和团队更多。

您需要了解的信息:授权通常是通过角色和组建立的,因为个别用户和操作级别上的管理难以执行。

关注的原因:过去,使用接口可能要通过一个受信任的应用程序进行,由它来代表提供方执行授权。如果您现在为其他请求方提供此接口,您就必须信任各请求方能够在其应用程序中写入恰当的授权和访问控制逻辑。这通常是一种不可接受的风险,给请求方应用程序增加了过多的复杂性。替代方法通常会将授权逻辑提取到集成层中,更好的方法是将其提取到一个可由集成层调用的独立访问管理组件之中。

您还必须考虑 "adopted authority" 模式;例如,提供方信任请求方,因此在请求方表示 “代表用户 A 执行这项活动” 时,提供方就会执行请求,而不会复查究竟谁是用户 A。

数据所有权

描述:谁拥有操作触及的数据?哪个系统包含主数据?

示例:可拥有数据的位置的部分示例如下:

  • 提供此接口的系统拥有数据。数据读取和更改可由具有恰当授权的用户执行。
  • 系统中的数据是一份副本。可以通过此接口读取数据,但不能更新。
  • 数据并非主数据,但可以对其进行更改,更改将自动复制到主数据。这里需要考虑更新存在冲突的风险。

关注的原因:从更宽泛的企业视角来看,提供方存在允许您更改数据的接口并不代表着它是更新数据的最恰当的方法。在大型企业中,重要数据实体复制到多个独立系统中的情况极其常见。“客户” 数据通常分布在客户关系系统、计费系统、市场营销系统和其他许多系统中。每个系统都可能包含客户数据的不同片段。考虑在这些情况下,一项非常简单的地址更改操作的复杂性。您需要考虑是否正在通过正确的接口更新数据,是否存在必须遵循的数据管理战略,是否应引入数据同步模式来确保所有数据源保持最新。

隐私

描述:谁能看到通过接口发送或接收的数据是否至关重要?

示例:隐私问题有着多种不同的类型。其中部分最常见的类型如下:

  • 数据授权:销售人员应仅能查看其地区内的数据。
  • 数据加密:信用卡详细信息在传输中必须保持不可见。
  • 数字签名:在处理大宗订单之前,您必须能够证明大宗订单确实是由请求方做出的。
  • 读取审计:您可能需要记录谁对数据执行了读取操作,以便了解之前谁查看过数据。

关注的原因:授权(如 前文 所述)提供了一定程度的隐私性,但仅在操作级别发挥作用,而不在数据级别发挥作用。需要以特殊方式处理数据的特定属性时尤其如此。例如,有可能需要加密全部信用卡号码,也可能需要将其从集成层执行的任何日志记录中完全删除。从本质上来说,数据隐私模式与业务数据密切相关,因此很少会采用通用的方式实现,而且通常需要显式、有时复杂的、往往 CPU 密集的编码工作。对这些模式的需求对于实现预测有着显著的影响,也可能对软件许可成本有明显影响。


G. 可靠性

可用性

描述:接口最终将在何时可用?发生意外中断的频率如何?持续多长时间?

示例:可用性是服务水平协议内最重要的指标之一,因此有许多常见测量方法,例如:

  • 高可用性:一个系统的可用性百分比通常按 “9” 测量,以宕机时间与目标整体可用性之间的比例决定。例如,99.9% 的可用性称为 “三个九”,表示每天平均约 10 分钟的中断。
  • 可用性时段:可以在何时通过此接口调用系统?是否存在计划内的维护宕机时间?是否仅在办公时间提供支持?例如:24/7、工作日的上午 9:00 至下午 5:00、除银行休假日之外的上午 5:00 至下午 11:00 等。
  • 故障间平均时间:中断间的平均时间是多少?这项指标更常用作以追溯的方式评估是否实现了 SLA 的方法。

关注的原因:如果提供方的可用性低于要求,那么无论有其他多少特征匹配,都可能造成重大问题。这通常是一项难以解决的问题,因为在系统本身内提高可用性的代价可能极为高昂(尤其对于陈旧的系统来说)。如果请求方需要的可用性比提供方能够提供的更高,那么您就可能需要考虑将部分请求-响应接口转为即发即弃接口,或者引入存储和转发交互模式。

交付保证

描述:如果发出了一条请求,您是否有充分的信心保证它能得到处理?

示例:

  • 如果请求是通过非事务性协议(这是 Web 服务的默认协议)发出的,而在请求与响应之间发生了通信故障,那么就无法了解请求是否已被接收。因此,没有 WS-Transactionality 的 Web 服务请求是没有交付保证的。
  • 如果接口使用了一种事务性、面向消息的传输机制,例如 WebSphere MQ,消息将持久保留(而非保留在内存之中),提供方会通过事务的方式将消息添加到队列之中,那么您就能够获得交付保证。当然,要获得全面保障,您还需要考虑灾难恢复战略,例如是否将队列数据镜像到第二个数据中心。

您需要了解的信息:就保证交付而言,还有另外一个方面:一次性交付。您能否确保消息仅被处理一次?举例来说,如果提供方本身并不会获取一个事务内的消息,那么在某些错误情况下,就可能会对一条消息作出两次或更多次的处理。

关注的原因:如果您的业务事务价值较高,或者在丢失时会产生高成本的负面效应,那么就需要确保接口具有恰当、健壮的传输、事务性和恢复机制。如果提供方未能提供必要的保证级别,那么您可能就需要通过集成层引入一种有保障的交付模式。


H. 错误处理

错误管理功能

描述:如果在调用接口时发生错误,这些错误要如何处理?由谁处理?

示例:您真正关注的是错误如何沿接口传播,以便了解谁会受到错误的影响,谁必须对错误做出反应。

  • 在 HTTP 等阻塞式传输中,错误通常必须立即向回推送给请求方,以便使请求方能够释放阻塞的线程。随后,请求方需要管理任何重新提交。错误也可能会记录在日志中,例如,以便每天分析此类日志,观察频繁出现的问题。
  • 通过非阻塞式传输机制提供的接口也可能会提供其他错误管理选项。尽管错误可以直接反映给请求方,但向调用方隐藏某些错误也有可能是更加合理的做法,方法是存储错误并通知支持人员。如果问题得到了解决,就会发送一条成功响应,请求方不需要了解曾经出现过问题。

关注的原因:提供方采用的错误处理战略必须适合请求方。举例来说,请求方能否管理重新提交?请求方如何才能得知一个请求是否因处理时间过长而暂停,需要支持人员干预?

已知异常情况

描述:您在设计时已经了解的错误,因此可以预期通过有意义的方式报告给调用方。

示例:共有两种主要错误类型可以通过有意义的方式报告给请求方:

  • 业务错误:表示接口功能上下文的某些方面的错误。例如,“未找到客户”(在搜索时)、“客户已存在”(在创建时)、“所请求的日期无交付时间可用”。
  • 系统错误:这类错误与接口执行的功能性活动无关,但与提供方可用性或网络状态等方面有关。例如,“系统因计划内维护而不可用”、“请求因系统超载而超时”、“无连接可用”。

关注的原因:请求方需要了解出现了哪些业务错误,因为可能需要请求方具备特定代码来管理这些场景。例如,“未找到客户” 错误可能意味着将用户转到不同的页面,以便检查客户具体信息是否输入正确。

某些系统错误可能是瞬时的,在这种情况下您可能希望在集成层内实现重试逻辑,以便减少请求方遇到此类错误的几率。

意外错误显示

描述:如何将意外错误显示给请求方。

示例:在出现错误时,提供方的表现各有不同。

  • 未知错误将作为带有特定故障代码的 SOAP 故障回传。这是一种能得到充分控制的未知错误显示。
  • 未知错误作为自由文本消息回传,使用未指定的结构。对于请求方来说,这种方式更难管理,但至少是可预测的。
  • 未知错误导致多种行为,从 HTTP 丢失连接,到 HTTP 错误响应,再到自由文本 HTTP 响应。请求甚至可能无限期挂起。这是一种极有挑战的场景,对于请求方而言非常难以管理。

关注的原因:您需要确定,为使您的请求方能够捕捉、控制和记录所发生的意外错误,请求方需要具备多高的复杂性水平。您需要将请求包含在一个复杂的错误处理程序中,甚至要使用一个隔离的适配器,以便确保这些意外错误不会影响请求方的运行时。


结束语

现在您应该了解,正如介绍中所说明的那样,尽管集成协议、风格和架构不断变化和演进,但系统间的基本集成特征仍然大体保持相同。自从计算机系统最初开始彼此沟通以来,所有这些特征都是极为重要的,在可以预见的未来也将继续保持其重要性。

现在,您已经全面、具体地掌握了各集成特征代表的含义、其重要性所在以及为了成功和可靠地集成而需要捕捉哪些内容。您可以将这些信息与 第 1 部分 的内容相结合,第一部分解释了应该在一个项目的生命周期内的什么时间捕捉这些不同的特征。

有了这样的知识,您就能够通过更加系统的方式评估项目的集成要求的复杂性,降低项目风险,同时提高最终技术解决方案的质量。


致谢

作者特此感谢以下人员对于本文的贡献和审阅:Andy Garratt、David George、Geoff Hambrick、Carlo Marcoli 和 Claudio Tagliabue。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=810759
ArticleTitle=捕捉和分析接口特征,第 2 部分: 集成特征参考指南
publish-date=04192012