重复使用 MongoDB 连接并关闭它。

3
我在我的应用程序中使用Node原生客户端1.4,并在文档中发现了一些令人困惑的东西:
连接池是由驱动程序维护的数据库连接缓存,以便在需要新的数据库连接时可以重用连接。为减少应用程序创建的连接池数量,我们建议只调用MongoClient.connect一次并重用回调返回的数据库变量:
阅读此内容时会有几个问题:
  1. 这是否意味着db对象也维护副本集提供的故障转移功能?我认为这应该是MongoClient的工作(不确定,但C#驱动程序文档确实说MongoClient维护副本集)
  2. 如果我正在重复使用db对象,那么何时应调用db.close()函数?我在每个示例中都看到了db.close()。但是如果我们要重复使用它,不应该保持它打开吗?
编辑: 因为这是一个关于重用的主题,所以我还想知道如何在不同的函数/对象之间共享db? 随着项目的扩大,我不想将所有函数/对象嵌套在一个大的闭包中,但我也不想将其传递给所有函数/对象。 有什么更优雅的方法可以在应用程序中共享它?
1个回答

1
"连接池"的概念在数据库连接中已经存在了一段时间。实际上这是一个常识性的方法,因为考虑到每次想要发出查询时建立数据库连接是非常昂贵的,你不希望做这样的事情并增加额外的开销。
因此,一般原则是有一个对象句柄(在这种情况下是 `db` 引用),它本质上会去检查可以使用哪个“池化”的连接,并且如果当前的“池”已经完全利用,则创建另一个(或几个)连接以达到池的限制,以便服务请求。
MongoClient 类本身只是一个构造函数或“工厂”类型的类,其目的是建立连接和连接池,并返回一个句柄以供以后使用。因此,这里创建的连接实际上是由其他东西管理的,例如复制集故障转移或可能从可用实例中选择另一个路由器实例以及通常处理连接。
因此,在“长期运行”的应用程序中,该“句柄”要么是全局可用的,要么可以从实例管理器中检索,以便访问可用的连接。这避免了在代码的其他地方“建立”新连接的需要,而这已经被说明是一项昂贵的操作。"
你提到的“示例”代码通常出现在许多驱动程序实现手册中,经常或总是调用db.close。但这些只是示例,不适合长时间运行的应用程序,因此这些示例往往是“循环完成”的,它们显示了所有的“初始化”,各种方法的“使用”,最后在应用程序退出时进行“清理”。
良好的应用程序或ODM类型的实现通常会有一种设置连接、共享池并在应用程序最终退出时优雅地清理的方式。对于小脚本,你可能会像“手册页”示例一样编写代码,但对于较大的长时间运行的应用程序,你可能需要实现代码来在实际应用程序退出时“清理”你的连接。

非常感谢您提供如此详细的答案。我一直以为NodeJS驱动程序的工作方式与C#驱动程序相同,但事实证明并非如此。我正在开发一个socket.io服务器项目,我认为它是您所说的“长时间运行的应用程序”。因此,在开始监听端口之前,我会准备好db对象,并尝试在不同的请求之间共享相同的db。您所说的是我需要在某些服务器事件中进行清理,当服务器退出时,对吗?也许是server.on("close", ...) - yaoxing
另一个问题是我应该如何共享db对象?我试图避免将其传递给不同的函数/对象。但我也不想将所有函数/对象嵌套在一个闭包中。有什么建议可以更优雅地实现这一点吗? - yaoxing
@yaoxing 可以通过多种方式获得访问该实例的权限,而不仅仅是将所有代码放在“open”回调中。这本身就是一个广泛的问题,但考虑一个持有实例连接的单例类,或者深入研究Mongoose ODM代码,甚至只使用那个,即使你想要无模式,因为那里有一些技术用于共享连接句柄和池。请记住,“副本”实际上只是引用,除非您明确克隆对象。所以相当便宜。 - Neil Lunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接