服务通过发送和接收消息的服务接口进行通信。服务到服务的通信遵循协定,通过明确此协定,用户可能在不影响交互的情况下更改服务实现。
本页内容
![]() | 协定简介 |
![]() | 服务接口 |
![]() | 设计时协定 |
![]() | 运行时协定 |
![]() | 服务接口 |
![]() | 会话 |
![]() | 协定小结 |
![]() | 注意 |
协定简介
两个服务进行交互时,消息在它们之间来回发送。 两端都需要确切知道它们发送的是什么、如何发送、预期得到什么以及如何预期。不但有必要定义可以发送什么消息、消息应该采用什么格式以及如何发送消息,而且重要的是,还要指定这些消息应该按照什么顺序发送。协定是两个服务之间发送的所有内容以及如何发送的定义或绑定协议。
服务接口
服务通过服务接口向其他服务提供它们的功能。服务接口用于接口用于对象的服务。 对象接口定义了方法调用的特征,而服务接口则定义了消息的特征。有一些格式可同时用于描述这两种接口,例如,可以使用 Web 服务描述语言 (WSDL http://www.w3.org/TR/wsdl) 来定义服务接口,这与在 COM 中使用接口描述语言 (IDL) 的方式几乎一样。
如果一个对象要使用另一个对象,它需要知道那个对象的接口。 同样,要在另一个服务的程序代码中使用此接口,则必须知道该接口的特征。可以利用工具来使用服务的实现或接口的描述来生成可以与服务通信的代码。对于要使用服务的程序员而言,这两种途径没有多大差别。
虽然服务接口与对象接口类似,但有一个重要区别: 服务接口不支持实例模型。一个对象对另一个对象实例化,然后调用其接口来使用该对象;之后就可以对该对象进行若干次调用。服务只向一个服务发送一个消息;当发送多个消息时,基础体系体系结构可能将这些消息发送到不同的物理位置,不过,客户端通常觉察不到有任何差别。当对象远程调用其他对象时,通常称之为远程过程调用 (RPC)。
服务接口描述消息需要操作的完整信息。 其中包括服务提供的函数,以及这些函数的参数和返回值。可以把请求或响应看作动词,而将参数看作主语,这些主语常常被称为业务文档或文档。
因为使用者和服务相互通信,所以二者都可以发送和接收消息。 因而,使用者也必须是服务,服务接口必须定义传入消息和传出消息。服务接口以匹配对的形式存在;最简单的匹配对接口由能够发送请求和接收响应的传统代理提供。
我们会在设计中使用服务接口,不使用实例模型,使用在空间和时间中分布的交互,使用有时不可靠的异步消息处理,使用复杂的异常处理,但这一切并不能使设计服务变得更容易。设计一个可靠的服务需要时间,这使得服务设计的成本居高不下。
设计时协定
两个服务进行交互时,消息在它们之间来回发送。我们不但有必要定义可以发送什么消息和消息应该采用什么格式,而且重要的是,还要指定这些消息应该按照什么顺序发送。
例如,买方可能发送一个采购定单,并期望卖方发送一个承认已收到定单的确认消息。然后,买方可能预期卖方在三天之内发送定单确认(例如,确认已接受定单并且正在处理),在收到此确认之前,买方可以取消定单。买方需要理解并预料到将收到这两种消息。卖方可能也需要能发送部分确认消息,如果订购的商品缺货,可能甚至会发送替代商品的建议。
买方和卖方之间的交互可能非常复杂,如果双方没有用相同的方式理解这种交互,最终就会出现问题。
在进行两端的设计之前,双方需要就许多先决条件达成一致:
• | 交互的目的是什么? |
• | 交互中有哪些参与方或角色? |
• | 使用什么消息? |
• | 那些消息采用什么格式? |
• | 有哪些可能的消息序列? |
• | 每个步骤后可能继续发生什么事情? |
• | 可能出现哪些业务异常? |
• | 业务异常或技术异常出现后采取什么措施? |
协定用于定义消息、消息格式以及消息的发生序列(基于交互角色)。需要说明的是,消息序列包括可能的异常以及对这些异常作出的反应;异常可能是由参与方导致的,也可能是由基础体系体系结构导致的。例如,如果其中一个参与方没有及时响应,可以视为业务异常;不过,如果无法及时传送消息,则说明出现了技术异常。具体的划分常常取决于涉及的业务情况;如果响应预定在几天内返回,发生阻止传送的技术异常的可能性最小。如果要求在几秒钟之内响应,协定应该明确地定义对异常作出的反应。
每个参与方都必须在协定中实现自己特定的角色。 在前面的示例中,整个处理实现了买方的角色或卖方的角色。协定通常由两端的处理来实现。这种处理定义了发送消息和接收消息的操作,并且具有判定发送哪个消息或预期哪个消息的判定点。 该处理还定义了从外表看来不可见的操作。例如,收到定单后,处理可能会检查是否有库存以及给买方打多少折扣。虽然响应可能取决于那些内部操作,但另一端感觉不到判定过程的存在;另一端知道它可以预期许多反应中的任何一个,但服务接口隐藏了判定算法。
图 1 阐释了两个正在通信的服务之间的协定。
![bdadotnetarch08_03](https://i-blog.csdnimg.cn/blog_migrate/388f1bd73c6c0522bace46e483e85214.png)
图 1. 协定
服务接口不仅定义消息和消息格式,还定义排序约束和任何其他约束(例如,超时期限、异常以及对例如排队的传输的要求)。 它是服务在协定中扮演的角色的定义。
服务可以使用多个接口(常常如此),以便与多个其他服务进行通信。 例如,收到采购定单的服务可能需要与仓库服务、记帐服务等通信。
定义设计时协定
定义服务时,需要确定该服务将发送的消息、由该服务接收的消息以及这些消息的大致序列。 还应该确定异常,包括可能发生的超时异常,以及应该如何处理这些异常。这些内容确定后,定义服务(接口)的外部行为,然后就可以确定协定。 这个过程完成后,可以实际编写实现代码。
这里再次强调,在应用程序生命周期的设计阶段正确地确定和定义协定是一项投资,这种做法有助于:
• | 用正确的行为构建服务。 如果为服务定义了接口和消息序列,就可以在会话的任何一端实现该协定。 |
• | 构建可互换的服务。 可以在协定的任何一端改变参与方,只要双方都遵守协定,这种做法不会导致任何问题。 |
• | 例如,用户可能需要为一个原有的系统构建一个包装,然后再构建与该包装对话的服务。因为该服务将通过包装的服务接口进行通信,所以,如果以后有另一个服务提供同样的接口,就可以用它来替换原有的系统。 另一个例子是,大企业的运作牵涉到许多供应商。企业将定义要使用的服务接口,所有供应商都需要使用该服务接口。 不过,企业可以在不影响供应商的情况下更改它们的服务实现。 |
• | 确定哪些服务可以协同工作。 如果您有一个具有已知服务接口集的服务,则可以迅速确定可以与之通信的其他服务。 图 2 阐释了这一点。 ![]() 图 2. 共享服务对之间的状态 |
• | 构建支持设计和管理的工具。 如果您构建的是 CASE 工具,则可以假设,如果每个服务的接口和角色都设计得当,它们在构建后将正确通信,这就好比将协定看成不同类型的电缆,您可以确定哪些设备能连接起来。 |
运行时协定
到目前为止,本文已经讨论了协定的设计时方面。 消息流、消息格式和传输的可靠行为都是设计的一部分。协定的许多其他方面只有部署服务的组织才知道,并且常常是组织之间协商的结果,甚至是那些组织内的不同小组之间协商后的综合结果。定义每天应该处理多少请求、使用哪些传输协议以及必须支持哪些编码类型的服务级别协议经常受到诸如身份验证机制、加密、签名这样的安全性限制的影响。可是,所有这些仍然是运行时协定的一部分,可以将它们视为协定中的不同段落。 协定定义了两个服务之间的通信的所有方面。
服务接口
正如前面所讨论的那样,服务接口实现了协定。 设计时协定有很大一部分是开发阶段在代码中实现的。消息序列几乎始终受到业务逻辑的支配,并且渗透在业务逻辑的设计中。 不过,协定的很大一部分可以由基础结构来提供。基础结构可以将逻辑地址映射到物理地址,并且可以提供身份验证机制、负载平衡和故障转移。 当然,基础结构还可以帮助实行由业务逻辑施加的限制。
服务接口通常提供协定的发现机制;Web 服务描述语言 (WSDL) 标准详细说明了许多发现机制,以后还将增加更多内容。因此,服务接口不仅启用和执行协定,还提供有关协定的信息,从而使其他服务能遵守该协定。
基础结构同时需要运行时信息和设计时信息来实现服务接口。
一个服务可以有多个接口;协定定义了那些接口中的一个和另一个服务的一个接口之间的交互。更准确地说,设计时协定定义了两个接口之间的交互;利用设计时协定,设计人员和程序员可以构建正确的服务。运行时协定将约束添加到一对端口或地址;运行时协定允许信息技术 (IT) 部门表达和传达所需要的运行时约束。本文的其余部分将对设计时和运行时不加区别地使用服务接口和协定这两个术语,除非要特意进行区别。
会话
当两个服务在发送和接收消息时,它们相当于加入了一个会话。 会话是协定的实例,并且必须遵循协定中定义的协议。服务可以在没有任何额外验证的情况下参与会话;不过,如果基础结构按照协定对会话进行验证,异常处理就会变得更加一致,服务的开发也更容易。
这种验证可能发生在许多地方: 可以对协定的任意一端或两端进行验证,或者,可以创建由所有参与方共享的协定的主要实例。如果违反了协定,必须确保针对相关的参与方产生定义明确的异常。
基础结构除了有助于按照协定验证会话,还可以提供有关会话状态的信息。这对于各参与方保持同步很有用,但如果其中的一个参与方是一般性用户接口应用程序,就更有帮助了。应用程序可以向基础结构询问会话中下一个可能的步骤是什么,并向用户显示适当的按钮。再举另外一个例子,电子表格应用程序可以使用费用报表服务接口,它需要知道服务在会话中的特定点公开了哪些可能的操作。可能发生这种事情的另一种情况是,参与方之一不是处理,而是一个不能存储状态的、更一般性的组件。 例如,可以使用台式机启动一个订购过程,然后需要在个人数字助理 (PDA) 上继续发出定单。 必须存在某种在处理的正确阶段将 PDA 连接到会话的方式。
可监视服务之间的会话,并获得有关会话状态的信息。这与查询定单状态有所不同,查询定单状态时,要通过服务的业务逻辑从服务请求信息;此处提到的情况则是从基础结构软件请求诸如协定中接下来可能发生的步骤这样的信息;这种信息与业务逻辑密切相关。
协定小结
服务接口定义了发送到服务的消息的特征。 它们以匹配对的形式存在,也就是说,在会话的任何一端,都存在一个服务接口。
协定用于定义围绕两个服务之间发送的消息的所有信息。其中包括诸如应该按什么顺序发送和接收消息、出错时应该产生什么异常、消息采用什么格式以及如何确保消息的安全这样的判定。
在设计阶段定义明确的协定将产生更易于使用和更易于管理的服务。
注意
• | 在 SOAP 及所有相关标准中,使用端口和端口类型这两个术语。 端口是一个被命名的位置,它是服务接收的消息的端点,或称为统一资源定位器 (URL)。端口类型就是本文所讨论的所谓的服务接口。 编程语言通常引用接口,而通信协议(例如,简单对象访问协议 (SOAP))则引用端口类型。 |