可伸缩架构(第2版):云环境下的高可用与风险管理
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

深入了解服务

那么如何来决定服务的边界呢?公司组织、文化以及应用程序的类型都会在很大程度上影响服务边界的确定。

以下是一组你可以用来确定服务边界的指导原则。不过,这些只是原则,并不是规则,也很可能随着工业进程的发展而发生改变,但是它们可以帮助我们思考什么是服务以及如何划分服务。

以下是较高层面上的指导原则(按照先后顺序)。

特定的业务需求

是否有特定的业务需求(例如,会计、安全或者监管)会影响服务的边界?

清晰和独立的团队所有权

负责该功能的团队是否清晰和独立(例如,在另一个城市,或者在另一个楼层,或者甚至只是一个不同的经理),是否会帮助确定服务边界?

天然隔离的数据

服务所管理的数据是否天然地与系统其他数据相独立?将数据放到一个单独的数据存储器中是否会对系统造成过大压力?

共享的能力/数据

服务是否提供了一些被其他服务使用的共享能力,这些共享能力是否需要共享数据?

我们现在分别来解释以上每一项原则。

指导原则1:特定的业务需求

在某些情况下,某些特定的业务需求会决定一个服务的边界。这些需求可能是监管、法律、安全需要或者一些关键业务的需求。

假设你的系统接受来自用户的在线信用卡支付。但是你应该如何收集、处理并且存储这些信用卡,以及它们所代表的支付呢?一个好的商业策略是将处理信用卡的过程交给另外一个服务,与系统中的其他服务区分开。

将关键业务逻辑放在独立的服务中,可以实现有效的分隔。例如,对于信用卡业务来说,有以下几点原因:

法律/监管需求

法律和监管需求会要求你在保存信用卡的方式上,选择与其他业务逻辑或其他业务数据不同的方式。将信用卡处理业务拆分成独立的服务,使我们能更容易地处理这些数据。

安全

出于安全的考虑,你可能需要额外的防火墙来保护这些服务器。

校验

你可能需要对这些能力进行更加严格的产品测试,以保证它们的安全性。

限制性访问

你通常会希望限制对这些服务器的访问,这样只有必要人员才能访问高度敏感的支付信息,例如,信用卡。你通常不希望或者不需要将这些访问权限提供给所有的工程人员。

理解关键业务逻辑的需求,是决定服务边界应该位于何处的一个重要考虑因素。

指导原则2:清晰和独立的团队所有权

应用程序正在变得越来越复杂,需要越来越多的开发人员进行开发,通常也提供更专业的功能。随着开发人员、团队和开发地点的增加,团队之间的协作变得越来越难。

服务能够将更小的、清晰的、独立的模块所有权赋予不同的团队。

一个单独的服务应该由一个3~8人组成的开发团队来负责和运行。这个团队应该负责该服务的所有方面。

这样就减少了团队之间的依赖,使得独立的团队更容易运行系统和实现创新。

如之前所述,单个服务应该只由单个团队负责和运行。关键是要确定这个团队可以负责该服务的所有方面。这意味着这个团队要负责服务所有的开发、测试、部署、性能以及可用性等各个方面。

根据服务的复杂性和功能不同,一个团队也可以管理多个服务。除此之外,如果多个服务本质上是类似的,那么让一个团队来管理所有这些服务可能会更容易一些。

出于安全原因隔离团队

有些时候,你希望限制能够访问某个服务代码和数据的人员数量和范围。这对于需要审计或者存在法律约束的服务来说尤其重要,例如,之前所讨论的信用卡支付处理。限制对含有敏感数据服务的访问,可以降低数据暴露所导致的问题。像这种情况,你可以从物理上限制只有关键人员才能访问服务的相关代码、数据和系统。

除此之外,将敏感数据分成两个或多个服务,每个服务由不同的团队管理,也可以有效降低多个服务同时泄露数据的风险。

出于安全原因隔离数据

当你在处理信用卡支付时,信用卡号码本身可以被存储在一个服务中。而使用信用卡所必需的信息(例如,账单地址和CCV代码)可以存储在第二个服务中。通过将该信息分开保存在两个服务中,每个部分都由单独的团队负责,你可以避免任何员工无意或有意地将信用卡信息泄露出去,造成不当影响。

你甚至可以选择不由自己来保存信用卡号码,而是将它们存储在一个第三方信用卡服务公司的服务中。这可以保证即使你的其中一个服务被入侵,信用卡本身的数据也不会被泄露。

指导原则3:天然隔离的数据

服务的一个要求是,其托管状态和数据需要与其他数据相隔离。出于多种原因,让多个独立的代码库对同一组数据进行操作是有问题的。只有在你隔离数据之后,隔离代码和所有权才能起作用。

图3-6展示了一个服务(服务A)试图访问存储在另一个服务(服务B)中的数据。它说明了服务A访问服务B中数据的正确方式,即服务A通过API调用来访问服务B,然后让服务B访问自己数据库中的数据。

图3-6:共享数据的正确方式

如图3-7所示,如果服务A试图直接访问服务B中的数据,而不是通过服务B的API,那么所有问题都会出现。这种数据集成会导致服务A和服务B过度耦合,并且维护数据和迁移模式时会出现问题。一般来说,如果服务A越过服务B的业务逻辑,直接访问服务B的数据,会导致严重的数据版本不一致和数据损坏问题。这种情况应该被严格禁止。

图3-7:共享数据的错误方式

如你所见,确定数据划分界线是确定服务划分界线的关键环节。对于一个服务来说,它是否能够负责自己的数据,并通过外部服务接口来提供数据访问呢?如果答案是“是”,说明这是一个很好的服务边界。如果答案是“否”,说明这不是一个很好的服务边界。

一个服务如果需要操作另一个服务的数据,必须通过数据所在服务的公开接口来访问。

指导原则4:共享的能力/数据

有些时候我们可以很容易地创建一个服务,因为它负责提供一系列的能力和数据。这些能力和数据可能需要在很多其他服务之间共享。

说明该原则最好的一个示例就是用户身份服务,它只是简单地提供系统中指定用户的信息,如图3-8所示。

图3-8:通过服务与其他服务共享通用数据

这个数据服务的业务逻辑也许不复杂,但是它最终负责所有用户的常用信息。这些信息通常被大量其他的服务所使用。

通过一个中心化的服务来提供和管理这类信息,在实际中非常实用。

多种原因

之前的指导原则大概描述了决定服务边界的基本标准。但是,通常你需要综合考虑多种原因才能最终做出决定。

例如,从数据所有权和共享能力的角度来看,只有一个用户身份服务是合理的,但是从团队所有权角度来看,可能就不一定了。保存用户身份的数据存储在某个数据库中可能是合理的,但是可能存储在一个或多个单独的服务中会更好。

举例说明,一个用户的个人资料中通常会有搜索选项,但是很少被搜索以外的功能使用。因此,这个数据可能更适合存储在一个搜索身份服务中,而不是用户身份服务中。这也可能是出于数据复杂性甚至是性能原因的考虑。

最终,你必须同时运用你的判断力和之前的标准。当然,你还必须考虑公司的业务逻辑和需要,以及特定的业务需求。