UNIXulimit
自托管部署的设置
大多数 UNIX 这样的操作系统(包括 Linux 和 macOS)都提供了基于每个进程和每个用户限制和控制使用系统资源(例如线程、文件和网络连接)的方法。这些“ulimit”可防止单个用户使用过多的系统资源。有时,这些限制的默认值较低,可能会在 MongoDB 正常操作过程中导致许多问题。
资源利用
mongod
和 mongos
分别使用线程和文件描述符来跟踪连接和管理内部操作。本节概述了 MongoDB 的一般资源利用模式。将这些数字与有关您的部署及其用途的实际信息相结合,以确定理想的 ulimit
设置。
一般来说,所有的 mongod
和 mongos
实例都会:
使用两个文件描述符和一个线程跟踪每个传入连接。
像系统进程那样跟踪每个内部线程或 pthread。
mongod
mongod
实例使用的每个数据文件都有 1 个文件描述符。mongod
当storage.journal.enabled
为true
时, 实例使用的每个日志文件有 1 个文件描述符。在副本集中,每个
mongod
都与副本集的所有其他节点保持连接。
mongos
除了用于客户端连接的线程和文件描述符外,mongos
还必须与所有配置服务器和所有分片(包括所有副本集的所有节点)保持连接。
对于 mongos
,请考虑以下行为:
mongos
实例维护一个与每个分片的连接池,这样mongos
就可以重复使用连接并快速完成请求,而无需创建新的连接。您可以使用
net.maxIncomingConnections
运行时选项来限制传入连接数。通过限制传入连接数,可以防止mongos
在mongod
实例上创建过多连接的级联效应。
审查和设置资源限制
ulimit
您可以在系统提示符使用 ulimit
命令检查系统限制,如下例所示:
$ ulimit -a -t: cpu time (seconds) unlimited -f: file size (blocks) unlimited -d: data seg size (kbytes) unlimited -s: stack size (kbytes) 8192 -c: core file size (blocks) 0 -m: resident set size (kbytes) unlimited -u: processes 64000 -n: file descriptors 64000 -l: locked-in-memory size (kb) unlimited -v: address space (kb) unlimited -x: file locks unlimited -i: pending signals 192276 -q: bytes in POSIX msg queues 819200 -e: max nice 30 -r: max rt priority 65 -N 15: unlimited
ulimit
是指每个用户在各种资源方面的限制。因此,如果您的 mongod
实例以同时运行多个进程或多个 mongod
进程的用户身份执行,则可能会出现对这些资源的争用。另外,请注意 processes
值(即-u
)是指不同进程和子进程线程的总数量。
在 Linux 上,您可以通过发出以下形式的命令来更改 ulimit
设置:
ulimit -n <value>
ulimit
有“硬”限制和“软”限制两种,它们都会影响 MongoDB 的性能。“硬”ulimit
是指用户在任何时间都可以拥有的最大活动进程数。这是上限:任何非 root 进程都无法提高“硬”ulimit
。相反,“软”ulimit
是实际强制执行的会话或进程限制,但任何进程都可以将其提高,直到达到“硬”ulimit
允许的最大值。
如果连接数增长过高,较低的“软”ulimit
可能会导致 can't create new thread,
closing connection
错误。因此,请务必将这两种 ulimit
值均设置为推荐值。
ulimit
将同时修改“硬”和“软”值,除非在修改限制值时指定了 -H
或 -S
修饰符。
对于许多 Linux 发行版,您可以通过将 -n
选项替换为 ulimit
-a
输出中任何可能的值来更改值。
更改 ulimit
设置后,您必须重新启动该进程才能使用修改后的设置。在 Linux 上,您可以使用 /proc
文件系统来查看正在运行的进程的当前限制。
使用 ulimit
对系统限制所做的任何更改都可能会在系统重新启动后恢复,取决于您的系统配置和默认设置。检查您的发行版和操作系统文档,了解更多信息。
您通常应该使用 systemctl
启动 mongod
,其中使用了 ulimit
设置:
systemctl start mongod.service
如果不使用 systemctl
启动 mongod
,systemd
将会覆盖一些 ulimit
设置。例如,如果按以下命令中的方式启动 mongod
,则会使用用户切片(例如 user-1000.slice
)systemd
设置:
mongod --config ~/mongod.conf
注意
systemd
用户切片限制了用户进程的资源。
macOS
对于使用brew 安装方法安装了 MongoDB Community 的 macOS 系统,当您通过brew services
启动 MongoDB 时,会自动设置推荐的打开文件值。 有关更多信息,请参阅使用 brew 运行 MongoDB 。
对于运行 MongoDb 企业或使用 TGZ 安装方法的 macOS 系统,请使用 launchctl limit
命令设置 推荐值。请参阅操作系统文档,了解在正在运行的系统上更改系统限制的详细过程。
Red Hat Linux Enterprise Server 和 CentOS
Red Hat Enterprise Linux 以及 CentOS 6 和 7 强制实施单独的最大进程限制 nproc
,该限制会覆盖 ulimit
设置。该值在以下配置文件中定义,具体取决于版本:
版本 | 值 | file |
---|---|---|
RHEL / CentOS 7 | 4096 | /etc/security/limits.d/20-nproc.conf |
RHEL / CentOS 6 | 1024 | /etc/security/limits.d/90-nproc.conf |
要为这些版本配置 nproc
值,请创建一个名为 /etc/security/limits.d/99-mongodb-nproc.conf
的文件,并使用新的 soft nproc
和 hard nproc
值来提高进程限制。有关推荐的值,请参阅建议的 ulimit
设置。
对于 RHEL/CentOS 8,不再需要单独设置 nproc
值。在 RHEL/CentOS 8 上,ulimit
命令足以配置所需的最大进程数。
推荐的ulimit
设置
每个部署都可能有独特的要求和设置,但以下阈值和设置对 mongod
和 mongos
部署尤为重要:
-f
(文件大小):unlimited
-t
(CPU 时间):unlimited
-v
(虚拟内存):unlimited
[1]-l
(锁定内存大小):unlimited
-n
(打开文件):64000
-u
(进程/线程):64000
请谨记,更改 ulimit
设置后,务必要重启 mongod
和 mongos
实例,以确保更改生效。
Considerations
使用 Upstart 的 Linux 发行版
对于使用 Upstart 的 Linux 发行版,如果您将 mongod
和/或 mongos
实例作为 Upstart 服务启动,则可以在服务脚本内指定限制。可以使用 limit
节段执行此操作。
指定推荐的 ulimit
设置,如下例所示:
limit fsize unlimited unlimited # (file size) limit cpu unlimited unlimited # (cpu time) limit as unlimited unlimited # (virtual memory size) limit memlock unlimited unlimited # (locked-in-memory size) limit nofile 64000 64000 # (open files) limit nproc 64000 64000 # (processes/threads)
每个 limit
节段将“软”限制设置为指定的第一个值,并将“硬”限制设置为指定的第二个值。
更改 limit
节段后,请使用以下方法重新启动应用程序服务,以确保更改生效:
restart <service name>
使用 的 Linux 发行版 systemd
如果您将 mongod
和/或 mongos
实例作为 systemd
服务启动,则可以在其服务文件的 [Service]
部分中指定限制。服务文件位于类似 /etc/systemd/system/<process-name>.service
的位置。
您可以使用资源限制指令来设置限制。
指定推荐的 ulimit
设置,如下例所示:
[Service] # Other directives omitted # (file size) LimitFSIZE=infinity # (cpu time) LimitCPU=infinity # (virtual memory size) LimitAS=infinity # (locked-in-memory size) LimitMEMLOCK=infinity # (open files) LimitNOFILE=64000 # (processes/threads) LimitNPROC=64000
每个 systemd
限制指令都会将“硬”和“软”限制均设置为指定值。
更改 limit
节段后,请使用以下方法重新启动应用程序服务,以确保更改生效:
systemctl restart <service name>
注意
如果是通过软件包管理器(例如 yum
或 apt
)安装的 MongoDB,则自动安装的服务文件中已包含这些 ulimit 值。
/proc
文件系统
注意
本节仅适用于 Linux 操作系统。
/proc
文件系统将每个进程的限制存储在位于 /proc/<pid>/limits
的文件系统对象中,其中 <pid>
为进程的 PID,即进程标识符。您可以使用以下 bash
函数返回具有给定名称的一个或多个进程的 limits
对象的内容:
return-limits(){ for process in $@; do process_pids=`ps -C $process -o pid --no-headers | cut -d " " -f 2` if [ -z $@ ]; then echo "[no $process running]" else for pid in $process_pids; do echo "[$process #$pid -- limits]" cat /proc/$pid/limits done fi done }
您可以复制此函数并粘贴到当前 shell 会话中,或将其作为脚本的一部分加载。通过以下任一调用方式来调用该函数:
return-limits mongod return-limits mongos return-limits mongod mongos
[1] | (1、2) 如果在运行 MongoDB 的系统上限制虚拟内存或常驻内存大小,操作系统将会拒绝满足额外的分配请求。 |
[2] | ulimit 的 -m 参数对内核版本高于 2.4.30 的 Linux 系统不起作用。如果您愿意,可以省略 -m 。 |