SOA四个原则


SOA面向服务的开发基于以下四个基本原则:

1、边界明确
面向服务的应用程序通常由分布在遥远的地理位置、多个信任机构和不同执行环境中的服务组成。在复杂性和性能方面,穿越这些不同边界的成本并不低。

面向服务的设计承认这些成本,因此对边界穿越给予了高度重视。由于每次跨边界通信的成本都很高,因此面向服务基于显式消息传递模型,而不是隐式方法调用模型。

与分布式对象相比,面向服务模型将跨服务方法调用视为一种私有实现技术,而不是一种原始构造--特定交互可以作为方法调用来实现这一事实是一种私有实现细节,在服务边界之外是不可见的。

虽然面向服务并不强加 RPC 风格的全网调用堆栈概念,但它可以支持强有力的因果关系概念。消息通常会明确指出特定消息属于哪个(些)消息链。这种指示对于消息相关性和实现几种常见的并发模型非常有用。

边界明确的概念不仅适用于服务间通信,也适用于开发人员之间的通信。

即使在所有服务都部署在同一地点的情况下,每个服务的开发人员跨越地理、文化和/或组织界限也是很常见的。这些界限都会增加开发人员之间的沟通成本。

服务导向通过减少必须跨服务边界共享的抽象概念的数量和复杂性来适应这种模式。通过尽可能缩小服务的表面积,减少了开发组织之间的互动和交流。

在面向服务的设计中,有一个主题是始终如一的,那就是简单性和通用性不是奢侈品,而是关键的生存技能。

2、服务是自主的
面向服务的技术反映了现实世界,因为它并不假定存在一个无所不知或无所不能的神谕,对运行系统的所有部分都具有感知和控制能力。

服务自主性的概念体现在开发的多个方面,其中最明显的就是部署和版本管理

面向对象程序往往是作为一个单元部署的。尽管在 20 世纪 90 年代为实现类的独立部署付出了巨大的努力,但事实证明,对于大多数开发组织而言,实现面向对象与组件交互所需的规范是不切实际的。再加上面向对象接口版本化的复杂性,许多组织在推出面向对象代码时变得极为保守。.NET框架的XCOPY部署和私有程序集功能的流行就表明了这一趋势。

面向服务的开发不同于面向对象的开发,它假定应用程序的原子部署是例外,而不是规则。虽然单个服务几乎总是以原子方式部署,但整个系统/应用程序的总体部署状态很少是静止的。单个服务的部署通常早于任何消费应用程序的开发,更不用说部署到野外了。亚马逊公司(Amazon.com)就是这种 "先建后用 "理念的一个例子。亚马逊的开发人员不可能知道,他们的服务会以多种方式被用于构建有趣而新颖的应用程序。

随着时间的推移,面向服务应用程序的拓扑结构会不断演变,有时甚至不需要管理员或开发人员的直接干预。在面向服务的系统中引入新服务的程度取决于服务交互的复杂性和以共同方式交互的服务的普遍性。面向服务鼓励通过降低服务交互的复杂性来提高通用性。随着特定于服务的假设渗入服务的公共界面,能合理模仿该界面并作为合理替代品的服务就会越来越少。

自主服务的概念也会影响处理故障的方式。对象被部署为在与消费应用程序相同的执行上下文中运行。面向服务的设计认为这种情况是例外,而不是常规。因此,服务认为消费应用程序可能会在没有任何通知的情况下发生故障,而且经常是在没有任何通知的情况下发生故障。

为了保持系统的完整性,面向服务的设计使用了多种技术来处理部分故障模式。事务、持久队列、冗余部署和故障转移等技术在面向服务的系统中非常常见。

3、服务共享的是结构和契约,不是类
类:面向对象编程鼓励开发人员以类的形式创建新的抽象。

类是一种方便的抽象概念,因为它们在一个命名单元中共享结构和行为。面向服务的开发没有这样的结构。相反,服务的交互完全基于模式(结构)和契约(行为)

每个服务都会公布一个合约:

  • 该合约描述了它可以发送和/或接收的信息结构,
  • 以及对这些信息的一定程度的排序约束。

结构与行为之间的这种严格分离大大简化了部署,因为分布式对象概念(如逐值调用)需要一个共同的执行和安全环境,这与自主计算的目标直接冲突。

服务本身不涉及类型或类,而只涉及服务支持的机器可读和可验证描述。

  • 考虑到面向服务的应用程序的开发和部署方式本身具有分布式性质,因此强调机器可验证性和验证非常重要。
  • 与传统的类库不同,服务必须非常谨慎地验证每条信息中的输入数据
  • 基于机器验证兼容模式和合约的架构为开发人员和基础架构提供了保护单个服务和整个应用程序完整性所需的提示。

由于特定服务的结构与合约在广阔的空间和时间范围内都是可见的,因此服务导向要求结构与合约式在一段时间内保持稳定。

  • 在一般情况下,不可能将结构与合约的变更传播给遇到过服务的所有各方。
  • 因此,与传统的面向对象接口相比,面向服务设计中使用的结构与合约往往具有更大的灵活性。
  • 服务通常会使用 XML 元素通配符(如 xsd:any)和可选的 SOAP 标头块等功能,以不破坏已部署代码的方式发展服务。

4、服务兼容性是根据策略确定的
面向对象的设计常常混淆结构兼容性和语义兼容性。面向服务分别处理这两个方面。结构兼容性以结构与合约为基础,可以通过机器技术(如数据包嗅探、验证防火墙)来验证(如果不是强制执行的话)。语义兼容性则以策略形式明确说明能力和要求。

每项服务都以机器可读策略表达式的形式公布其能力和要求。

  • 策略表达式指出了哪些条件和保证(称为断言)必须成立才能使服务正常运行。
  • 策略断言由一个稳定且全局唯一的名称标识,无论该断言应用于哪项服务,其含义在时间和空间上都是一致的。
  • 策略断言还可能带有参数,用于限定断言的确切解释。
  • 单个策略断言对整个系统来说是不透明的,这就使得实现者可以应用简单的命题逻辑来确定服务兼容性。

banq注:
本文发表于2004年,后来2008年DDD概念更加细化:

  • 服务=后来发展为微服务,DDD中限定上下文BC,服务代表不同上下文,分布式环境、客户端与服务端(后来被RESTful分担)
  • 面向对象=DDD中聚合根对象