• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

关于MongoDB连接数运维

MongoDB 彭东稳 6年前 (2017-03-23) 27324次浏览 已收录 0个评论

使用 MongoDB 时,可能会遇到因为 mongod 连接数用满了,导致客户端无法连接的问题。mongod 的最大连接数通过net.maxIncomingConnections指定,默认值为 1000000,相当于没有限制,生产环境强烈建议根据实际需求配置,以避免客户端误用导致 mongod 负载过高。

为什么需要限制连接数?

连接是要消耗资源的,而且消耗的并不少。mongod 的服务模型是每个网络连接由一个单独的线程来处理,每个线程配置了 1MB 的栈空间,当网络连接数太多时,过多的线程会导致上下文切换开销变大,同时内存开销也会上涨。

  • 内存:MongoDB为例,每个线程都要分配1MB的栈内存出来。1000个连接,1G内存就这么没了,甭管是否是活跃连接。
  • 文件句柄:每个连接都要打开一个文件句柄,当然从成本上讲,这个消耗相对内存是小了很多。但换个角度,文件句柄也被其他模块消耗着,比如WT存储引擎,就需要消耗大量的文件句柄。

是否真的需要这么多的链接,一般的业务场景下请求压力在1000QPS左右,按照每个请求50ms计算,最多也就需要1000/(1000/50)==50个链接即可满足需求,并且是整个系统50个链接即可。

客户端驱动如何使用?

MongoDB 各个语言的 Driver 基本都会封装包含一个 MongoClient 的对象(不同语言的 Driver 名字可能稍有不同),通常应用在使用时通过 MongoDB connection string URI 来构造一个全局的 MongoClient,然后在后续的请求中使用该全局对象来发送请求给 mongod。

通常每个 MongoClient 会包含一个连接池,默认大小为 100,也可以在构造 MongoClient 的时候通过 maxPoolSize 选项来指定。

一种典型的错误使用方式是,用户为每个请求都构造一个 MongoClient,请求结束释放 MongoClient(或根本没释放),这样做问题是请求模型从长连接变成了短连接,每次短连接都会增加『建立 tcp 连接 + MongoDB 鉴权』的开销,并且并发的请求数会受限于连接数限制,极大的影响性能;另外如果 MongoClient 忘记释放,会导致 MongoClient 连接池里连接一直保持着,最终耗光所有的可用连接。

通常 MongoClient 使用默认100的连接池(具体默认值以 Driver 的文档为准)都没问题,当访问同一个 mongod 的源比较多时,则需要合理的规划连接池大小。

举个例子,mongod 的连接数限制为 2000,应用业务上有 40 个服务进程可能同时访问这个 mongod,这时每个进程里的 MongoClient 的连接数则应该限制在 2000/40 = 50 以下 (连接复制集时,MongoClient 还要跟复制集的每个成员建立一条连接,用于监控复制集后端角色的变化情况)。

查看最大连接数

其中 available 表示空闲可用的连接数。current 表示已经占用了的连接数,两者相加就是实例的最大连接数。

但这个连接数也可以修改,只要在启动的时候加入--maxConns=2000即可。如果再次查询最大连接数发现没有增加到 2000,那么其实是 Linux 默认进程能打开最大文件数有关,可以通过 ulimit 解决。

查看实例进程信息

返回包含在数据库实例正在进行的操作信息的文档。db.currentOp()方法包装数据库命令currentOp

db.currentOp() 可以接受的过滤器文档或布尔参数。

如果将过滤器文档传递给 db.currentOp(),则输出仅返回与过滤器匹配的当前操作的信息。筛选器文档可以包含:

Field Description
"$ownOps"

布尔值。如果设置为true,则只返回当前用户的操作信息。

用户可随时操作 db.currentOp( { “$ownOps”: true } ) 来查看自己的操作。

New in version 3.2.9.

"$all"

布尔值。如果设置为true,则返回所有操作信息,包括空闲连接和系统连接的操作。

"$all": true 覆盖所有输出字段过滤。

<filter> 指定在输出字段过滤条件。见例子。

另外,下面两个操作是等价的:

currentOp 和数据库 profile 报告信息基本相同,主要包含以下所有 CRUD 操作:

结果集解释:

 

示例

下面的示例使用具有各种查询文件 db.currentOp 方法来过滤输出。

Write Operations Waiting for a Lock

下面的示例返回正在等待锁的所有写操作的信息:

Active Operations with no Yields

下面的示例返回从未取得所有活动正在运行的操作:

Active Operations on a Specific Database

下面的示例返回对数据库DB1所有的活动操作已运行3秒以上信息:

Active Indexing Operations

下面的示例返回正在创建索引操作的信息:

用JS处理结果集

杀掉进程

先执行 db.currentOp() 获取进程号,类似 ps -ef。

查看最近错误

 

<参考>

MongoDB killOp 案例详解

为什么 MongoDB 连接数被用满了?

https://docs.mongodb.com/manual/reference/command/currentOp

https://docs.mongodb.com/manual/reference/method/db.currentOp/#db.currentOp


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (1)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!