假设我想使用 ASP.NET Core 创建一个多租户 SaaS 应用,并且我想使用类似于以下示例的 Azure SQL 弹性池: Microsoft
文档每个池的最大数据库数为 500:Azure 定价
附加信息:
我将从 Azure SQL 单一数据库开始
我将使用实体框架核心
问题:
如果我的应用超过 500 个用户,会发生什么情况?有哪些选项 如此高效地扩展?(达到弹性池的限制时)
该选项与 EF Core 迁移的匹配程度如何?
关于如何开始并在以后解决这个问题的任何其他建议?
答案上下文
在回答您的具体问题之前,让我添加一些有关我看到的解决方案的背景。多租户带来了租户管理。而且,就像在你链接到的文档中一样,可能会有某种目录包含所有特定于租户的信息。其中一条信息可能(很可能)是特定于租户的数据库的连接字符串。
假设一个租户连接,系统根据它所在的租户从目录中获取要连接的数据库(我们称之为租户的上下文)。应用程序会将连接字符串移交给应用程序的其余部分以使用。
现在,这就是解决方案的美妙之处:连接字符串可以(几乎)指向任何地方。它可以指向池中的数据库,也可以指向托管实例。它甚至可以指向已通过互联网提供的本地数据库。这一切都是因为应用程序不知道数据的位置,它只是获取一个连接字符串并开始工作。
1. 如果我的应用超过 500 个用户会怎样?有哪些选项可以有效地扩展它?(达到弹性池的限制时)
假设用户是指租户:什么都不会发生。将在应用程序可访问的任何位置(例如在新池中)创建新数据库。由于租户的连接字符串可以指向任何位置,因此完全没问题。
2. 该选项与 EF Core 迁移的匹配程度如何?
该选项与任何其他数据库模型一样适合 EF Core 迁移:需要以体面且受管理的方式执行数据库更新。例如,这可以通过运行迁移或更新脚本来完成。事实仍然是:您需要更新多个数据库。要做到这一点,制定一个体面的迁移计划是明智的。
有几种选择可以缓解可能的问题,或者至少限制东西损坏的可能性。一种是仅创建仅添加到当前模型的迁移。另一种方法是通过在服务总线等中间具有异步通信层来将数据库模型与应用程序分离。
这是一个非常复杂的策略,并且高度依赖于要构建的应用程序类型、数据库更新的频率以及数据库方案的复杂性等因素。
3. 关于以后如何开始和处理这个问题还有其他建议吗?
就我而言:如果你知道这即将到来,现在就采取行动。尽早实施多租户是最容易的。越往下走,就越难,因为您可能会在应用程序中开始硬编码(不是真的,而是某种)连接,一旦您想要添加多租户,就需要解耦。
结论
如果我正确解释了您的问题,您就会知道多租户将成为您的应用程序的"事物"。这意味着您需要从一开始就解决它。但是您不必从一开始就拥有完整的成熟多租户......你只需要为此做好准备。
更技术化一点:例如,您可以实现一个TenantContext
,该在登录时标识租户,并在登录时获取随附的连接字符串(存储、服务总线、数据库等)。然后,在应用程序的其余部分中,从TenantContext
获取连接字符串,并使用这些字符串获取特定于租户的数据。
首先,例如在开发过程中,上下文可能非常简单,并且只返回一个租户的信息。但是,由于您引入了解耦,应用程序的其余部分已经为多租户做好了准备。一旦需要它成为现实,您需要做的就是 实施TenantContext
.
编辑:
由于下面的评论,作为补充:有一种方法可以事先在DI系统中注册DbContext
实例。您可以实现类似注入上下文的ConnectionStringResolver
之类的东西。只要您实际需要DbContext,租户上下文也是已知的。构造 DbContext,使用ConnectionStringResolver
为租户查找正确的连接字符串。