6

我正在开发一个非常复杂的多租户应用程序架构。

.

3种完全不同的应用程序

许多客户使用的应用程序不止一种;有 3 种不同类型的应用程序。

应用 A、应用 B、应用 C

.

每个APP都是多租户的

每个应用程序都有其客户。

APP A - 客户 A1 - 客户 A2

APP B - 客户 B1 - 客户 B2

APP C - 客户 C​​1 - 客户 C​​2

.

共享信息

许多信息在不同的应用程序之间共享

“客户 A1”需要操作或仅查看“客户 C1”拥有的数据

.

问题

考虑到我正在使用 Asp net mvc、EF、Sql Server。哪个是正确的实现?

一个站点和多个区域?创建多个站点?多个数据库?只有一个分贝?过滤?sql过滤视图?...

一些应用示例?

编辑

和...把业务逻辑放在哪里?

4

5 回答 5

2

我建议您首先在 .Net 之上构建自己的多租户工程堆栈(框架),它将处理多租户在租户明智数据隔离、支持水平扩展、基于视图过滤方面的所有要求用户的租户上下文和角色,租户明智的数据模型扩展,租户明智的 UI 定制,基于角色、权限和数据范围实施访问限制——对于不同的租户可能会有所不同等。

业务逻辑可以建立在这个框架之上。这种方法将为您的产品提供强大而强大的工程基础。

另一种选择是购买现成的多租户工程堆栈,将其安装在 Visual Studio 上并将其用作开发模板。

于 2011-01-21T07:02:01.013 回答
0

理想情况下,在具有单个应用程序的多租户服务器中,您希望每个租户在物理上使用不同的数据库,而不仅仅是指定数据属于哪个租户的列

但无论哪种方式,您都必须确保所有数据库函数都使用正确的数据库连接或租户列键。这是真正的问题

确保这一点的方法是每个做出此决定的应用程序只有一个函数,并确保所有数据库函数在没有调用此函数时都失败(直接或间接如下)

例如,使用 global.asax AuthenticateRequest 或 BeginRequest 函数中的 MVC,您可以验证用户是谁,然后计算他们需要使用哪个数据库连接,或者在针对该请求的每个查询中必须使用哪个租户列键。然后将其存储在会话变量等中

如果你有三个应用程序,我会创建三个独立的网站。他们可以通过共享项目共享公共类。如果它们可以单独部署,生活通常会更轻松

于 2010-12-01T03:18:21.090 回答
0

这是一个具体的答案,但只是您在设计时可能会考虑的一些方面。

关于共享信息,我认为这里最重要的部分是定义客户之间的关系以及每个客户相对于其他客户拥有的角色和权利。最好的方法是首先确定可以做什么。

例子:

Read Only|cust1|cust2|cust3
---------+-----+-----+-----
customer1| 1   | 1   | 0
customer2| 0   | 1   | 0
customer3| 1   | 0   | 1

Write    |cust1|cust2|cust3
---------+-----+-----+-----
customer1| 1   | 1   | 0
customer2| 0   | 1   | 0
customer3| 0   | 0   | 1

所以在上面,customer1 可以读取和写入(更新)customer2 的数据。

话虽如此,主要问题是对这些关系进行建模,即共享信息。使用@TFD 的建议,这些关系可以在客户登录时与相关租户 ID 一起加载到会话中。

(根据提供的信息,我的另一个倾向是,这可能是每个应用程序的问题,而不是客户唯一的问题。为了说明这一点,请将上表中的 'cust' 值替换为App。)

为每个应用程序创建单独的站点,因为我假设每个应用程序都有一个独特的目的,尽管有共享的功能。

如果存在其他交叉数据关系,可能需要不同的 Config DB。数据库将存储每个应用程序的所有租户信息(包括与其他应用程序的关系)。这个建议的原因是,据我所见,您有三个独立的多租户应用程序,它们使用共享数据库方法相互独立 - 但每个应用程序都需要在某种程度上与另一个应用程序进行交互。
就数据库中的客户而言,我建议将“客户”表限制在配置数据库中。然后,您可以拥有基于每个应用程序要求的内容数据库。

于 2010-12-01T20:25:56.137 回答
0

我的建议是使用带有 Sliverlight 和 MVVM 设计模式的 PRISM。PRISM 专为这种复合应用程序而设计,其中每个应用程序都是独立的,并且还可以通过 PRISM 公开的事件相互通信。

于 2011-01-20T09:49:01.893 回答
-1

您可以有多种方法 - 由于应用程序是数据驱动的,因此即使在应用程序出现错误的情况下,构建一个能够保护数据的数据库设计也是有意义的。

一种方法是确保有用于访问任何表的存储过程,并且将安全逻辑内置到存储过程中。您可以确保为每个客户使用不同的数据库用户名,并且该数据库用户名映射到映射表中的该租户 ID。然后存储的过程可以始终检查被请求/修改的数据实际上属于映射到正在运行过程的 db 用户的租户 ID(通过使用上下文信息)。

然后,您将需要某种方法来确保应用程序创建的数据库连接仅使用映射到该租户 ID 的相应用户名。这意味着您需要另外一个存储过程来为您提供此信息(可能使用用户名/id 作为输入),并且此存储过程应该可以通过通用数据库用户名执行。请记住,这是唯一需要为该公共数据库用户授予执行权限的存储过程。

这可能看起来像编写一堆额外的代码,但它确实有助于知道您的数据库即使由于应用程序错误也会拒绝错误的请求。您唯一真正非常小心的地方是您获得该用户 ID 的正确租户数据库用户名和密码的地方,这应该是很有可能的。

于 2010-12-03T04:54:49.140 回答