【问题标题】:Mongoose create connection for multi-tenancy support in node.jsMongoose 在 node.js 中为多租户支持创建连接
【发布时间】:2014-10-22 11:44:01
【问题描述】:

我正在研究一种使用 node.js + mongoose 和 mongodb 实现多数据库以支持多租户的好方法。

我发现 mongoose 支持一种名为 createConnection() 的方法,我想知道使用它的最佳实践。实际上,我将所有这些连接存储在一个数组中,由租户分隔。应该是这样的:

var connections = [
   { tenant: 'TenantA', connection: mongoose.createConnection('tenant-a') },
   { tenant: 'TenantB', connection: mongoose.createConnection('tenant-b') }
];

假设用户向租户发送他将通过请求标头登录的租户,我在 express 中非常早期的中间件中获得了它。

app.use(function (req, res, next) {
    req.mongoConnection = connections.find({tenant: req.get('tenant')});
});

问题是,是否可以静态存储这些连接,或者更好的做法是在每次发出请求时创建该连接?

编辑 2014-09-09 - 有关软件要求的更多信息

起初我们将拥有大约 3 个租户,但我们的计划是在一两年内将这个数字增加到 40 个。读操作比写操作多,它基本上是一个带有机器学习的大数据系统。它不是免费增值软件。由于历史数据量很大,数据库非常大,但是将非常旧的数据移动到另一个位置不是问题(我们已经考虑过)。如果我们的数据库机器上的可用资源用完,我们计划稍后对其进行分片,我们还可以将不同机器上的一些租户分开。

最让我感兴趣的是,有些人说为多租户添加前缀集合不是一个好主意,但原因很短。

https://docs.compose.io/use-cases/multi-tenant.html

http://themongodba.wordpress.com/2014/04/20/building-fast-scalable-multi-tenant-apps-with-mongodb/

【问题讨论】:

  • 始终创建和销毁连接的成本很高 - 您是否在数据库中使用身份验证?还是仅在您的应用程序中?每个租户是在一个单独的实例中,“db”,单独的“collection”还是......?即连接有何不同?
  • 嘿,谢谢回复。身份验证发生在应用程序级别,但它检查 mongo 集合(用户)。这个想法是为每个租户都有一个数据库(在网络上进行了一些研究之后,人们说要避免收集前缀,但他们没有说为什么......)。我们还不知道租户之间会有什么不同,也许在未来的某个时候,但我希望它像不同的索引一样为它做好准备。

标签: node.js mongodb mongoose multi-tenant


【解决方案1】:

我不建议手动创建和管理这些单独的连接。我不知道您的多租户要求的详细信息(租户数量、数据库大小、预期的交易数量等),但我认为使用 Mongoose's useDb function 之类的东西会更好。然后 Mongoose 就可以处理所有的连接池细节了。

更新

我要探索的第一个方向是在单独的节点进程上设置每个租户。在单独的节点进程中运行租户有一些有趣的好处。从安全角度(隔离内存)和稳定性角度(一个租户进程崩溃不会影响其他人),这是有意义的。

假设您基于 URL 的租赁,您将在实际租户服务器之前设置一个代理服务器。它的工作是查看 URL 并根据该信息路由到正确的进程。这是一个非常简单的node http proxy 设置。每个租户实例可以是完全相同的代码库,但使用不同的配置启动(告诉他们使用什么 mongo 连接字符串)。

这意味着您可以设计您的实际应用程序,就好像它不是多租户一样。每个进程只知道一个mongo数据库,不需要多租户逻辑。它还使您能够在以后根据负载轻松拆分流量。如果出于性能原因需要拆分租户,您可以在代理级别透明地执行此操作。 DNS 可以保持不变,您只需在后台移动实例所在的服务器即可。您甚至可以让代理在多个服务器之间平衡对租户的请求。

【讨论】:

  • 我已编辑问题以提供有关要求的更多详细信息。至于 useDb 函数,我认为当并发请求到达服务器并更改数据库时请求仍在运行时可能很危险。如果第一个请求还有任何操作,它可能会对错误的租户进行更改。那正确吗 ?谢谢!
  • useDb 返回另一个要操作的数据库对象。它不会更改现有的数据库对象,因此不会对错误的数据库应用任何运行中的操作。
  • 租户之间的负载是否相当一致,或者您是否希望某些租户具有更高的使用/数据要求?
  • 以上更新。我倾向于将租户逻辑推送到代理服务器,并设计应用程序本身,就好像它只有一个数据库可供使用。
  • @TimothyStrimple 我喜欢你的想法,我愿意接受它。请你举个例子。还有菜鸟问题,我可以以编程方式创建目标吗?如果是这样,如果目标信息存储在数据库中,我将如何做到这一点?谢谢
猜你喜欢
  • 2015-09-11
  • 1970-01-01
  • 2018-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多