常见问题
本页内容
- 为什么我在连接到 MongoDB 时会出错?
- 连接池在 Node 驱动中是如何工作的?
- "connectTimeoutMS"、"socketTimeoutMS" 和 "maxTimeMS" 之间的区别是什么?
- 如果客户端断开连接,正在运行的操作会发生什么?
- 我如何确认驱动已关闭不可用的套接字?
- 我如何防止套接字在激活之前超时?
- "connectTimeoutMS" 和 "socketTimeoutMS" 的 "0" 值代表什么?
- 我如何防止长时间运行的操作减慢服务器速度?
- keepAlive 选项的作用是什么?
- 如果我遇到意外的网络行为,我该怎么办?
- 我如何防止缓慢的操作延迟其他操作?
- 我如何确保我的连接字符串对副本集有效?
本页包含常见问题和相应的答案。
提示
如果您在本页上找不到问题的答案,请参阅问题 & 帮助 页面,以获取下一步操作和更多资源。
为什么我在连接MongoDB时会出现错误?
如果您连接MongoDB部署遇到问题,请参阅连接故障排除指南以获取可能的解决方案。
节点驱动程序中的连接池是如何工作的?
每个MongoClient
实例为其MongoDB拓扑中的每个服务器都有一个内置连接池。连接池在需要时打开套接字,以支持应用程序中对MongoDB的并发请求。
每个连接池的最大大小由maxPoolSize
选项设置,默认值为100
。如果对服务器的使用中连接数达到maxPoolSize
的值,则对该服务器的下一个请求将等待,直到有连接可用。
除了支持应用程序请求所需的套接字之外,每个MongoClient
实例还为您的MongoDB拓扑中的每个服务器再打开两个套接字,用于监控服务器状态。例如,连接到三个节点副本集的客户端将打开六个监控套接字。如果应用程序使用maxPoolSize
的默认设置并且仅查询主节点(默认),则连接池中最多可以有106
个总连接。如果应用程序使用读取偏好来查询从节点,那些连接池将增长,并且可以有306
个总连接。
为了在一个进程中支持高并发MongoDB请求,您可以增加maxPoolSize
。
连接池是速率限制的。选项maxConnecting
决定了连接池在任何时候可以并行创建的连接数。例如,如果maxConnecting
的值为2
,则尝试并发检查第三个连接时,只有在以下情况之一发生时才会成功:
连接池完成创建连接,并且连接池中的连接数少于
maxPoolSize
。现有连接被检查回连接池。
由于连接创建的速率限制,驱动器重用现有连接的能力得到了提高。
您可以使用minPoolSize
选项设置每个服务器并发连接的最小数量,默认值为0
。驱动器使用此数量初始化连接池。如果套接字关闭,导致套接字总数(正在使用和空闲的)低于最小值,则打开更多套接字,直到达到最小值。
您可以通过设置maxIdleTimeMS
选项来设置连接在连接池中保持空闲的最大毫秒数。一旦连接空闲了maxIdleTimeMS
,连接池会将其移除并替换。此选项默认值为0
(无限制)。
以下MongoClient
的默认配置适用于大多数应用程序
const client = new MongoClient("<connection string>");
MongoClient
支持多个并发请求。对于每个进程,创建一个客户端并在此进程的所有操作中使用它。这种方法比为每个请求创建客户端更有效。
驱动器不会限制等待套接字变为可用的请求数量,应用程序需要负责将其池的大小限制在负载峰值期间的排队大小。请求将等待在waitQueueTimeoutMS
选项中指定的时长,该选项默认为0
(无限制)。
等待时间超过waitQueueTimeoutMS
定义的长度的请求将引发连接错误。如果将限制负载峰值期间操作持续时间的重要性置于完成每个操作之上,则可以使用此选项。
当任何请求调用MongoClient.close()
时,驱动器将关闭所有空闲套接字,并在它们返回到连接池时关闭所有正在使用的套接字。调用MongoClient.close()
只会关闭不活跃的套接字,并不会直接终止任何正在进行的操作。驱动器仅在相关操作完成时关闭任何正在使用的套接字。然而,MongoClient.close()
方法会关闭现有的会话和事务,这可能会间接影响正在进行的操作和打开的光标的行为。
"connectTimeoutMS"、"socketTimeoutMS"和"maxTimeMS"之间的区别是什么?
设置 | 描述 |
---|---|
connectTimeoutMS |
默认值 30000 |
socketTimeoutMS | socketTimeoutMS 指定驱动程序在关闭之前等待不活跃套接字的时间量。默认值是永不超时套接字。此选项仅适用于已建立的套接字。 |
maxTimeMS | maxTimeMS 指定服务器在操作达到服务器后等待操作完成的最大时间。如果操作超过指定的时间限制,则返回超时错误。您可以将 maxTimeMS 仅传递给单个操作或游标。 |
要指定您的 MongoClient
的可选设置,请在构造函数的 options
对象中声明一个或多个可用设置,如下所示
const client = new MongoClient(uri, { connectTimeoutMS: <integer value>, socketTimeoutMS: <integer value> });
要查看所有可用设置,请参阅MongoClientOptions API 文档。
要指定 maxTimeMS
,将 maxTimeMS()
方法与超时指定链接到一个返回 Cursor
的操作。
const cursor = myColl.find({}).maxTimeMS(50);
客户端断开连接时,正在运行的操作会发生什么?
从 MongoDB 服务器版本 4.2 开始,如果客户端断开连接,服务器将终止运行中的操作,如聚合操作和查找操作。要查看受此行为影响的所有操作的完整列表,请参阅服务器手册中的服务器版本 4.2 发行说明。
其他操作,如写入操作,即使客户端断开连接,在 MongoDB 服务器上也会继续运行。如果您的应用程序在客户端断开连接后重试操作,这种行为可能会导致数据不一致。
如何确认驱动程序已关闭不可用的套接字?
如果您遇到意外的网络行为或MongoDB进程失败并显示错误,您可能不会收到驱动程序正确关闭相应套接字的确认。
要确保在这些情况下驱动程序正确关闭套接字,请设置socketTimeoutMS
选项。当MongoDB进程超时时,驱动程序将关闭套接字。我们建议您为socketTimeoutMS
选择一个值,该值是您的应用程序执行的最慢操作预期持续时间的两到三倍。
如何防止套接字在激活之前超时?
拥有大量的连接池并不总是能减少重连请求。考虑以下示例
一个应用程序的连接池大小为5个套接字,并且将socketTimeoutMS
选项设置为5000毫秒。操作平均每3000毫秒发生一次,重连请求频繁。每个套接字在5000毫秒后超时,这意味着在那些5000毫秒内,所有套接字都必须做些事情以避免关闭。
每3000毫秒一条消息不足以保持套接字活跃,所以几个套接字将在5000毫秒后超时。为了避免过多的套接字超时,通过指定maxPoolSize
选项来减少驱动程序在连接池中可以维护的连接数。
要为您的MongoClient
指定可选的maxPoolSize
设置,在构造函数的options
对象中声明,如下所示
const client = new MongoClient(uri, { maxPoolSize: <integer value>, });
“connectTimeoutMS”和“socketTimeoutMS”的值设为“0”意味着什么?
如果您将connectTimeoutMS
或socketTimeoutMS
的值设为0
,则您的应用程序将使用操作系统的默认套接字超时值。
我该如何防止长时间运行的操作降低服务器性能?
您可以通过指定超时值来防止长时间运行的操作降低服务器性能。您可以将maxTimeMS()
方法链式调用到一个返回Cursor
的操作上,为特定动作设置超时。
以下示例展示了如何将maxTimeMS()
方法链式调用到一个返回Cursor
的操作上
// Execute a find command await collection .find({ $where: "sleep(100) || true" }) .maxTimeMS(50);
keepAlive选项的作用是什么?
《keepAlive》连接选项指定是否在TCP套接字上启用传输控制协议(TCP)保活。如果启用保活,驱动程序会通过向MongoDB部署发送周期性的ping来检查连接是否活跃。此功能仅在操作系统支持SO_KEEPALIVE
套接字选项的情况下有效。
《keepAliveInitialDelay》选项指定驱动程序在启动保活之前等待的毫秒数。
5.3版本驱动程序已弃用这些选项。从驱动程序版本6.0开始,keepAlive
选项永久设置为true
,而keepAliveInitialDelay
设置为300000毫秒(300秒)。
警告
如果您的防火墙忽略或丢弃保活消息,您可能无法识别已丢失的连接。
如果遇到意外的网络行为,我该怎么办?
如果您的应用程序和MongoDB之间的防火墙配置不正确,您可能会遇到意外的网络行为。这些防火墙可能在删除连接方面过于激进,从而导致意外错误。
请确认您的防火墙表现出以下行为
防火墙在关闭连接时发送一个
FIN
数据包,通知驱动程序套接字已关闭。防火墙允许保活消息。
提示
要了解更多关于keepalive消息的信息,请参阅keepAlive选项的作用是什么? 常见问题解答条目。
如何防止慢速操作延迟其他操作?
当您使用相同的MongoClient
实例并发运行多个MongoDB操作时,慢速操作可能会延迟其他操作。慢速操作会占用与MongoDB的连接,这会导致其他操作等待直到有额外的连接可用。
如果您怀疑慢速的MongoDB操作导致了延迟,您可以使用以下方法检查所有正在进行的操作的性能
在您的部署上启用数据库分析器。有关更多信息,请参阅服务器手册中的数据库分析器。
运行
db.currentOp()
MongoDB Shell命令。有关更多信息,请参阅服务器手册中的db.currentOp()文档。启用连接池监控。有关更多信息,请参阅连接池监控。
确定哪些操作导致延迟后,尝试提高这些操作的性能。阅读MongoDB性能最佳实践指南以获取可能的解决方案。
如果您实施了性能最佳实践但仍遇到延迟,您可以通过修改连接设置来增加连接池的大小。连接池是在任何时间点由驱动程序维护到服务器的一组连接。
要指定连接池的最大大小,您可以在您的MongoClient
实例的连接选项中设置maxPoolSize
选项。默认值是100
。如果到服务器的已使用连接数达到maxPoolSize
,则发送到服务器的下一个操作将暂停,直到有可用的连接到驱动程序。以下代码在创建新的MongoClient
时将maxPoolSize
设置为150
。
const client = new MongoClient(uri, { maxPoolSize: 150 });
提示
要了解更多关于连接池的信息,请参阅Node驱动程序中的连接池是如何工作的?常见问题解答条目。
如何确保我的连接字符串对副本集有效?
传递给驱动程序的连接字符串必须使用与 副本集配置 中设置完全一致的服务器主机名。假设您已经为副本集设置了以下配置,为了使副本集发现和 故障转移 正常工作,驱动程序必须能够访问 server1
、server2
和 server3
。
{ "_id": "testSet", "version": 1, "protocolVersion": 1, "members": [ { "_id": 1, "host": "server1:31000" }, { "_id": 2, "host": "server2:31001" }, { "_id": 3, "host": "server3:31002" } ] }
如果您在这里找不到您问题的答案,请尝试我们在 问题和帮助 部分列出的论坛和支持渠道。