作者:Suren Machiraju 和 Ralph Squillace

审校:Christian Martinez、James Podgorski、Valery Mizonov 和 Michael Thomassy

本文介绍针对 Windows Azure 设计多租户应用程序(通常是为其他组织提供服务的 ISV 应用程序)所需的方法,这些程序更高效,即运行或构建的成本较低,和/或性能更高、更稳定或可伸缩性更好。本文首先介绍多租户应用程序的一般原则、与构建和运行多租户应用程序有关的 Windows Azure 平台的结构和行为,然后侧重介绍多租户模式的特定方面,特别是应用于 Windows Azure 时的情况:应用程序和数据资源以及这些资源的设置和管理。本文从这些侧重点的每个方面讲述了您在 Windows Azure 上创建成功的多租户应用程序所必须综合考虑的安全、成本和可伸缩性问题。

什么是多租户应用程序?

Wikipedia 从以下方面给出了多租户模式的定义。

重要提示

如果您已知道我们将在本文中讲述的内容,请接着阅读 Windows Azure 多租户服务概述以直接跳到相关指南。如果您还有不太了解的内容,可以以后重新阅读本节。

多租户模式是指软件体系结构中的一个原则:在服务器上运行软件的单个实例,为多个客户组织(租户)提供服务。多租户模式与多实例体系结构对应,后者为不同的客户组织设置单独的软件实例(或硬件系统)。在多租户体系结构中,软件应用程序在设计上将数据和配置进行虚拟分区,每个客户组织使用一个自定义的虚拟应用程序实例进行工作。(Wikipedia.org)

简单地来说,这意味着什么?我们以一个餐馆预订应用程序为例加以说明。餐馆本身不具有 IT 基础结构来构建一个几乎实时与前台连接进行预订或取消预订的功能齐全的 Internet 预订网站。(在大多数情况下,餐馆雇用其他公司来构建自己的静态网站!)因此您可能创建一个单独的应用程序,该程序允许各个餐馆注册、创建帐户、使用自己的徽标和颜色自定义网页的外观、上载菜单、将 Web 应用程序与前台的计算机连接起来、处理来自其他预订应用程序的预订请求等。

在此示例中,每个餐馆看到一个自己使用的应用程序,一旦登录,这个程序就只是它们的。它们的客户仅看到餐馆的网站,似乎是餐馆自己构建好了一切。(对于想要就餐的客户来说,这就是一项增值服务,而且餐馆正在为此支付 ISV 费用!)这可能类似于以下关系图,其中预订应用程序支持多个租户,在本示例中为 Contoso 和 Fabrikiam 餐馆。在此关系图中,Bob、Priyanka、Jasmine 和其他客户正在考虑是否要订餐,他们可能正在看菜单。

它可能类似于以下关系图。

从体系结构上说,应用程序可以采用这样一种模式:每个客户都有一个全新的应用程序实例并且可以进行特殊的自定义;而且可能每个客户都有自己的虚拟机 (VM)。按常理来说确实如此,但是它会给 ISV 带来很多问题,如果您的应用程序应用范围较广时,这些问题大多数都会显现出来(此方法通常称为单租户、多实例设计。我们稍后将稍微详细地介绍这种方法,但是由于本文的侧重点不在此处,因此点到为止)。

如果您希望自己的应用程序被很多餐馆采用(很可能最终很多公司需要一般预订支持),您可能要构建一个在租户(在本示例中为餐馆)之间共享资源的应用程序,以便显著降低您的维护成本和资源成本,从在工作负荷增加时获得更好的性能、成本更低。以这种方式构建的应用程序即 Wikipedia 所说的多租户、单实例应用程序。

应用程序实例

需要指出的是,我们这里所说的“实例”是指整个逻辑应用程序,而非一个虚拟机、.exe、进程或其他类似的项。实际上,上图中的预订应用程序包含很多不同的外部和内部“服务”– 通过 Web 服务通信的组件。

通常构建这样的 Web 应用程序以使用 Web 场 – 在 Web 场中,多组服务器处理应用程序重要组件的多个实例,在应用程序执行时将任何应用程序状态数据存储在远程存储区中,这样,即便是某个应用程序的任何一个实例由于任何原因而消失,另一个实例可以恢复或者完成该进程。简而言之,这种高度可伸缩的新型应用程序可以拆分为进程组件和存储组件,这些组件与通信组件和安全组件一起构成了整体应用程序的单个面朝外的“实例”。

多租户服务的增加

Windows Azure 上的多租户模式意味着将应用程序拆分为无状态服务和存储区,并在需要时按照标识管理数据流:状态仅在必须直接处理租户的标识的那些服务中引入。它遵循一般面向服务的应用程序的服务无状态原则。例如,顶层服务(如网页和面向公众的 Web 服务)或安全服务本身,这些服务必须直接处理安全声明和令牌。而应用程序中的其他组件和服务应尽量可由应用程序中可代表任何租户的任何其他部分重用。

租户及其客户并不关注多租户模式

本节在此处要强调一件事:租户公司和它们的客户并不关注您的应用程序是如何构建的。他们只关注应用程序如何工作:是否稳定、性能如何,可以提供哪些功能以及费用是多少。他们完全没必要关注其他的事情。(当然,也可能存在这样的情况:您可能需要通过某种审核方式证实您正在构建和运行符合安全(特别是法律或法规)要求的程序。但是这些审核仅仅是为了证明规则合规性的例外情况,本质上并非针对体系结构。)

Windows Azure 多租户服务概述

设计多租户系统的关键问题是正确把握提供租户隔离功能(一方面)和提供这类专用资源的成本之间的平衡。换句话说,您必须计算可以在租户间共享多少资源以便您的解决方案正常工作且经济合算。通常租户间可以共享的资源越多,解决方案就越经济合算 – 只要它仍满足性能和安全要求。

注意

如果您不清楚什么是多租户模式或为什么它对 Windows Azure 应用程序很重要,请随时查看什么是多租户应用程序?以了解一些背景信息;然后再回到此处。

平衡的问题涉及很多方面,我们主要考虑以下方面:

  • 安全性 - 隔离存储的数据、身份验证以及授权机制
  • 缩放 - 自动缩放平台计算、缩放平台存储容量
  • 管理和监视
  • 设置多租户资源
  • 度量和计费

我们知道设计多租户体系结构是一个复杂的过程,其中存在很多变动因素,本文不打算详细讨论这些因素,而是介绍一些主要注意事项以及有帮助的提示,并提供指向相关详细信息的链接。依照这样的思路,让我们开始大体上了解这种体系结构。

体系结构概述

支持多个不同客户的一个方法是完全拒绝多租户模式,而是根据需要为每个客户分配资源。当您使用此方法(称为单租户)时,将自动为客户设置专用资源。如果您将分布式应用程序体系结构想象成一个频谱图,此方法代表的是频谱图一端的资源完全由租户专用的情形,而另一端则是资源完全共享的情形。本文介绍如何设计更靠近完全共享一端的分布式应用程序:具有共享(或多租户)应用程序和数据资源的分布式应用程序。

构建多租户应用程序时,您需要权衡为每个客户提供隔离所需的资源成本。显而易见,您需要考虑哪些应用程序和数据资源可以在客户之间共享以及哪些资源需要客户独占使用。但是,您必须要认识到,多租户模式在资源共享方面不能简单地全盘接受或者全盘否定。在面向服务的应用程序中,您可以(很可能)根据自己的需求,混合和匹配哪些资源可以在客户之间共享以及哪些资源由各个客户专用。需要再次强调:您可以决定哪些应用程序服务可以共享,可以共享到什么程度以及哪些服务不能共享。这给您的设计带来很大的灵活性。请利用这种灵活性。

哪些资源可以共享?

下图显示我们考虑的 Windows Azure 资源,我们将针对它们进行一些决策。查看关系图(和一般多租户体系结构)中所有资源的一个有用方法是提取每个组件并定义将它放置在应用程序或数据层中的何处。

在此关系图中,Windows Azure 计算和访问控制服务显然是应用程序层资源,中继端点也是,它们用于连接计算实例。表、Blob 和 SQL Database 显然是数据层资源。但是,Caching 以及队列通常作为支持某些应用程序设计和通信模式的临时存储区,因此可以根据其用途作为存储资源或应用程序层资源。

此外,您在具体事例中采用哪个方法取决于您要向租户公开多少功能。例如,如果您要允许租户向自己的客户端提供租户特定的标识,可能需要常规的、确保多租户安全的用户名/密码安全令牌服务 (STS)。但是,您可能还要允许租户实现一个这样的服务并与访问控制服务联合使用。另一个示例是您是否要允许租户的客户在租户的 Web 角色或辅助角色实例中上载和执行代码。这样做可能需要一个混合和匹配多租户和单租户角色实例的特定多租户解决方案。

在知道了这些之后,我们来考虑如何成功共享资源。我们将在本主题和其他主题中从应用程序的角度介绍在一个资源中支持多个租户的一般方法,还将介绍如何设置和管理这些资源以及如何使用 Azure 进行设置和管理。设置和管理共享的资源不会有大问题,但是在某些情况下值得我们深入探讨一下。

应用程序资源

设计多租户应用程序意味着确保计算、数据和其他应用程序组件尽可能处理多个租户标识以及每个租户的客户标识。本节讨论使用 Windows Azure 的各种方法中涉及的问题,并提出在您的应用程序设计中处理这些问题的最佳方法建议。

计算

我们首先了解一下 Windows Azure Web 角色和辅助角色提供的应用程序资源,以及在多租户解决方案中应如何使用它们来托管 Web 服务、网站和其他一般处理。

多租户应用程序中 Windows Azure Web 角色和辅助角色最主要的用途是,在采用单个角色实例为多个租户提供服务的模式中,根据租户服务中的需求增加(或减少)计算资源。

按主机标头划分网站租户

在最粗粒度的解决方案中,将配置每个 Web 角色实例来支持多个网站和 Web 应用程序,可能每个租户一个角色实例。这可以通过修改服务定义中的 Sites 元素来实现。每个网站可以绑定到同一端点并使用 HTTP/1.1 主机标头来隔离它们,或它们可以绑定到自己的端点。但是,请注意,将每个网站绑定到自己的端点不会按租户进行缩放,因为 Windows Azure 具有每个角色实例 5 个输入端点的限制。

如果您使用 HTTP/1.1 主机标头来支持多个租户,租户(以及它们的客户)只需通过不同的 URL(如 www.fabrikam.com 用于一个租户,www.contoso.com 用于另一个租户)就可以访问所需租户的网站,即使它们实际上是与单个 Web 角色实例内的单个端点联系。此方法允许您以最小的成本按租户隔离不同的网站文件。此方法还允许您按应用程序池隔离租户,因为默认情况下每个网站有自己的应用程序池。但是,请注意,因为提供 HTTP/1.1 主机标头的 URL 是在域名系统 (DNS) 中定义的,您需要让自己的域名提供商配置 DNS,使之指向您的 *.cloudapp.net 地址;请记住您的新租户 URL 要在 Internet 上变得完全可发现可能需要 24 小时。有关一个实例如何托管按主机标头区分的多个网站的示例,请查看 Web 角色的 Windows Azure 加速器

SSL 通信

使用 HTTP/1.1 主机标头方法的一个注意事项是 Windows Azure 不实施这些网站之间的安全边界;这意味着一个网站使用的 SSL 证书可以从其他网站使用。更为复杂的问题是,如果只有主机标头不同,IIS 7 不支持存在多个具有自己的证书的网站

重要提示

如果每个网站将单独的 IP 地址或端口用于自己的 HTTPS 绑定,可能有多个使用唯一服务器证书的 SSL 网站。与在 IIS 6.0 中一样,如果用于这些网站的 HTTPS 绑定位于同一 IP 地址/端口并只使用主机标头区分,则 IIS 7.0 不支持存在多个具有自己的服务器证书的网站。这是因为进行 SSL 协商时,主机标头信息不可用。因此,在使用主机标头的同一 IP 地址具有多个网站的唯一方法是配置所有这些网站以使用具有通配符 CN 的同一 SSL 证书。有关详细信息,请参阅http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/596b9108-b1a7-494d-885d-f8941b07554c.mspx?mfr=true

因此,如果您正在使用 SSL 证书,可能需要采用不同的方法。一种方法是使用带通配符 CN 的单个证书(采用格式 *.yourdomain.com),或使用统一通信证书(您显式列出了所有子域)。这类证书可以从 GoDaddy 和 Thawte 等证书颁发机构获取,它们很容易创建。每个租户然后使用 URL 通过 SSL(如 https://fabrikam.yourdomain.com 或 https://contoso.yourdomain.com)来访问资源。

另一个方法是为每个网站分配一个专用 Web 角色和一个租户证书。因为这不是多租户方法,它也不能缩放,因此需要占用更多计算资源,管理开销也更大。尽管如此,有时仍需要采用这种方法。

按查询参数划分网站租户

另一个方法是使用单个网站来为多个租户提供资源。如果您的网站是使用 ASP.NET MVC 构建的,可以为每个租户创建单独的 MVC 区域。或者,您在它们之间共享默认区域并基于查询参数(如租户 ID)使控制器以不同方式呈现内容。如果您要按租户提供进程隔离,需要在网站内定义虚拟应用程序。实际上每个租户在网站下获得一个虚拟应用程序。这也可以通过执行以下操作实现:编辑服务定义内的 Sites 元素,但是不为每个租户添加新的 Site,而是在您的主 Site 元素中,为每个租户添加一个 VirtualApplication 元素

辅助角色中的 Web 服务

对于完全多租户解决方案,托管 Web 服务的辅助角色与 Web 角色中托管的相应服务具有相同的行为 - 所有租户访问相同的服务端点。

辅助角色也用于提供后台处理。在完全多租户方案中,您使用一个辅助角色,该角色的RoleEntryPoint.Run 方法循环处理工作项但是并不知道工作项是哪个租户创建的 -- 因此您是在所有租户上共享计算资源。

存储

多租户应用程序必须实现如何隔离它们存储和使用的数据并保持良好性能。本节介绍 Windows Azure 中的数据存储技术,包括 SQL Database,Windows Azure blob、表和队列,服务总线队列和主题以及多租户应用程序中的 Caching 服务。

作为应用程序的存储区,SQL Database 存储显然是一个重要的存储位置。但是在多租户体系结构中,它的用途并不仅限于此,还充当设置新租户以及存储管理数据的存储区。

将 SQL Database 用于应用程序资源

在此方案中,多个租户的应用程序数据存储在单个逻辑数据库中。尽管提供多租户数据库有明显的成本优势(通过在所有租户上分摊成本来实现),但是如果要满足此方案特定的各种要求,则会增加系统的复杂性:

  • 必须充分隔离数据并防止一个租户无意或恶意访问另一个租户的数据。
  • 为所有租户维护合理的查询性能,同时限制个别(特别是消耗大量资源)的租户所造成的影响。
  • 处理快速增长的共享数据库大小,它可能超过 SQL Database 当前支持的最大数据库大小:50 GB。

从概念上说,将租户数据和查询处理分布在多个数据库上可以提高性能,但问题是,哪种体系结构允许您在解决方案中使用此功能?在回答此问题前,我们先看一下体系结构的频谱图。在此频谱的一端是传统向上扩展,即您使用功能更强大的硬件来解决问题。和单租户体系结构方法一样,我们的重点并不是向上扩展,提到它只是为了帮助理解,因为它对多租户解决方案有太多的限制。我们关注的重点是使用分片技术的各种向外扩展方法:

  • 线性分片
  • 扩展分片
  • 压缩分片
  • 混合线性/扩展分片体系结构。

上述四种有用的分片技术都是将数据库添加到体系结构以支持向外扩展,对于每种技术,在存储的、定义分片的数据(通常是指数据域或数据联合)之间有一定的逻辑分隔。可以使用某些键值(如客户 ID)或属性(如年)来定义这些数据域。在本文中为了简单起见,在多租户体系结构的环境中,我们将数据域看作租户。

回到前文的频谱图中,在频谱图的一端是传统的向上扩展模型。在此方法中,所有租户共享相同的 SQL Database。换句话说,每个数据库有多个租户。在频谱图的中间是线性分片体系结构,在该结构中每个租户有自己的 SQL Database。在频谱图的远端,每个租户可以有多个 SQL Database,这称为扩展分片方法。

其他两个方法适用于中间的方案。在压缩分片体系结构中,SQL Database 数目少于租户数,但是有一个以上的 SQL Database。同样,在有多个数据域、针对每个域作出分片决策(如区域和租户)的方案中,我们提供混合线性/扩展分片体系结构,在该体系结构中,每个区域获得一个特定的、具有多个数据库的扩展分片,特定租户的数据分布在该扩展分片的多个数据库中。换句话说,体系结构按区域线性向外扩展,但是采用按租户的扩展方式。这些分片方法需要抽象层(如 Enzo SQL 分片库),该层知道如何在实现的分片方法中导航,特别是帮助将查询分散到所有分片并将数据修改操作定向到相应的分片。在 2011 年下半年推出的 Windows Azure SQL Database 联合承诺简化在 SQL Database 上实现分片体系结构,但是我们要考虑您当前应执行哪些步骤来实现这些体系结构。

在 SQL Database 中保护多租户数据

我们首先了解一下如何保护您的租户数据。从本质上说,在 SQL Database 的数据库级别管理安全性与管理内部 SQL Server 的安全性基本相同,这意味着创建安全原则并使用它们来控制对特定架构对象(架构、表、视图、存储过程等)的访问。然后您创建合适的每租户 SQL Server 登录名、数据库用户和数据库角色,并使用这些安全原则将权限应用到架构对象。一个方法是为每个租户定义一个架构 – 应用到架构的安全设置将访问权限仅限于该租户。

另一个方法是在同一组表中存储所有租户数据,通过某些键(如租户 ID 列)来在表内分隔它们,这样实现逻辑分隔。在此方法中,业务层中的逻辑负责正确按租户筛选数据访问权限(尽管 SQL Database 联合也可以执行此任务)。此方法的关键在于数据的所有请求必须穿过此逻辑以将访问权限限制为正确的租户;OData(借助使用查询和更改拦截器的 WCF Data Services)是实现此方法的合适技术。我们甚至提供一些框架(如 Enzo,将在以后讨论)帮助您实现此逻辑。

在知道了这些之后,让我们将它们应用到以前所述的向外扩展体系结构。线性分片体系结构中的安全设置可以很简单:每个租户有自己的数据库,因此有针对该分片的专用登录名和用户。在所有其他分片体系结构中,安全设置需要更加精细,它依赖于在架构对象级别定义的权限和业务层的实施的组合。

性能注意事项

接下来,我们将重点放在性能上。SQL Database 维护任何 SQL Database 的三个副本。在一个主副本和两个辅助副本间复制每个数据库的数据时,所有读取和写入操作均在主副本上进行,辅助副本仅在故障转移情况下帮助进行查询处理。Windows Azure SQL Database 体系结构确定主副本和两个辅助副本的位置。如果承载主副本的计算机负载很重(由您自己的租户或其他租户造成),SQL Database 体系结构可能将另一计算机上工作负载较轻的辅助副本切换为主副本。此切换的速度很快,但是仍会导致活动会话的中断,此时必须准备好多租户应用程序来进行处理。

在知道了这些之后,如果要优先确保每租户性能,您应考虑使用分片体系结构,该结构为每个租户分配一个或多个数据库(如线性、扩展或混合体系结构)。但是,如果您有很多要这样分配数据库的租户,会遇到一些困难。显然,您创建的每个数据库是有成本的,但是更重要的是每个 SQL Database 服务器只能有 149 个数据库,如果您调用云支持服务 (CSS),此限制就会显现。对于具有很多数据库的多租户情形,您的解决方案还需要能在达到此限制值的情况下分配 SQL Database 服务器。

将 Windows Azure 表用于应用程序资源

使用一个存储帐户名称和密钥来保护 Windows Azure 表,该存储帐户名称和密钥只能为所有存储资源全局分配。这意味着要提供每租户数据的隔离存储,服务提供商必须为每个租户创建一个存储帐户。这可以通过 Windows Azure 服务管理 API 来实现。分配新存储帐户不会产生额外成本,并且这样做可以提高性能,因为可以将不同的资源应用到不同的帐户。也就是说,通过配额来管理一个订阅可以具有的存储帐户数,而配额可以通过与云服务支持 (CSS) 联系进行调整。

如果您的应用程序需要在单个帐户中存储多个租户的数据,必须创建自己的抽象方式筛选返回给指定租户的数据。一种方法是为每个租户创建一个表并在每个表级别授予访问权限。此方法的优点是您可以利用完整的分区键和行键来快速访问数据,而且将查询定向到正确的表所用的逻辑很简单。缺点是会增加系统复杂性,因为您必须基于租户将查询定向到相应的表。另一种方法是在表内按租户进行水平分区,此时您的数据访问层仅将具有特定分区键的数据返回给客户端。这避免了将查询定向到相应的表的麻烦,但是将您限定为单个分区键值,因而会影响大型每租户数据集的性能。

将 Windows Azure Blob 用于应用程序资源

Windows Azure Blob 可以很好满足多租户应用程序的存储需求。您应创建公共 blob 容器以便提供对网站图像、图形和租户徽标等共享数据的只读访问。私人 blob 容器(仅由特定租户或租户和系统访问)将用于文档或每个租户的配置文件等应用程序数据。除了进行匿名访问之外,务必要使用共享访问签名为各种操作指定受保护容器或 blob 的容器级访问策略,这些操作包括:blob 读取/写入、拦截列表、属性或元数据,删除 blob、租借 blob 和枚举容器内的 blob。通过指定容器级访问策略,您可以调整权限而不必使用共享访问签名签发受保护资源的新 URL。

将 Windows Azure 队列用于应用程序资源

Windows Azure 队列通常用于代表租户驱动处理,但是也可能用于分配设置或管理所需的工作。

此处我们要考虑是使用指定的队列管理属于多个租户的项,还是为每个租户分配一个队列。Windows Azure 存储模型仅适用于存储帐户级别,因此如果需要按租户隔离队列,必须在单独的存储帐户下创建它们,就像使用表存储方式时所做的那样。此外,在单个队列的情况下,不可能定义将用途限制为仅放置或仅接收消息的权限,因为如果某个租户具有有访问权限的存储帐户,他可以执行 Azure 队列 API 允许的每个操作,甚至可以删除共享队列!简而言之,队列不应公开给租户,而是由服务自动管理。

将服务总线队列用于应用程序资源

对于将工作推送给共享服务的租户特有的应用程序功能,您可以使用单个队列,这样每个租户发送者只有权(根据从 ACS 签发的声明派生)推送到该队列,而只有服务的接收者有权从数据来自多个租户的队列进行请求。此过程的反方向可能是使用 AF 队列时的情况,您可以使用系统服务推送单个队列上针对特定租户接收者的消息。您还可以使用 AF 队列的订阅功能多播这些消息。最后,您可以使用会话消息将客户特定的工作定向到客户特定的接收者,尽管只通过单个共享队列推送。

尽管这些方法最大程度减少了您必须管理的队列数(这在某种程度上降低了总体系统复杂性),它们可能限制排队或取消排队操作的吞吐量,因为未在更多资源上分摊负载(使用多个队列时也是如此)。此外,在有多个租户发送者的情况下,您必须能解决单个租户独占队列、而其他下游处理的租户消息得不到处理的问题。使用 AF 队列,您可以延迟消息,因此还可以检测来自单个租户的大量消息,暂时延迟这些消息以处理其他租户的消息,之后再来处理它们。

将缓存服务用于应用程序资源

在多租户应用程序中,缓存通常用于频繁访问的租户特有的应用程序数据。因为不提供在单个缓存内设置不同权限的功能,此模式将为每个租户设置不同的缓存。这意味着为租户设置新的 AppFabric 命名空间并在该空间内创建缓存。目前不提供可以自动创建缓存的管理 API,因此仍需要操作员使用 Windows Azure 门户手动进行创建。

连接和安全服务

Windows Azure 多租户应用程序使用其他“中间件”服务实现连接和安全功能:服务总线中继服务和 Windows Azure 访问控制服务 (ACS)。

将 ACS 用于应用程序资源

Windows Azure 访问控制服务

是一种基于云的服务,它在使得身份验证和授权功能从您的代码中分离的同时,提供了一种简便的方法来验证用户身份并为他们授权,使他们可以访问您的 Web 应用程序和服务。不必使用您的应用程序特有的用户帐户来实现一个身份验证系统,您可以通过 ACS 执行身份验证和对用户授权的大多数工作。ACS 与基于标准的标识提供程序集成,包括企业目录(如 Active Directory)和 Web 标识(如 Windows Live ID、Google、Yahoo! 和 Facebook)。(如果您不信,请阅读此文章。)

无论您是否在构建多租户系统,ACS 都可以实现对应用程序本身的安全访问。使用 ACS,您的应用程序可以通过一个身份验证 API (ACS API) 来构建,通过该 API 可以处理任何标识提供程序的安全令牌。这意味着您不必为 Facebook、Google、Yahoo、Windows Live 等各个第三方标识提供程序或 Active Directory Federation Server (ADFS) 编写单独的代码。您只需要为 ACS 编写代码而将其余工作留给 ACS 和标识提供程序。

在 ACS 中设置标识

如何配置 ACS 或实现您自己的 STS 的详细信息已超过本文档讨论的范围,但是您可以在识别声明的 Web 应用程序和服务的授权中开始考虑这类问题。要了解用于通过联合安全性外包您应用程序的安全功能的基本方法,请阅读本指南。要开始构建您自己的 STS,您可能要从此处了解有关如何使用 Windows Identity Foundation (WIF) 构建 STS 的背景知识,但是最好从一个完整的 STS 入手(如 Thinktecture 的 STS 入门)并对它进行自定义以满足自己的需要。

在使用 ACS 的多租户应用程序内,通常使用以下高级步骤设置标识:

  • 创建证书(例如,每个租户)
  • ACS 命名空间设置(如果按命名空间隔离),包括要保护的租户的应用程序配置(称为依赖方, RP)和声明转换规则。使用 ACS 管理 API 或 ACS 门户完成此操作。
  • 创建用于租户登录的 root 管理员帐户(使用提供安全令牌服务的标识的 API)。
将服务总线中继用于应用程序资源

作为端点公开的服务可能属于某租户(例如,在系统外托管(如内部部署)),或可能是专门为租户设置的服务(因为通过它们传输敏感、租户特有的数据)。在这些情况下,处理多个租户不成问题,困难在于实施租户特有的用途。使用访问控制服务 (ACS) 保护对这些端点的访问,其中客户端必须有签发人名称和密钥、SAML 令牌或简单 Web 令牌。这可以使用服务总线和 ACS 管理 API 通过编程方式进行配置。

注意

请记住服务总线队列和主题以及订阅已作为存储方式讨论过,尽管它们通常用于以特定方式处理应用程序数据流。

设置资源

本节讨论如何设置资源以支持多租户应用程序。和在应用程序设计内支持多个租户一样,设计多租户设置也有几个决策点,具体取决于您要启用的功能以及您的应用程序使用的 Windows Azure 服务。

和多租户应用程序的设计一样,我们将讲述如何使用计算、存储以及连接和安全服务来设置多租户应用程序。

使用 Azure 角色设置和管理资源

多租户解决方案中的专用辅助角色通常用于设置和取消设置每个租户资源(如新租户注册或取消注册时)、收集度量使用量的数据、按某个计划管理缩放或响应关键性能指标超过阈值。这个角色还可用于将更新和升级程序应用到解决方案。

Web 角色通常专用于允许服务提供商监视和管理系统资源、查看日志、性能计数器以及手动设置等。

将 ACS 用于设置资源

设置受 ACS 保护的租户资源时,您将需要使用 ACS 管理 API 或门户来为新设置的租户创建初始 admin 帐户。

将缓存服务用于设置资源

设置受 ACS 保护的租户资源时,您将需要使用 ACS 管理 API 或门户来为新设置的租户创建初始 admin 帐户。

设置存储的注意事项

适用于多租户解决方案中的 Windows Azure 表、blob 和 SQL Database 的一个注意事项是地理分布,特别是在识别在系统内必须唯一(跨解决方案中使用的所有数据中心)的数据并确保用户获得良好体验时。一种方法是构建自定义复制策略以将这类共享数据靠近最终用户(当然必须确保新数据是唯一的,可能通过始终插入到主数据源来实现)。另一种方法是对数据进行分区,以便将访问全局数据的数量和频率降到最低。

通常 Azure 存储的另一个注意事项是 Azure 所施加的硬性限制,因为“大”并不是无限的。计划您的多租户解决方案时,应考虑这些可伸缩性限制

将 SQL Database 用于设置资源

在涉及大量数据的一些多租户方案中,最好通过从现有 SQL Database 参考实例复制来设置新的 SQL Database。这样做可提高设置速度,但是必须综合考虑除租户和系统本身的成本之外,还会带来维护额外 SQL Database 的成本。

设置 SQL Database 资源

设置租户的新 SQL Database 资源的方法包括:

  • 在脚本中使用 DDL 或将它们作为程序集内的资源嵌入
  • 使用 API 创建 SQL Server 2008 R2 DAC 包并部署它们。您还可以将 Windows Azure blob 存储区中的 DAC 包部署到 SQL Database,如本示例中所示。
  • 从主引用数据库复制
  • 使用数据库导入导出功能从文件设置新数据库。
设置 Windows Azure BLOB 存储区

设置 BLOB 存储区的方法是首先创建容器,然后应用策略,创建共享访问密钥并将它们应用到受保护的容器和 blob。

将 Windows Azure Blob 用于设置资源

为新租户设置计算或预先初始化的存储资源时,应使用容器级访问策略(如上所述)来保护 Azure blob 存储区以保护 CS 包、VHD 映像和其他资源。

管理资源

最后,多租户应用程序的设计必须能执行非常重要的任务,如管理应用程序、租户及其服务,管理所有数据资源和解决相关的连接和安全问题。本节介绍在运行 Windows Azure 时通常如何使用计算、数据和其他服务来支持多租户应用程序。

将 Windows Azure 角色用于管理资源

服务提供商需要提供监视和管理系统资源的方法。Web 角色通常专用于为服务提供商提供用于管理资源、查看日志、性能计数器和手动设置等的工具。

将 ACS 用于管理资源

大多数多租户系统将需要在 ACS 内创建的、用于保护系统资源的命名空间,以及创建和管理每个租户的命名空间(例如为使用 AF 缓存所用的命名空间)。这也可以使用 ACS 管理命名空间来实现。

将缓存服务用于管理资源

如果服务提供商将某些 KPI 或计算统计信息公开给所有租户,它可能决定缓存这些通常请求的值。租户本身不能直接访问缓存,必须通过某个中介(如 WCF 服务)来访问,该中介保留访问缓存的实际授权密钥和 URL。

将 SQL Database 用于管理资源

这样的示例包括非联合租户的单个系统级、不知道数据中心的成本资格/角色的数据库,或那些依赖于配置为用于 ACS 的自定义 IP STS 的数据库。对于关注多个地理分布的多租户系统,存在管理数据的中央系统问题。要解决这些问题,您可以采用我们以前所述用于应用程序资源的方法,即通过定义您的地理区域为混合线性/扩展分片体系结构中的分片或采用更简单的线性分片体系结构。在这两种情况下,利用中间层逻辑分散和聚合结果以监视和管理查询。

将 Windows Azure 表用于管理资源

Windows Azure 诊断 (WAD) 基础结构默认情况下登录到 Windows Azure 表。依赖这些 WAD 表(跟踪、事件日志和性能计数器)时,您只需要考虑记录的数据有多敏感、谁有权访问它们以及最后选择是在客户间隔离它们(也称为设置)还是在系统范围内共享。例如,您不可能允许所有租户直接访问诊断日志表(该表汇总了解决方案中所有实例的跟踪数据)和将一个租户的数据公开给另一个租户。

将 Windows Azure Blob 用于管理资源

存储在 blob 存储区中的规范管理资源是 IIS 日志和崩溃转储信息。将 IIS 日志从角色实例传输到 blob 存储区。如果系统监视依赖于 IIS 日志,您将要确保通过容器级访问策略只有系统可以访问这些日志。如果您的租户需要这样的一些数据,您将要对数据执行一些后处理(可能为了确保仅包含该租户的数据),然后通过租户特定的容器将结果推送给租户。崩溃转储在另一方面只是服务提供商系统为了帮助排除基础结构故障而要访问的信息,它很可能包含跨租户的数据。

度量

在多租户应用程序的环境中,度量的目的是对租户计费(该费用与使用情况有关)和收集系统级 KPI 来了解容量计划和正在进行的体系结构决策。度量什么呢?度量一般分为以下类别:

  • 原始资源消耗量:Azure 和 AppFabric 资源使用量(如计算小时数、数据存储大小、消息数)
  • 应用程序功能的特定使用量(例如,每次使用计费的高级操作)
  • 租户自己的用户产生的使用量

后两个度量倾向于由应用程序特定要求驱动,因此我们将着重讲述对所有基于 Azure 的服务提供商通用的原始资源消耗量。从原始资源的角度看,对于大多数 SaaS 应用程序,计算小时数最重要,其次是存储大小,最后是从数据中心的数据传输量(传出)-- 尤其现在到 Azure 数据中心的数据传输是免费的。

因此您如何获取度量原始计算或存储量方面的数据呢?让我们举例说明。

计算小时数

遗憾的是,目前没有 API 用于按服务提供商的订阅查询此信息。最好的方法是按照对 Windows Azure 计算时间进行计费的方式来近似度量使用量。例如,对于分配的每个实例,计算实例运行的小时数,将它向上舍入到最接近的小时数,再乘以实例大小的每小时成本。

数据存储

同样,没有公共的计费或管理 API 可以提供 Windows Azure 存储(Blob、表或较少使用的队列)或缓存和服务总线队列的精确使用量,但是我们可以通过知道正在存储的实体大小和跟踪租户在计费期平均使用存储的实体数来近似得到这方面的数据。SQL Database 大小是个例外;您可以通过在 master 数据库内查询 sys.database_usage 并汇总一个月的结果来获得实际成本,从而确定您要在当天计费的数据库大小。

针对多租户解决方案缩放计算

尽管特定要求会有所不同,通常考虑自动缩放时,该方法意味着根据一些探索法增加或减小实例计数。此探索法可能依赖于从原始数据(如性能日志、IIS 日志或甚至队列深度)派生的一些关键性能指标 (KPI)。此外,可能实现它仅仅为了响应某个计划,如记账应用程序中通常针对月末突发情况增加实例计数,而在其他时间减少实例计数。

这里考虑的关键因素是增加或减少实例计数不是瞬间完成的。您的算法应满足这两方面的需求。增加实例计数时,最好您可以预计需求:它不必是很长范围的预测(但是基于 20 分钟)以允许您的实例变得可用。减少实例计数时,考虑到您为作为完整小时的部分小时付费,因此为这个完整小时保留那些不需要的实例更有经济意义。

结论和资源

框架和示例

阅读上述内容后,您可能同意构建多租户解决方案是个大投资的说法。从这个角度看,从示例或框架入手比较合适。以下是一些好的入手点。

Windows Azure 的 Microsoft Enterprise Library 5.0 集成包

Microsoft 企业库是解决企业软件开发中常见的横向问题的可重用应用程序块集合。Windows Azure 的 Microsoft Enterprise Library 集成包是可用于 Windows Azure 技术平台的 Microsoft Enterprise Library 5.0 的扩展。它包括自动缩放应用程序块、暂时性故障处理应用程序块、blob 配置源、受保护的配置提供程序和一些学习资料。从此应用程序块开始学习是个不错的选择。

CloudNinja

CodePlex 上提供的 CloudNinja 示例演示本文所述的多租户模式的以下方面。

  • 多租户 Web 角色
  • 专用管理/设置辅助角色
  • SQL Database 中的线性分片
  • 用于管理的专用 Windows Azure 表
  • 用于设置的专用 Azure 队列
  • 专用公共/私人 Blob 存储区
  • 多租户 AppFabric 缓存
  • 基于时间和 KPI 的自动缩放
  • 度量
  • 具有自定义 STS 和 ACS 的联合安全性
Fabrikam Shipping

Codeplex 上提供的 Fabrikam Shipping 示例演示多租户 SaaS 方案的很多方面。

  • 专用和多租户 Web 角色
  • 专用管理/设置辅助角色
  • SQL Database 中的线性分片
  • 专用公共/私人 Blob 存储区
  • 具有自定义 STS、ADFS、Facebook、Google、Live ID 和 ACS 的联合安全性
  • PayPal 集成
Enzo SQL 分片库

CodePlex 上提供的 Enzo SQL 分片库演示和帮助理解本文中所述的各种 SQL Database 分片技术。

Lokad 云

Lokad 云是一个功能丰富的框架,它提供本文中所述的很多功能,还提供其他功能。

  • 自动缩放
  • 强类型化的 Azure Blob、表和队列存储(这称为对象到云的映射程序)。
  • 任务计划程序
  • 日志记录
Azure 自动缩放

如果您正在查找要从中构建您自己的自动缩放程序的简单示例,CodePlex 上的“Azure 自动缩放”示例是个不错的选择。当然,我们还提供一些商业软件来帮助解决更复杂的问题。特别是 Paraleap AzureWatch 可帮助您自动缩放您的应用程序。 

链接和参考

多租户体系结构

相关主题

在 Windows Azure 上设计多租户应用程序的更多相关文章

  1. 在Windows Azure上配置VM主备切换(1)——Linux篇

    对任何一个上线系统来说,高可用设计是不可或缺的一个环节,这样才可以确保应用可以持续.稳定的运行,而不是频繁的掉线.停机.高可用设计的核心思路很简单,就是消除一切单点故障,将单点链路或者节点升级为多点. ...

  2. 在 Windows Azure 上部署并定制化 FreeBSD 虚拟机镜像

     发布于 2014-12-11 作者 陈阳 FreeBSD 基础镜像现已登陆中国的 VM Depot! 对于青睐 BSD 而非 Linux 的开源爱好者来说,这无疑是个好消息.同时,随着该基础镜像 ...

  3. 如何将SQL Server运行到Windows Azure上

    从2012年6月6日开始,Windows Azure上一些强大的新功能现在可用于预览,包括新的Windows Azure虚拟机(VM).其中有关Windows Azure虚拟机最强大的一件事是他们利用 ...

  4. Windows Azure 上的 Symfony,适用于 PHP 开发者的强大组合

     发布于 2014-06-13 作者 陈 忠岳 Symfony 是针对 PHP 开发者的流行开源 Web 应用框架.现在,您可以更轻松地在 Windows Azure 上使用它,这都归功于 Ben ...

  5. 快速学习使用 Windows Azure 上的 SharePoint Server 2013

     为了在当今的企业环境中占据一席之地,您需要能够迅速顺应变化和应对挑战.有时,需要及时调整您的SharePoint 基础结构以保持竞争优势. 基础结构即服务可通过随时使用.即付即用的解决方案应对这 ...

  6. Windows Azure 上 Linux VM 中的交换空间 – 第 2 部分

    本文章由 Azure CAT 团队的 Piyush Ranjan (MSFT) 撰写. 在前一篇文章 Windows Azure 上Linux VM 中的交换空间第 1 部分中,我介绍了在默认情况下, ...

  7. 在 Windows Azure 上部署预配置 Oracle VM

    Microsoft 和 Oracle 近期宣布建立战略合作伙伴关系,基于此,我们将通过 Windows Azure 镜像库推出多种常用的 Oracle 软件配置.即日起,客户可以在 Windows S ...

  8. 为在Windows Azure上的网站配置自定义域名

    本篇体验给Windows Azure上的网站自定义域名,首先"CNAME"和"A记录"是必须了解的概念. 假设,在Windows Azure上的网站域名是:x. ...

  9. 在Windows Azure上创建ASP.NET MVC网站

    本篇体验在Windows Azure上创建ASP.NET MVC网站. →登录到Windows Azure管理门户 →点击左下方的"新建" →点击"自定义创建" ...

随机推荐

  1. (转)如何获得当前ListVIew包括下拉的所有数据?

    ListView listView = activity.getListView();获取的仅仅是当前屏幕显示的list,但是具有下拉信息,不在当前屏幕,但是下拉显示的数据无法或得到.谁知道如何获得当 ...

  2. json.loads(s) returns error message like this: ValueError: Invalid control character at: line 1 column 33 (char 33)

    json.loads(s) returns error message like this: ValueError: Invalid control character at: line 1 colu ...

  3. CFile用法(转)

    一.各种关于文件的操作在程序设计中是十分常见,如果能对其各种操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而在较短的时间内编写出高效的代码,因而熟练的掌握文件操作是十分重要的.本文将对Vis ...

  4. 阿里云SLB快速切换至https

    域名caifuxiang.com是直接解析到阿里云SLB的,运行了好几年的http服务,今天通过修改配置快速切换到了https,莫名就感觉更上档次了! 首先,SSL证书 服务可以提供免费单域名证书 w ...

  5. JavaScript Promise启示录--(转)

    本博文转至:http://www.csdn.net/article/2014-05-28/2819979-JavaScript-Promise [编者按]JavaScript是一种基于对象和事件驱动并 ...

  6. LWIP在STM32实现

    http://www.openedv.com/posts/list/25178.htm

  7. app的apk 安装的方法--adb--命令安装 (含把apk放某个文件夹,每次启动自己安装)

    adb安装 1.在app自动化之前,首先手机上有要被测试的app,如何把电脑本地上的app安装到手机上呢?可以在运行自动化代码前,在cmd输入adb指令,把电脑app安装到手机上 adb instal ...

  8. 52道Python面试题

    1.python中is和==的区别 Python中对象包含的三个基本要素,分别是:id(身份标识) .type(数据类型)和value(值).‘==’比较的是value值‘is’比较的是id 2.简述 ...

  9. MySQL 5.7 坑爹参数 – log_timestamps

    官网原话: This variable was added in MySQL 5.7.2. Before 5.7.2, timestamps in log messages were written ...

  10. py4常用模块

    导入模块方式 import 单文件 from dir import file 目录下文件 如果有相同的名称,可以采用别名的方式 from dir import file as rename.file ...