我的书单

概述

SaaS架构具有多种形态和规模,存在无数种多租户架构模式和策略的组合,这些组合被用于构建与SaaS公司的业务领域、合规要求和商业现实最匹配的SaaS架构。然而,所有SaaS架构中都存在一些核心主题。本章的目的是探讨一套架构构造和概念,作为构建多租户SaaS架构的最基本起点。其核心思想是详细阐述这些 核心构建块 的细节,为后续深入探讨这些概念如何通过具体技术实现奠定基础。

我们将从租户概念入手,探讨租户上下文如何被引入架构。目标是突出租户在整个架构中的作用,明确其在多租户架构各层级中的具体触点。在此基础上,我们将进一步探讨如何对多租户架构的各组成部分进行分组与组织。重点将放在识别任何 SaaS架构中的通用组件,概述支持核心功能所需的根本性服务,以及用于接入、认证、运营和管理租户及整体环境的横向服务。虽然每个应用程序都有其独特之处,但仍存在一套通用的策略,用于实现SaaS实现中的多租户安全、存储、部署和路由模型。我们将涵盖的主题将帮助您更好地理解多租户如何影响您设计和构建应用程序各组成部分的方式。

最后,我们将探讨一些SaaS模型的其他内容,包括创建分层用户体验、租户资源的验证和配置,以及构建系统管理员视图以监控环境。掌握这些核心SaaS架构概念是理解多租户架构中典型组成部分的关键。目标是帮助您更好地理解在定义SaaS架构蓝图时需要关注的核心构建块。您可能已经对如何扩展、保障安全、设计和运营一个健壮的架构有一定的理解。在SaaS中,我们的目标是弄清楚多租户如何影响并覆盖这些关键概念,从而改变我们构建多租户环境的方式。

在架构中添加多租户

让我们通过分析一个传统的非SaaS应用程序,开始探索SaaS架构概念。在经典应用程序中,环境是从头开始构建的,假设它将由单个客户安装和运行。每个客户本质上都有自己的专用资源占用。图2-1展示了此类应用程序可能的设计和构建概念。

图2-1 传统非SaaS环境

左侧是一个应用程序的简化视图。在此,该应用程序被构建后出售给各个客户。这些客户可能将软件安装在自己的环境中,或在云端运行。这种方法简化了整个环境的架构模型。当我们知道应用程序将在专属于每个客户的环境中运行时,客户如何进入环境、如何访问我们的资源以及如何使用环境服务等选择都变得更加简单。这里的基本思路是,你拥有一段软件,然后为每个新客户复制一份。现在,让我们思考一下在多租户SaaS环境中交付同一应用程序意味着什么。图2-2展示了这种场景的概念性视图。您可以看到,我们的客户(现在是租户)都在使用同一应用程序。

图2-2 向租户中心化体验的转变

虽然在图中这一转变看似简单,但它对我们设计、构建、保护和管理该环境的方式产生了深远影响。我们本质上已经从基于单客户的专用模型过渡到了多租户架构。支持这种模型会影响系统底层实现的各个维度。它影响您如何实现身份验证、路由、扩展、性能、存储,以及在特定领域如何编写系统应用逻辑。您还会注意到本图中术语使用的关键变化。在该图顶部,我不再将系统消费者称为“客户”。取而代之的是,它们在整本书中都将被称为“租户”。为何做出这一变更?为了更好地理解这一核心概念,让我们通过运行时视角深入查看其中一个应用服务,看看租户在运行时如何在我们的环境中呈现。如果我分别在三个不同时间点对产品微服务进行快照,可能会看到类似图2-3所示的场景。

图2-3 租户的运行时快照

在快照1中,我们的产品微服务有两个租户正在使用该服务(T1和T3)。下一个快照中则有三个完全不同的租户。关键点在于,资源不再属于任何单一消费者;它已成为系统中任何租户均可使用的共享基础设施。而且,在许多情况下,多个租户可以同时使用该资源。这种转向使用共享基础设施的转变,要求我们采用新的方式来描述系统被消费的方式。以前,每个消费者都有自己的专用基础设施,因此继续使用“客户”这一术语是容易的。然而,在多租户环境中,我们会将环境中的消费者描述为“租户”。

租户概念与公寓楼的运作模式高度契合:您拥有建筑物并将其出租给不同租户。在此框架下,建筑物对应解决方案的共享基础设施,而租户则代表公寓内的不同住户。这些租户会消耗建筑物的共享资源(如电力、水等)。作为大楼的所有者,您负责管理和运营整个大楼,不同的租户会来来去去。入住率会随时变化。你可以看到这个术语如何更好地适用于SaaS模型,因为我们正在构建一个运行在共享基础设施上的服务,该服务可以容纳任意数量的租户。是的,租户仍然是客户,但“租户”这个术语让我们更好地描述他们在SaaS环境中的角色。随着我们继续深入,我们将更好地理解租户关系如何影响SaaS架构的实现。目前,只需记住我们环境中的每个消费者都将被称为租户。我们将在这-个租户信息贯穿我们SaaS架构讨论的多个层次。它代表了任何SaaS架构中最基本的核心元素之一。

SaaS架构的两个核心部分

如果我们从SaaS的细节中抽身出来,通常会发现,每个SaaS环境——无论其领域或设计如何——都可以分解为两个非常不同的部分。事实上,在我们本书中对SaaS的整个讨论中,我们将使用这两个部分作为透镜,来观察多租户系统是如何构建、部署和运行的。图2-4展示了SaaS的两个组成部分的概念示意图。在图的右侧,您可以看到标注为“控制平面”的部分。控制平面是放置所有跨切面构造、服务和能力的地方,这些构造、服务和能力支持多租户SaaS环境的基础需求。

图2-4 SaaS应用程序与控制平面

我们常将控制平面描述为用于协调和管理SaaS解决方案所有组件的“单一控制面板”。它处于使SaaS业务成功所需核心原则的中心位置。租户接入、计费、指标等概念以及众多其他服务均位于此控制平面中。您还会发现,我们的控制平面包含一个管理应用程序。这是SaaS提供商用于配置、管理和运营其SaaS环境的控制台或管理界面。该控制平面与我们在第1章中提到的概念相对应,即围绕应用程序的一系列组件。这里有一个有趣的注意事项:控制平面中运行的服务并非作为多租户服务进行构建或设计。

从本质上讲,控制平面的能力本身并不具备多租户特性。它不包含支持单个租户需求的特定功能,而是提供所有租户共享的服务和功能。虽然建筑师和开发人员常常倾向于从应用程序的多租户特性入手讨论SaaS,但SaaS架构的基础往往始于控制平面。在许多方面,控制平面起到强制作用,要求工程师从开发初期就融入并支持多租户的细微差别。相比之下,应用层是SaaS服务功能与特性得以实现的场所。这里是多租户原则在SaaS环境中经典体现的领域。我们在此阶段更关注多租户架构如何影响服务设计、功能实现、安全策略及底层资源的性能表现。

我们在应用层投入的时间和精力主要集中于识别并选择与您的环境参数、时间表及业务需求最匹配的技术、应用服务和架构模式。这是您投入精力构建一个支持敏捷性、能够支持多种用户角色和消费模式的应用程序架构的阶段。需要特别指出的是,应用层并不存在通用的设计、架构或蓝图。我倾向于将应用层视为一张空白画布,其内容将根据SaaS服务所需的独特服务组合与能力进行定制化绘制。虽然我们在SaaS应用架构中会看到一些共通的主题和模式,但业务、领域和遗留系统考量始终会对SaaS应用的架构布局提出特定要求。这种将SaaS分为两部分的视角与我们在第一章讨论的多租户模型相一致。

我们的应用层可以共享所有租户的基础设施,也可以拥有完全独立的基础设施,这并不重要。只要我们有一个控制平面,能够通过统一的体验管理和运营这些租户环境,那么我们就认为这是一个多租户环境。这种关注点的分离也影响了我们对SaaS环境中各元素如何更新和演进的思维模型。控制平面的服务和能力通常有自己的版本控制、更新和部署流程。它们可以在系统整个生命周期中使用,支持运营和功能需求的混合。与此同时,应用平面更多地由系统租户的需求和体验驱动。在此,更新和部署被引入以提供新功能、提升租户性能、支持新的分层策略等。这两部分共同构成了SaaS环境中最基本的构建模块。理解这些平面(plane)的作用将对您在架构、设计和分解SaaS产品时采取的策略产生重大影响。

控制平面内部

现在我们对控制平面和应用平面的角色有了更清晰的认识,让我们从高层次上探索一下通常在控制平面范围内存在的核心概念。我们将在本书后面的章节中对这些主题进行更深入的探讨,包括实际实现和架构策略。然而,在当前阶段,我们需要先提升视角,建立对控制平面中不同组件的整体理解。对这些组件、它们的角色以及它们之间的关系有更高的层次理解,将使我们能够探索多租户架构的构建块,而不会被技术、语言和领域因素带来的不同细节所分散。拥有这种基础视图将使您能够看到整体格局,并开始看到跨越所有SaaS架构模型的不同组件。以下是对SaaS架构控制平面中可能出现的不同服务和能力的分解,包括入驻、身份、指标、计费和租户管理。

用户入驻

控制平面负责管理和协调将新租户引入您的SaaS环境所需的所有步骤。从表面上看,这可能是一个简单的概念。然而,正如您将在第4章中看到的,入驻体验涉及许多复杂的组件。您在此处做出的选择,在许多方面都构成了使您的SaaS环境中的多租户业务和设计元素得以实现的核心。目前,让我们先保持高层次视角,关注入驻体验的关键要素。在图2-5中,您将看到一个概念化的组件示意图,展示了在入驻体验中发挥作用的各个组件。我展示了一个租户通过控制平面注册我们的SaaS服务并触发入驻流程的场景。在初始请求之后,控制平面将负责整个入驻流程,创建并配置租户及其对应的身份足迹。这包括为租户分配一个唯一标识符,该标识符将在我们多租户架构的大多数组件中被广泛使用。

图2-5 租户入驻

您还会注意到控制平面与应用程序平面进行交互,为每个租户预配置和配置所需的应用程序特定资源。在深入探讨入驻原则的详细视图时,我们将看到入驻体验的这一部分可能变得相当复杂。虽然入驻体验存在一些共同主题,但实际的入驻实施会因所处领域、解决方案的业务目标以及应用程序架构的规模而存在显著差异。然而,关键在于入驻代表了一个基础概念,它位于SaaS体验的入口处。业务团队应积极参与并影响系统构建过程中这一环节的规划与实施。更高的层次是,入驻流程处于创建和连接多租户环境中最基本元素的核心位置:租户、用户、身份以及租户应用程序资源。入驻流程将这些概念有机结合,并为在SaaS环境的所有组件中引入租户概念奠定基础。

身份

乍一看,你可能会好奇为什么身份识别要纳入SaaS架构中。确实,你可以使用多种不同的身份识别解决方案来构建你的SaaS解决方案。你甚至可以认为,你的身份提供商在某种程度上超出了我们对控制平面讨论的范围。然而,事实证明,多租户架构与控制平面往往与你的SaaS架构有着密切的关联。图2-6展示了身份在多租户环境中应用的简化视图。

图2-6 将用户绑定到租户身份

在左侧,您可以看到与身份验证和授权通常相关的经典用户身份概念。确实,我们的SaaS用户会对SaaS系统进行身份验证。然而,在多租户环境中,仅能验证用户身份是不够的。SaaS系统必须知道您作为用户的身份,并且必须能够将该用户绑定到一个租户。事实上,登录到我们系统中的每个用户都必须以某种方式与一个租户相关联。我经常将这种用户/租户绑定称为您的SaaS身份。

将用户映射到租户的概念在以下环境中更为自然:即个人作为实体的一部分绑定到服务时。在B2B场景中,商家是租户,而用户则是商家中存在的多个用户之一。在B2C模型中,用户本身就是是租户,此时无需单独映射到租户。

这种用户/租户绑定最终会为系统整体身份体验增添复杂性,要求架构师和开发者制定策略,以在符合整体身份验证模型要求的前提下,将这两个概念进行绑定。当我们开始考虑如何在多租户环境中支持 联合身份模型 时,情况会变得更加复杂。我们将看到,身份体验越是超出我们的控制范围,支持用户与租户之间的绑定就越复杂和具有挑战性。在某些情况下,您可能需要引入构造来将这两个概念缝合在一起。在第四章深入探讨用户注册和身份管理时,您将更清晰地理解身份在多租户架构中的核心作用。正确处理身份管理是构建高效、清晰的租户引入策略的关键,在此处应用的策略和模式将对设计与实现的多个环节产生连锁影响。

指标

当应用程序在多租户模型中运行时,难以清晰地了解租户如何使用系统。例如,如果共享基础设施,很难确定哪些租户正在使用该基础设施,以及单个租户的活动如何影响解决方案的规模、性能和可用性。使用系统的租户数量也可能不断变化。新租户可能被添加,现有租户可能离开。这使得运营和支持多租户环境特别具有挑战性。这些因素使得SaaS公司特别需要在控制平面中构建丰富的指标和分析功能。

目标是创建一个集中化的枢纽,用于捕获和聚合租户活动,使团队能够监控和分析单个租户的使用和消耗模式。指标的作用非常广泛。收集的数据将在运营环境中使用,使团队能够衡量和排查系统健康状况。产品所有者可能利用这些数据评估特定功能的资源消耗。客户成功团队可能利用这些数据衡量新客户的价值实现时间。

核心理念是,成功的SaaS团队将利用这些数据驱动其SaaS产品在业务、运营和技术层面的成功。你可以想象指标将如何影响多租户系统中众多组件的架构和实现。微服务开发人员需要考虑如何以及在何处添加指标监控。基础设施团队需要决定如何以及在何处展示基础设施活动。业务部门需要参与并帮助捕获能够衡量客户体验的指标。这些只是指标可能影响实施的众多领域中的几个例子。租户必须处于指标策略的核心,如果无法通过租户视角对数据进行过滤、分析和查看,消费和活动数据的价值将大大降低。

计费

大多数SaaS系统都依赖于计费系统。这可能是自建的计费系统,也可能是来自不同计费提供商的商业SaaS计费系统。无论采用何种方式,计费都是一个核心概念,自然属于控制平面的一部分。计费在控制平面中有几个关键触点。它通常与用户入驻流程相关,每个新租户都需要在计费系统中被创建为“客户”。这可能包括配置租户的计费计划以及设置租户计费配置文件的其他属性。

许多SaaS解决方案在生成账单时会通过计量和测量租户活动来实现计费。这可能包括带宽消耗、请求数量、存储消耗或其他与特定租户相关的活动事件。在这些模型中,控制平面和计费系统必须提供一种方式,将这些活动数据摄取、处理并提交至计费系统。这可能是与计费系统的直接集成,或通过引入自有服务来处理数据并将其发送至计费系统。我们在第14章中将详细探讨计费集成。这里的关键在于认识到计费很可能成为您控制平面服务的一部分,并且您很可能需要引入专门的服务来协调这一集成。

租户管理

我们SaaS系统中的每个租户都需要集中管理和配置。在控制平面中,这由租户管理服务实现。通常,这是一个较为基础的服务,提供创建和管理租户状态所需的所有操作(在B2C环境中,这些对应于用户)。这包括跟踪与租户关联的唯一标识符、计费计划、安全策略、身份配置以及活跃/非活跃状态等关键属性。

在某些情况下,团队可能会忽略此服务或将其与其他概念(如身份管理)合并。对于多租户环境,拥有一个集中管理所有租户状态的服务至关重要。这为租户配置提供了一个统一入口,使租户能够通过集中化体验轻松管理。我们在第5章中将进一步探讨实现租户管理的要素和变体。

应用程序平面

现在我们对控制平面中的核心概念有了更好的理解,让我们开始看看多租户在应用程序平面中常见的出现位置。虽然控制平面通常有一组一致的通用服务,但应用程序平面则更加抽象。多租户在应用程序平面中的应用方式和位置会因多种因素而显著不同。尽管如此,仍会出现一些主题,尽管形式不同,但会在您的应用程序平面中浮现。

因此,尽管这里存在差异,但每个SaaS架构师都需要考虑如何以及在何处将这些主题引入其解决方案的应用层。当您深入研究应用层时,会发现技术栈和部署范围将对这些概念的实现方式产生重大影响。在某些情况下,可能存在与您的用例完美匹配的现成解决方案。在其他情况下,您可能需要自行设计解决方案来填补技术栈中的空白。虽然构建这些解决方案可能会增加解决方案的复杂性和开销,但在大多数情况下,您仍应承担这一额外工作,以确保您的SaaS解决方案不会在多租户架构的关键要素上做出妥协。在接下来的章节中,我们将通过实际应用示例,更具体地探讨这些构造在应用层中的实现方式。不过,目前我们先退一步,确立一套适用于所有SaaS架构的核心应用层原则。

租户上下文

在应用程序平面中,租户上下文是核心概念之一。租户上下文并不对应任何特定的策略或机制,而是一个更广泛的概念,旨在传达应用程序平面始终在特定租户上下文中运行的理念。这种上下文通常以令牌或其他构造的形式表示,用于封装租户的所有属性。

一个常见的示例是JSON Web Token(JWT),它将用户和租户信息整合到一个构造中,并在多租户架构的各个组件间共享。此JWT成为我们在租户上下文(即上下文信息)与依赖该上下文的任何服务或代码间传递信息的通行证。该令牌即被称为租户上下文。

现在,您会发现租户上下文直接影响应用程序架构处理租户请求的方式。这可能影响路由、日志记录、指标、数据访问以及应用程序层中存在的其他构造。图2-7展示了租户上下文在实际应用中的概念视图。图2-7中的流程展示了租户上下文在多租户环境中不同服务和资源中的应用。该流程从图的左侧开始,租户通过在注册过程中创建的身份进行身份验证,并获取其租户上下文。此上下文随后被注入到应用程序的某个服务中。该上下文会流向系统中的每个下游交互,使您能够在各种不同用例中获取并应用该上下文。

图2-7 应用租户上下文

这正是SaaS环境与传统应用环境最根本的差异之一。我们的服务不仅与用户交互,还必须在SaaS应用程序所有组件的实现中内置租户上下文。您编写的每个微服务都会使用此租户上下文。您需要解决如何在不增加系统实现复杂性的情况下有效应用此上下文的问题。事实上,这是我们在第7章深入探讨SaaS微服务时将重点讨论的关键主题。

作为一名SaaS架构师,这意味着你必须始终考虑 租户上下文如何在系统中传递。你还需要考虑用于打包和应用租户上下文的具体技术策略,以限制复杂性并促进敏捷性。这是SaaS架构师和开发人员需要不断平衡的任务。

租户隔离

多租户架构的本质在于将客户及其资源置于可共享资源或至少在共同基础设施环境中共存的场景中。这一现实意味着多租户解决方案通常需要采取创新措施,以确保租户资源免受跨租户访问的潜在威胁。为了更好地理解这一概念的基础,让我们看看一个在应用程序平面上运行的解决方案的简单概念视图(如图2-8所示)。

图2-8 实现租户隔离

您会看到我们有一个最简单的应用程序平面,运行着单个微服务。在此示例中,我们的微服务管理两组不同的数据。右侧示例中,租户数据存储在两个独立的数据库中。左侧示例中,同一微服务中的数据混杂在同一张表中。同时,我们的微服务与所有租户共享计算资源。这意味着我们的微服务可以同时处理来自租户1和租户2的请求。虽然我们的租户数据存储在独立的存储结构中,但我们的解决方案中没有任何机制能确保租户1无法访问租户2的数据。即使使用独立的数据库,这一情况依然成立。

将数据存储在独立数据库中并不能保证租户无法跨越这一边界,以专用模型部署资源并不等同于实现租户隔离。不过,这样做确实能简化实现过程。为了防止访问其他租户的资源,我们的应用程序层必须引入一种机制来阻止 跨租户访问。实现此机制的具体方式将根据多种不同考虑因素而大不相同。然而,租户隔离的基本概念适用于所有可能的解决方案。核心思想是,每个应用程序层都必须引入针对性的构造,严格执行对单个租户资源的隔离——即使这些资源可能运行在共享构造中。我们将在第9章中对这一概念进行详细探讨。毋庸置疑,租户隔离是SaaS架构中最基础的构建块之一。在构建应用程序平面时,您需要找到适合自己需求的实现方式,以在SaaS架构的各个层次上强制执行隔离。

数据分区

我们的应用程序层中的服务和功能通常需要为租户存储数据。当然,您选择如何以及在哪里存储这些数据可能会因您的SaaS应用程序的多租户特性而有所不同。任何因素都可能影响您存储数据的方法。数据类型、合规要求、使用模式、数据规模、所用技术——这些都是多租户存储设计中的关键要素。在多租户存储领域,我们称这些不同存储模型的设计为数据分区。核心思想是根据数据的多租户特性选择一种存储策略,将租户数据进行分区。这可能意味着数据存储在专用的存储结构中,也可能意味着数据存储在共享的存储结构中。这些分区策略受多种变量影响。

您使用的存储技术(对象存储、关系型数据库、NoSQL等)显然会对存储租户数据的表示和存储方式产生重大影响。应用程序的业务需求和使用场景也会影响您选择的策略。这里涉及的变量和选项列表非常庞大。作为一名SaaS架构师,您的职责是分析系统中存储的各类数据,并确定哪种分区策略最能满足您的需求。您还需考虑这些策略对解决方案敏捷性的影响。数据对新功能部署、解决方案可用性以及运营复杂性的影响,在选择数据分区策略时需仔细权衡。值得注意的是,选择策略时往往需要进行精细化决策。不同应用层服务中的数据分区方式可能存在差异。这是一个更深入的话题,我们将在第8章中进行更详细的探讨。到本章结束时,您将对如何利用多种存储技术实现不同策略的落地有更清晰的理解。

租户路由

在最简单的SaaS架构模型中,您可能会发现所有租户共享资源。然而,在大多数情况下,您的架构会存在变体,其中部分或全部租户的基础设施可能是专用的。事实上,按租户部署微服务的情况并不少见。关键点在于,SaaS应用架构通常需要支持分布式部署,其中资源以共享与专用模式的任意组合运行。图2-9展示了一个支持共享与专用租户资源混合部署的SaaS架构简化示例。在此示例中,我们有三个租户将向应用程序服务发起请求以调用操作。在此特定示例中,部分资源为共享资源,部分为专用资源。在左侧,租户1拥有完全专用的服务集。同时,在右侧,您可以看到由租户2和3共同使用的服务。请注意,产品和评分服务被这两个租户共享。然而,这两个租户各自拥有订单服务的专用实例。

图2-9 租户上下文中的路由

现在,当您退一步查看这些服务的整体配置时,可以看出我们的多租户架构需要包含策略和构造,以正确将租户请求路由到适当的服务。在此示例中,这发生在两个层次。从顶部开始,您会看到应用程序层从三个独立的租户接收请求。在此处,我引入了一个路由器的概念占位符。该路由器必须接受所有租户的请求,并使用注入的租户上下文(我们在之前讨论过)来确定如何以及将每个请求路由到何处。

此外,在右侧的“租户2/3”框中,您会看到另一个路由占位符,它将根据租户上下文确定哪个订单服务实例将接收请求。让我们通过几个具体示例来理清思路。假设我们收到来自租户1的请求,需要查询一个产品。当路由器接收到此请求时,它会检查租户上下文,并将流量路由到左侧的产品服务(针对租户1)。现在,假设我们收到租户2的请求,要求更新一个产品,同时需要更新一个订单。在此场景中,顶级路由器会根据租户2的上下文,将请求发送至右侧的共享产品服务。随后,产品服务会通过服务间路由器向订单服务发送请求。该路由器会检查租户上下文,解析为租户2,并向专属于租户2的订单服务发送请求。此示例旨在强调在SaaS环境中处理多种部署场景时,需要具备多租户意识的路由构造。当然,您在此处应用的技术和策略将根据多个参数而有所不同。此外,还有丰富的路由工具和技术,每种工具可能以不同的方式实现这一目标。通常,这归结于找到一个能够提供灵活且高效的方式来获取并根据租户上下文动态路由流量的工具。我们将在本书后面的具体解决方案中看到这些路由构造的应用。目前,重要的是要理解在多租户环境中,路由通常会为我们的基础设施路由模型增添新的复杂性。

多租户应用程序部署

部署是一个相对成熟的主题。你构建的每个应用程序都需要一些DevOps技术和工具,以部署应用程序的初始版本以及后续更新。虽然这些概念同样适用于多租户环境中的应用程序层,但你还会发现,不同类型的租户应用程序模型会为应用程序部署模型带来新的考虑因素。我们已经提到,租户可能同时使用专用和共享资源。有些租户可能完全使用专用资源,有些可能完全使用共享资源,还有些可能同时使用专用和共享资源。了解这一点后,我们必须考虑这将如何影响应用程序部署的DevOps实现。假设部署一个包含两个专用微服务和三个共享微服务的应用程序。在此模型中,我们的部署自动化代码必须能够访问SaaS应用程序的多租户配置。它不仅会像经典环境中那样部署更新后的服务,还需查询租户部署配置文件,以确定哪些租户需要为每个专用微服务单独部署对应的微服务。因此,应用程序平面中的微服务可能需要多次部署。我们的基础设施自动化代码可能还需要将租户上下文应用于这些微服务的配置和安全配置文件。从技术上讲,这并非直接属于应用程序平面。然而,它与我们在应用程序平面中采用的设计和策略有着紧密的联系。通常,你会发现应用程序平面与租户环境的预配置之间会变得高度互联。

灰色地带

尽管控制平面和应用程序平面涵盖了多租户架构的大部分核心构造,但仍有一些概念无法清晰地归类到这两个平面中。同时,这些领域仍属于基础SaaS主题的讨论范围。虽然可以为将这些内容归类到特定平面提出论据,但为了避免争论,我将单独处理这些少数项目,并探讨可能推动它们归入某一平面的因素。

分层

分层是一种大多数架构师在使用各种第三方服务时都会遇到的策略。其核心思想是,SaaS服务商通过设置不同层级来提供功能各异的版本,并对应不同的定价方案。例如,某SaaS服务商可能为客户提供基础、高级和企业版等不同层级,每个层级逐步增加额外价值。基础层级用户可能在性能、用户数量、功能等方面存在限制。高级层的用户可能享有更优的 服务级别协议(SLAs)、更高的用户数量限制以及访问额外功能的权限。一些SaaS架构师和开发人员犯的错误是,他们认为这些分层主要涉及定价和包装策略。实际上,分层对多租户架构的多个维度都有显著影响。

分层通过构建更灵活的SaaS架构实现,该架构为业务提供了更多机会来创建价值边界,而这些边界在没有分层的情况下可能无法实现。分层自然融入了我们对租户上下文的讨论,因为架构中共享的上下文通常包含对特定租户层级的引用。该层级贯穿整个架构,并可能影响路由、安全以及系统底层实现的其他诸多方面。在某些分层实现中,团队会将分层作为核心概念置于控制平面。

确实,用户接入过程通常需要将租户配置映射到特定分层。分层还常与计费计划相关联,因此将其维护在控制平面范围内似乎合乎逻辑。同时,分层在应用平面中也被广泛使用。分层可用于配置路由策略,或作为流量控制策略配置的一部分被引用。真正的答案是分层在两个平面中都有其位置。然而,我倾向于将其放置在控制平面,因为分层可以通过与控制平面的交互(如身份验证)进行管理和返回。返回的分层可附加到租户上下文中,并通过该机制在应用程序平面中应用。

租户、租户管理员和系统管理员用户

在讨论SaaS架构时,“用户”这一术语容易产生歧义。在多租户环境中,我们对“用户”的定义有多种含义,每种都扮演着不同的角色。图2-10展示了在多租户解决方案中需要支持的不同类型用户的概念视图。

图2-10 多租户用户角色

在图的左侧,您可以看到典型的租户相关角色。这里有两种不同的角色类型:租户管理员和租户用户租户管理员代表从您的租户中首次注册到系统的初始用户。此用户通常被授予管理员权限,使其能够访问用于配置、管理和维护应用程序级构造的独特应用程序管理功能。这包括创建新的租户用户。租户用户代表那些使用应用程序但不具备管理权限的用户。这些用户还可能被分配不同的应用程序角色,这些角色会影响他们的应用程序使用体验。在图的右侧,您会看到我们还设有系统管理员。这些用户与SaaS提供商连接,并可访问环境的控制平面,以管理、运营和分析SaaS环境的健康状况及活动。这些管理员可能拥有不同角色,用于定义其管理权限。部分管理员可能拥有完全访问权限,而另一些则可能在访问或配置不同视图和设置方面受到限制。

您会注意到,我还在控制平面中展示了一个管理控制台。这是系统管理员角色中常被忽视的一部分。它旨在强调需要一个专用的SaaS管理控制台,用于管理、配置和运营您的租户。这通常是您的团队需要构建的组件,以支持SaaS环境的独特需求(与用于管理系统健康状况的其他工具分离)。系统管理员用户需要通过身份验证才能访问此SaaS管理控制台。SaaS架构师在构建多租户环境时需考虑这些角色。虽然租户角色通常更易理解,但许多团队在系统管理员角色上投入较少。引入并管理这些用户生命周期的流程应作为整体设计与实施的一部分。您需要建立一个可重复且安全的机制来管理这些用户。

控制平面与应用平面之间的争论在用户管理方面尤为复杂。毫无疑问,系统管理员用户应通过控制平面进行管理。事实上,本章开头展示的两个平面的初始示意图(图2-4)实际上已将管理员用户管理服务纳入其控制平面。然而,当讨论租户用户的位置时,情况就变得模糊起来。有人认为,应用程序应负责租户用户管理体验,因此这些用户的管理由应用程序平面负责。同时,我们的租户入驻流程需要在入驻过程中为这些用户创建身份,这表明该功能应保留在控制平面。可以看出,这种情况很快就会陷入循环。在此情境下,我的总体倾向(附带保留意见)是身份应属于控制平面——尤其是因为这是租户上下文与用户身份关联的位置。身份的这一方面绝不应在应用程序平面范围内进行管理。

在这种情况下,您可以做出折中方案:由控制平面管理身份和认证体验,同时允许应用程序在身份体验之外管理租户的非身份属性。另一种选择是在控制平面中部署一个租户用户管理服务,以支持应用程序可能需要的任何额外用户管理功能。您还可以遇到管理员和租户体验使用独立身份的场景,这会增加复杂性。关键要点是,您需要仔细考虑如何以及在何处将身份识别融入您的环境中。

租户配置

到目前为止,我们强调了控制平面中入驻流程的作用。我们还探讨了入驻流程可能需要在入驻体验中预配置和配置应用程序基础设施的方式。这引发了一个重要问题:租户预配置应该位于控制平面还是应用程序平面?图2-11展示了两种选项的概念视图。左侧是租户预配置在应用程序平面运行的模型。在此场景中,入驻的所有元素(租户创建、计费配置和身份设置)仍在控制平面范围内进行。预配置步骤由入驻服务触发并协调,但实际运行在应用程序平面。

图2-11 租户配置过程的放置

另一种方法如图右侧所示。在此方案中,租户预配置从控制平面内部执行。这意味着租户预配置将执行应用程序平面内应用的基础设施配置脚本。这将入驻流程的所有组件都置于控制平面内。权衡主要集中在应用程序平面封装与抽象的程度。若认为应用程序基础设施的结构和占用空间应与控制平面隔离,则应选择左侧模型。若认为入驻流程本就属于控制平面,则可认为其自然应包含应用程序配置与部署流程。

我的倾向是将配置保持在被描述和配置的资源附近。我更倾向于不因应用程序平面架构的变更而更新控制平面。权衡在于控制平面必须支持更分布式的入站体验,并依赖控制平面与应用程序平面之间的消息传递来跟踪配置状态。两种模型各有优缺点。关键在于,部署应作为入驻体验的独立部分。因此,如果未来需要迁移部署,它将相对封装,可迁移而无需重大重构。

控制平面与应用程序平面的集成

一些组织会在控制平面和应用平面之间建立非常明确的边界。这可能是网络边界或其他某种架构设计,用于分离这两个平面。这种做法对某些组织有利,因为它允许根据每个平面的独特需求对它们进行配置、管理和运维。同时,这也为设计更安全的平面间交互提供了机会。基于此,我们可以开始考虑整合控制平面与应用平面的不同方法。在此阶段选择的整合策略将受到平面间交互性质、解决方案的地理分布范围以及环境安全级别等因素的显著影响。部分团队可能倾向于采用更松散耦合的模型,该模型更侧重事件或消息驱动,而另一些团队可能需要更原生的集成方式,以实现对应用层资源的直接控制。在此领域并无绝对规则,各类技术均可带来不同可能性。关键在于审慎选择能满足特定领域、应用及环境需求的集成模型。

此处的讨论大多倾向于将应用程序平面与控制平面部署在独立基础设施中的模型。尽管分离这些平面的优势显而易见,但需注意并不存在强制要求必须沿边界划分。在某些场景下,SaaS提供商可能选择将控制平面与应用程序平面部署在共享环境中。您的环境需求、技术特性以及其他多种因素将决定您如何为这些平面设置更具体的架构边界。关键在于确保系统被划分为这些独立的平面——无论它们如何部署或部署在何处。

在深入探讨控制平面具体细节时,我们可以分析这两个平面之间的常见交互点,并探讨具体的集成用例及其潜在解决方案。不过目前只需了解,集成是控制平面与应用平面整体模型中的关键组成部分。

为各平面选择技术

SaaS团队会根据多种不同变量选择实现其SaaS解决方案的技术。技能组合、云服务提供商、领域需求、遗留系统考量——这些只是在选择多租户SaaS解决方案技术时需要考虑的众多参数中的一小部分。现在,当我们通过控制平面和应用程序平面的视角审视SaaS时,自然会思考这两个平面的需求如何影响技术选择。如果应用程序平面采用完全基于容器的模型,是否意味着控制平面也必须使用容器实现?事实上,两个平面支持不同的需求和消费模式,没有任何迹象表明它们所使用的技术必须一致

例如,考虑一下您的控制平面的成本和消耗特征,与运行在应用程序平面中的服务相比,这些服务可能以更有限的方式被使用。我们可能更倾向于选择一种不同的技术来构建控制平面,以实现更具成本效益的模型。一些团队可能会选择使用无服务器技术来实现其控制平面,决策也可以更加细粒度。我可能为某些类型的服务选择一种技术,而为其他服务选择不同的技术。关键在于,你不应假设控制平面和应用程序平面的配置、消耗和性能特征是相同的。在设计你的SaaS环境时,你需要独立考虑这两个平面的技术需求。

避免绝对化

本节关于SaaS架构概念的讨论主要通过控制平面和应用程序平面来定义SaaS架构。这些平面为我们提供了一种自然的方式来思考多租户架构的不同组件,并为我们在SaaS环境中设计多租户架构的不同特性提供了良好的思维模型。尽管这些构造很有用,但我建议不要对该模型附加绝对结论。是的,这是一种思考SaaS的良好方式,并为我们提供了一个框架,用于讨论如何构建多租户解决方案。它无疑为我提供了一个强大的构造,用于与试图设计和架构其SaaS系统的团队进行沟通。它还强调了需要一套位于应用程序多租户架构范围之外的共享服务。然而,关键在于利用这些概念来指导您设计SaaS架构的方式,同时考虑到您的环境可能存在某些特殊情况,需要对设计方案进行调整。这并非要求严格遵循每个层级必须包含的内容,而是要构建一个能够明确划分职责、并与您的SaaS服务在安全、管理及运营特性上保持一致的架构。

多租户SaaS架构基础 | 构建多租户SaaS系统 | IT书单