内容
本页内容
![]() | 消息 |
![]() | 消息路由 |
![]() | 消息交换的形式 |
![]() | 消息处理要求 |
![]() | 消息处理基础结构 |
![]() | 消息处理小结 |
![]() | 注意 |
正如服务一文所描述的,服务是通过交换消息而进行交互的。 在我们提出的服务模型中,服务完全由其自身接受和产生的消息来定义,包括那些消息的排序要求。 消息在服务之间的成功路由是一个复杂的过程,而在组织所公开的服务之间共享的消息处理基础体系结构则可以最好地处理这一过程。
本主题将详细探讨这些概念,为读者提供消息和消息传送在基于服务的体系结构中所扮演的角色的概念视图。
消息
消息是从一个服务传送到另一个服务的信息单元。 消息必须是高度体系结构化的,这样才能被分析和理解。这种体系结构使用抽象描述了消息元素的架构文档在服务和解决方案开发人员之间进行通信。
消息架构中包括的关键信息有:元素名、数据类型(例如,“integer”)、值约束(例如,用于表示近似概率的整数可能要求在 0 到 100 之间)以及元素是否为必需。 利用强大的架构定义语言,可以用简单的类型来构建复杂的体系结构。
正如服务一文所提到的,服务需要独立于平台的类型系统,以实现互操作性。 这种系统必须明确地定义诸如 “integer”(整型)和 “float”(浮点型)这样的类型的位长,避免采用不易于在目标平台上实现的构造,通常便于将线格式数据元素转换为特定于系统的数据元素。
选择适当的类型系统只是软件设计人员必须设计具有互操作性的服务消息时所采用的方法之一。 消息是服务设计过程的中心;是要使各方都能够看到。 如果消息设计得不好,最终不得不进行修改,这将导致昂贵的重设计成本,因为所有服务使用者都迁移到新的界面。
消息设计包括功能元素和操作元素的定义,支持服务的功能要求和操作要求。 因为操作元素可能受到不理解功能元素的消息传送基础体系结构的作用,设计人员应该借助传输协议来确定功能元素的 “正文”之外的操作元素。
可互操作的消息设计的另一个原则是,充分利用 “头”和“正文”架构中现有的元素定义。 要最大限度地利用服务存储的电话号码,应该使用一个广为接受的元素定义来建模。 这种做法减少了设计工作,并且,这些人们普遍理解的元素可以原封不动地复制到使用它们的其他服务。
在概念上讲,消息必须是自给自足的,包含或引用了理解消息所必需的所有信息。 实际上,这种消息状态的一部分可能是不言而喻的: 例如,使用超文本传输协议 (HTTP) 时,来自服务的应答被解释为对同一连接上发送的请求的响应。
消息路由
我们最熟悉的消息传送形式是请求/响应: 发送者打开一个到接收端口的连接,发送消息,然后收到确认(可能结合了请求消息的处理所产生的响应正文)。
虽然看起来只进行几个步骤,但是,真正的过程常常更为复杂。 消息的传送通常要通过中间层(例如,高速缓存、过滤防火墙和凭证管理系统)。 这些中间层可以说是要侦听消息,以进行部分处理或完整处理。中间层可能产生异常(例如,拒绝访问请求的授权中间层),导致返回给发送者一个错误。
侦听是消息处理基础体系结构的概念基础。 通过侦听,消息得以沿着复杂的路径路由,以便共享的专门服务可以参与消息处理。
侦听更常见的一个应用是,使用不同的消息格式在服务之间进行请求转换,如图 1 所示。 这种模式既可以用于在使用专有协议的系统的前面提供符合标准的接口,又可用于转换遵守过时版本的服务协定的消息。
![bdadotnetarch08_03](https://i-blog.csdnimg.cn/blog_migrate/b736eba78386187366296f283cc04448.png)
图 1. 充当其他服务转换器的服务
请求也可以基于消息的任何元素或属性重定向到其他服务端口。 这种基于内容的路由的示例包括状态划分(例如,按日期划分的新闻存档)和网络拓扑优化(将请求路由到本地服务端口,而不是相距许多跃点的服务端口)。
在服务一文中已经简单讨论了异步消息传送的设计价值。 除非我们必须使请求非常迅速地收到响应(例如,一个不耐烦的用户访问网页的请求),否则,服务应该使用成对的端口进行异步交互。 发出请求的服务应该在消息头中提供响应可以被发送到的端口标识符。 实际上,请求者被放在消息处理链的末端,使用由实现与请求相关联的基本业务逻辑的中间层和服务创建的响应。
消息交换的形式
前面简单讨论了几种不同的消息交换形式。 不同的交换形式适用于不同的服务。 以下是一些交换形式的示例以及它们的使用原理:
• | Fire and forget(发后不理)。 使用这种形式时,只发送一个消息,并且不期望得到(或者不愿意接受)响应。 这种形式通常用于发送状态更新,如温度读数。 |
• | Monolog(独白)。 使用这种形式时,消息流被推向服务端口,没有应答。 独白通常用于音频/可视内容,经常使用多播或广播将内容推向一个以上的接收者。 |
• | “请求/响应”(请求/响应)。 这是一种我们很熟悉的形式,此时,客户端期望立即得到对信息请求的响应。 这是 HTTP 在 Web 上使用的主要消息交换形式。 |
• | “对话框”(对话)。 这是一种与多个由认可的协议绑定的相关交换建立的点到点连接。 简单邮件传输协议 (SMTP) 就采用这种形式。 |
• | Conversations(会话)。 虽然所有前面的形式都可以视为“会话”形式,但该术语在这里用于描述一种可能涉及许多服务的灵活的交换。 利用会话形式,可以进行支持实际业务功能所必不可少的复杂交换。 |
提供这个信息交换形式清单的目的并不是建立一个词汇表,而是为了说明服务设计人员需要选择适合应用要求的交换形式。
可以在服务提供中混合使用这些形式。 启动“独白”的请求/响应交换就是一个示例(例如,请求新闻提供的新闻“自动收录器”应用程序)。该自动收录器会发送一个包含将接受消息流的端口标识符的请求。 新闻提供服务会验证请求,如果该请求有当前订户的凭证,就会作出肯定的响应。新闻提供服务会将自动收录器的端口添加到多路广播列表,之后,自动收录器就开始接收消息。
长时间运行的异步会话给消息处理带来了若干个复杂因素。 首先,涉及到的一些服务,尤其是过程的发起方,需要维护有关会话的某种状态。例如,供应管理服务可能代表技术人员触发采购请求。为了能够向技术人员通知进度(即使是告知正在进行中),需要在交换的所有消息中都包括一个标记,以便唯一地标识会话。其次,在会话中,必须以每个消息为基础来建立安全上下文;没有任何会话上下文可用于凭据的缓存。
消息处理要求
与对网页的请求不同,实现高价值业务流程的服务通常更关心传送机制的可靠性,而不是响应的速度。为了使基于服务的应用程序结构成为业务应用程序值得信赖的平台,必须满足一些使用要求,这部分内容将简单介绍其中的一些要求。
可靠的消息处理
同步消息传送不可能完全可靠。 由于网络问题或系统故障,目标端口可能不可用。 网络延迟可能导致无法预测的请求滞后时间。 由于路由特性,消息流可能以错误的顺序到达。
传输的不可靠性的一般解决方案是,如果最初的传送尝试失败,就将请求排队并依靠重传。 但这个过程又带来了另一个可能发生的问题: 同一个消息的多个回执可能产生很不好的效果(例如,进行重复的订购)。 消息传送的一个原则是,确保消息的幂等性,也就是说,确保一个消息的多个回执具有与一个回执相同的效果。
可靠的消息传送基础结构的目标是,确保消息只按照正确顺序传送一次,在由策略驱动的时间间隔内无法实现此目标时,减少异常的产生。
并非所有应用程序都需要可靠的消息传送;例如,如果丢失某个消息,包括丢弃“迟到”的消息(也就是说,在后续消息之后到达),流音频也可以正常播放。但即使在这种情况下,应用程序也需要具有消息排序的意识,这样才能“播放”以错误顺序到达的消息内容。
针对可靠消息处理的大部分支持已经包含在基础结构服务中,无需为每个应用程序重新编写。 但在副作用特别严重时,可能需要对服务进行特殊改进,以确保消息的幂等性。
路由
复杂的消息路由对于实施实际的解决方案是必不可少的。消息可能需要通过在许多其他解决方案中提供可靠的消息传送、检查安全凭据以及维护消息通信的独立审核跟踪的服务来进行路由。
为了使不同的服务都能理解各个消息的路由需求,必须有一定的标准。 当 A 成功完成消息的处理后,消息头需要能够告诉服务 A:消息应该被发送到服务 B。 消息处理链中的所有服务都需要知道出现意外时如何路由异常。
如果使用了许多不兼容的路由协议规范,结果将产生一堆非可互操作的服务。 服务架构师应该选择满足最低应用程序要求的、实现最广泛的规范。
安全管理
安全性是在将业务流程移植到可由组织之外的其他方访问的网络时需要考虑的主要问题。消息需要得到保护,防止发生数据盗取和篡改;人员和系统需要经过可靠的身份验证;服务必须针对服务攻击的入侵以及如何拒绝攻击而进行强化。
网络安全是一个需要大量特定解决方案的多方面的问题。有些安全机制可作为共享服务或通过路由和过滤基础结构得到最佳实现,而其他方面的安全问题则必须在服务本身的范围内被解决。
软件设计人员的考虑因素包括:
• | 编译器和运行时环境的选择。 如果超出界限的内存访问可以用来影响外来代码的执行,服务就很容易受到危害。目前的开发工具和执行环境有助于防止这种攻击。 |
• | 日志记录和日志分析。 服务应建模为理解正常的访问模式和异常的访问模式。 所开发的系统应该能够向操作人员警告可疑活动。服务访问模型会随着时间的推移不断发展,因为实际操作经验有助于加深组织的理解。 |
• | 数据加密。 应该使用机制来保护敏感数据,防止未经授权的其他方对其进行访问(包括被授权作用于消息的其他部分的中间服务)。可以通过用只有预期的参与者才知道如何解密的方法对消息的特定部分进行加密来实现此目的。 |
• | 消息完整性。 安全校验和可用于说明消息在传输过程中尚未被修改。 它可以应用于部分消息,也可以应用于整个消息。因为中间层可能需要向消息添加头元素,所以,整个消息的校验和可能需要在每一跳重新计算;这个过程有力地支持了基于标准的完整性检查方法。 |
• | 身份验证和授权。 识别远程用户和服务带来了相当大的挑战。用户简直就是运行方面一个最令人头疼的问题:当合作伙伴组织中发生角色变更时,将影响对您的服务的访问权限;而从不同提供商访问服务的用户却不想管理每位用户的唯一凭据。解决方案是,将身份验证和权限管理安全地委托给合作伙伴,同时,服务协定明确地规定由合作伙伴对来自其组织的不当访问负责。在不久的将来,这将是一个相当大的创新和开发领域。 |
记录和审核
出于对组织智能以及对前面提到的安全注意事项的考虑,组织必须理解服务的使用原理。共享的日志记录功能应该向共享的分析引擎提供信息,分析引擎可允许组织进行服务建模、规划容量并对产生的问题进行故障排除。
有些服务可能需要由服务使用者和服务提供商以外的独立代理提供的可审核记录。使用这样的服务,可能对遵守政府规定或解决在合作伙伴组织之间就有关处理了哪些消息以及何时处理所可能发生的争端是非常必要的。
缓存管理
有几类服务会产生可缓存的结果。其中可能包括静态信息,例如,证券在特定日期的收盘价格,或可以在一段时间内有效地对其进行处理、但在采取行动之前应该进行验证的数据(例如,飞机航班上座位的售出情况)。
Web 缓存使用统一资源定位符 (URL) 作为密钥,并且很少尝试缓存复杂查询的结果。服务不提供这样的简单方法,因此必须通过开发标准来为服务请求派生密钥,并允许服务在响应中向中间层和使用者告知关于数据可缓存性的情况。
第 6 章“State”将详细讨论服务如何使用可缓存的数据以及不可缓存的数据。
消息处理基础结构
在刚刚提出的对强健的消息处理的操作要求中,有许多应该在消息处理基础结构中实现。该基础结构在概念上包括:
• | 公用组件。 组织需要为所有实施服务的系统使用的侦听和消息处理软件设立标准。 |
• | 组织基础结构。 路由器、防火墙和共享服务在满足安全要求、日志记录要求和基于内容的路由管理要求方面扮演了重要角色。 |
• | 合作伙伴基础结构。 类似地,使用您的服务的组织的网络和服务基础结构对于服务交付的安全性和可靠性同样至关重要。 |
• | 公共基础结构。 消息可能在使用组织和提供组织的网络的边缘的路由器之间经过很长的路径。除了提供了简单的比特流,公共基础结构还包括组织选择的用作实现审核、身份验证、加速和其他功能的中间层的服务。 |
图 2 以图形的方式描述了消息处理基础结构。
![bdadotnetarch08_03](https://i-blog.csdnimg.cn/blog_migrate/af7f441587d929aa900af8aa43b1b586.png)
图 2. 消息处理基础结构
由于所有消息都要通过消息处理基础结构,因此,它是管理操作功能的理想环境。这就意味着,您可以将核心业务功能(即您的服务提供的业务流程)与操作功能分开,这是您的服务与其他服务通信的方式。通过这些功能的分离,还可以将责任分配给组织内适当的专家组。
虽然您是独立于服务将使用的传输来设计服务的,但仍须考虑到这些服务还是会涉及到网络传输的。 业务逻辑将需要照顾分布式处理和异步处理的复杂性。
消息处理小结
消息是网络服务的设计中心。通过将重点放在正被操作的状态的线格式,基于服务的结构有利于集成和互操作性的设计。针对水平消息处理问题的标准解决方案将极大地有助于实现可互操作的服务的目标。
消息沿着复杂的路线,从使用者那里出发,通过中间层,到达服务提供商。 最终的响应也可能沿着另一个同等复杂的路径返回。服务和使用服务的应用程序必须在考虑到这些复杂性的前提下进行设计和开发。 将服务调用视为同步功能调用会产生脆弱的应用程序。
编写服务以及使用服务的应用程序时,涉及的大多数复杂因素应该被提升到在应用程序要求和组织策略允许的前提下尽可能更广泛地共享的消息处理基础结构。此基础结构将成为未来几年内整个计算机行业中创新和开发的关键方面。
注意
• | HTTP 的 Keep-Alive(保留连接)允许每个连接有多个交互,但这种形式仍然属于请求/响应。 |