FAQ
在此页面上
- 连接池在节点驱动程序中是如何工作的?
- 如何修复“MongoServerSelectionError: connect ECONNREFUSED::1:27017”错误?
- "connectTimeoutMS"、"socketTimeoutMS"和"maxTimeMS"之间有什么区别?
- 如何防止驱动程序在连接期间挂起或防止驱动程序花费太长时间尝试访问无法访问的副本集?
- 如果客户端断开连接,运行中的操作会怎样?
- 如何确认驱动程序关闭了不可用的套接字?
- 如何防止套接字在进入活动状态前超时?
- “connectTimeoutMS”和“socketTimeoutMS”的值为“0”意味着什么?
- 如何防止长时间运行操作拖慢服务器?
- “keepAlive”设置的作用是什么?
- 如果出现意外网络行为,我该怎么办?
- 如果在调用“client.connect()”时出现“ECONNRESET”,我该怎么办?
- 如何防止因运行缓慢而延误其他操作?
- 如何确保连接字符串对副本集有效?
本页包含常见问题及其相应解答。
提示
如果在本页中找不到问题答案,请参阅“问题与帮助”页面,了解下一步操作和更多资源。
连接池在节点驱动程序中是如何工作的?
对于 MongoDB 拓扑结构中的每个服务器,每个 MongoClient
实例都有一个内置连接池。连接池按需打开套接字以支持应用程序中对 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()
只能关闭不活动的套接字,因此使用此方法无法中断或终止任何正在进行的操作。只有当进程结束时,驱动程序才会关闭这些套接字。
如何修复“MongoServerSelectionError: connect ECONNREFUSED::1:27017”错误?
从版本 17 开始,Node.js 默认使用IPV6
。 您有几种方法可以解决此错误:
使用--ipv 6标志以
IPV6
模式启动mongod
,或在配置文件中将net.ipv6
选项设置为true
。使用 --ipv6 标志启动 mongodmongod --ipv6 在配置文件中设置 net.ipv6 选项net: ipv6: true 通过将
IPV4
指定为family: 4
MongoClient 的选项来 显式使用 。const client = new MongoClient(uri, { family: 4, });
"connectTimeoutMS"、"socketTimeoutMS"和"maxTimeMS"之间有什么区别?
设置 | 说明 |
---|---|
connectTimeoutMS |
提示修改 MongoClient.connect 的允许时间 要建立与 MongoDB 服务器的连接,请改用 默认值: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 = collection.find({}).maxTimeMS(50);
如何防止驱动程序在连接期间挂起或防止驱动程序花费太长时间尝试访问无法访问的副本集?
为防止驱动程序在连接期间挂起或防止驱动程序花费太长时间尝试访问无法访问的副本集,您可以设置连接选项的connectTimeoutMS
选项。 一般来说,应确保connectTimeoutMS
设置不低于副本集成员的最长网络延迟。 如果一个从节点位于地球的另一侧,并且延迟为 10,000 毫秒,则将connectTimeoutMS
设置为更低的值将阻止驱动程序连接到该节点。
如果客户端断开连接,运行中的操作会怎样?
从 MongoDB Server 4.2版本开始,如果客户端断开连接,服务器会终止聚合等正在运行的操作和查找操作。 要查看受此行为影响的操作的完整列表,请参阅MongoDB Server 4.28100} 版本发布说明 MongoDB Server。
其他操作,如写入操作,即使客户端断开连接,也会继续在 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
是一个 ,用于设置在启动connection-setting
TLS keepAlive 之前要等待的毫秒数 在 TCP 套接字上。keepAlive
选项将通过定期向 MongoDB 发送探测来保持套接字处于活动状态。 但是,这仅在操作系统支持SO_KEEPALIVE
时才有效。
警告
如果防火墙忽略或丢弃 keepAlive 数据包,这可能不起作用
如果出现意外网络行为,我该怎么办?
应用程序服务器和 MongoDB 之间存在的内部防火墙经常配置错误,并且在删除套接字连接时过于积极。
如果遇到意外的网络行为,请检查以下事项:
关闭套接字时,防火墙应发送
FIN packet
,以便驱动程序检测到套接字已关闭。防火墙应允许
keepAlive
探测器。
如果在调用“client.connect()”时出现“ECONNRESET”,我该怎么办?
在大多数操作系统中,每个连接都与一个 文件描述符 相关联 。操作系统通常对单个进程使用的文件描述符的数量设置限制。 如果连接池大小超过file descriptors
的限制,则可能会出现ECONNRESET
错误。
考虑以下操作:
1 const uri = "mongodb://localhost:27017/test?maxPoolSize=5000"; 2 // create a new MongoClient 3 const client = new MongoClient(uri); 4 5 await client.connect(err => { 6 // connection 7 });
如果此操作导致ECONNRESET
错误,则可能已达到 Node.js 进程的file descriptor
限制。 在这种情况下,您必须增加 Node.js 进程的file descriptors
数量。 在 MacOS 和 Linux 上,您可以使用 ulimit shell 命令。
ulimit -n 6000
这会将进程的最大file descriptors
数设置为 6000,从而允许 Node.js 使用大小为 5000 个套接字的池进行连接。
如何防止因运行缓慢而延误其他操作?
当您使用同一 MongoClient
实例同时运行多个 MongoDB 操作时,缓慢的操作可能会导致其他操作延迟。缓慢的操作会占用 MongoDB 的连接,从而导致其他操作需要等待,直到有其他连接空出来。
如果怀疑是缓慢的 MongoDB 操作导致了延迟,可以使用以下方法检查所有进行中操作的性能:
在部署中启用数据库分析器。 要了解更多信息,请参阅 手册中的 数据库分析器 MongoDB Server。
运行
db.currentOp()
MongoDB Shell 命令。如需了解更多信息,请参阅“服务器手册”中的 db.currentOp() 文档。启用连接池监控。如需了解更多信息,请参阅“连接池监控”。
确定哪些操作导致延迟后,请尝试提高这些操作的性能。 阅读《MongoDB 性能最佳实践指南》,了解可能的解决方案。
若在实施性能最佳实践后仍出现延迟,则可修改连接设置以增大连接池大小。连接池是指驱动程序随时进行维护的与服务器的一组连接。
要指定连接池的最大大小,可以在 MongoClient
实例的连接选项中设置 maxPoolSize
选项。maxPoolSize
的默认值为 100
。如果正在使用的服务器连接数达到 maxPoolSize
,则发送到服务器的下一个操作将暂停,直到与驱动程序的连接可用。以下代码在创建新的 MongoClient
时将 maxPoolSize
设置为 150
:
const client = new MongoClient(uri, { maxPoolSize: 150 });
提示
如需了解有关连接池化的更多信息,请参阅节点驱动程序中的连接池化如何运行?常见问题解答条目。
如何确保连接字符串对副本集有效?
传递给驱动程序的连接string必须使用副本集配置中设置的服务器的确切主机名。 给定副本集的以下配置设置,为了使副本集发现和故障转移正常工作,驱动程序应该能够访问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" } ] }
如果您无法在此找到问题的答案,请尝试问题和帮助部分中列出的论坛和支持渠道。