多租户 MongoDB + mongo 原生驱动 + 连接池

Ana*_*ran 5 connection-pooling multi-tenant mongodb node.js node-mongodb-native

我们正在尝试使用 nodejs/mongo-native 驱动程序来实施以下演示文稿(幻灯片 13-18)中概述的策略。

https://www.slideshare.net/mongodb/secure-mongodb-to-serve-an-awsbased-multitenant-securityfanatic-saas-application

总之:

  • 创建从node.js到mongodb的连接池。
  • 对于每个对租户的请求,从池中获取一个连接并对其进行“身份验证”。使用经过身份验证的连接来服务请求。响应后,将连接返回到池中。

我能够使用 mongo-native 驱动程序创建到 mongodb 的连接池,而无需指定任何数据库,如下所示:

const client = new MongoClient('mongodb://localhost:27017', { useNewUrlParser: true, poolSize: 10 });

但是,为了获取 db 对象,我需要执行以下操作:

const db = client.db(dbName);

这是我想要验证连接的地方,AFAICS,此功能已从更新的 mongo 驱动程序、node.js 和 java 中弃用/删除。

从演示来看,旧版本的 Java 驱动程序似乎可以做到这一点。

我是否可以使用单个连接池并使用相同的连接对各个数据库的租户进行身份验证?

我们的替代方案是为每个租户提供一个连接池,目前这对我们没有吸引力。

任何帮助将不胜感激,包括此功能被弃用/删除的原因。

小智 6

幻灯片里的我就是我!!:) 我记得那次会议,很有趣。

是的,这不再起作用了,他们在我们实现这个出色的功能 6 个月后就取消了它,当时我们已经在 Beta 版中推出了它。我们必须改变我们的工作方式..

遗憾的是,直到今天,在 Mongo 中,“连接”(网络内容、SSL、集群识别)和身份验证是两个独立的操作。想想当您运行 mongo shell 时,您提供主机、端口、副本集(如果有)以及您的连接!但没有经过认证。然后,您可以向 user1 进行身份验证,执行一些操作,然后向 user2 进行身份验证,并执行只有 user2 可以执行的操作。这是在同一个连接上完成的!无需再次创建通道、SSL 握手等开销...

当时,驱动程序让我们拥有一个“空白”连接的连接池,我们可以在当前执行线程的上下文中随意向当前租户进行身份验证。

然后他们弃用了这个功能,我认为是 Mongo 2.4 中的。现在,它们仅支持在创建时进行身份验证的连接。我们询问企业支持,他们没有说明原因,但对我来说,他们发现这种方式不安全,“旧”身份验证可能会泄漏,停留在“不那么空白”的可重用连接上。

我们对多租户基础设施实现进行了更改,从大型空白连接池更改为许多(小型)经过身份验证的连接池,每个租户一个池。每个租户的这些池可能非常小,例如 3 或 5 个连接。该解决方案可以很好地扩展到数百个租户,但为了满足数千个租户,我们必须进行各种优化以根据需要创建池、在空闲时间后关闭池、为非活动或休眠租户进行惰性创建等。这允许我们仍在研究解决方案和优化。

您始终可以返回到有权访问多个数据库的 Mongo 用户的经过身份验证的连接的全局池。是的,您可以在同一经过身份验证的连接上切换数据库。你只是无法切换身份验证。这是一个纯 Mongo Java 驱动程序的示例,我们使用 Spring 提供类似的功能:

MongoClient mongoClient = new MongoClient();
DB cust1db = mongoClient.getDB("cust1");
cust1db.get...
DB cust2db = mongoClient.getDB("cust2");
cust2db.get...
Run Code Online (Sandbox Code Playgroud)

有点相关的是,我建议查看 MongoDB 静态加密,这是一项企业功能。根据不同的密钥加密每个数据库(每个客户)的唯一方法。