我在运行 Kafka 实例并使用具有 1000 个分区的一个主题时遇到了问题java.io.IOException: Too many open files
,因此我开始研究我的 ec2 虚拟机中的文件描述符限制。我无法理解 Centos 7 机器上打开文件的确切限制,因为以下所有命令都会产生不同的结果。命令是:
ulimit -a
:打开文件1024lsof | wc -l
:298280cat /proc/sys/fs/file-max
:758881(与 一致/proc/sys/fs/file-nr
)
如果实际限制是最后一个命令产生的限制,那么我远远低于它(lsof | wc -l
:298280)。但如果是这种情况,命令的输出ulimit
对我来说相当不清楚,因为我远远高于 1024 个打开的文件。
根据官方文档,在 Centos 中检查文件描述符的最佳方法是/proc/sys/fs/file-max
文件但是这些命令之间是否存在所有这些看似“不一致”的情况?
答案1
file-max
是整个系统可以打开的最大文件数。这是在内核级别强制执行的。手册页指出
lsof
:
如果没有任何选项,lsof 会列出属于所有活动进程的所有打开文件。
这与您的观察结果一致,因为报告的文件数量lsof
远低于file-max
设置。
- 最后,
ulimit
用于在用户级别强制实施资源限制。参数“打开文件的数量”在用户级别设置,但应用于该用户启动的每个进程。在这种情况下,单个 Kafka 进程最多可以打开 1024 个文件句柄(软限制)。
您可以自行将此限制提高到硬限制 4096。要提高硬限制,需要 root 访问权限。
如果 Kafka 作为单个进程运行,您可以使用 查找该进程打开的文件数lsof -p [PID]
。
希望这能解决问题。
答案2
这是一个常见的错误:将原始调用的结果lsof
与假定的限制进行比较。
对于全局限制 ( /proc/sys/fs/file-max
),您应该看看/proc/sys/fs/file-nr
;第一个值表示使用的内容,最后一个值是限制。
OpenFile 限制针对每个进程,但可以针对用户定义;ulimit -Hn
有关用户限制,请参阅命令并参阅/etc/security/limits.conf
定义。通常与“app user”一起应用,例如:“tomcat”:将限制设置为 65000 给用户 tomcat,该限制将应用于其运行的 java 进程。
如果您想检查对进程应用的限制,请获取其 PID,然后:
cat /proc/${PID}/limits
如果您想检查某个进程打开了多少个文件,请获取其 PID,然后:
ls -1 /proc/${PID}/fd | wc -l
(注意 ls 是“减一”,不要与“减 el”混淆)
如果您想了解 lsof 的详细信息,但只想了解那些计入限制的文件句柄,请尝试以下操作:
lsof -p ${PID} | grep -P "^(\w+\s+){3}\d+\D+"
lsof -p ${PID} -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -a
备注:“文件”是文件/管道/tcp连接/等。
请注意,有时您可能需要成为 root 用户或使用 sudo 才能获得命令的正确结果;如果没有特权,有时您不会看到错误,只会得到更少的结果。
最后,如果您想知道进程访问文件系统上的哪些文件,请查看:
lsof -p ${PID} | grep / | awk '{print $9}' | sort | uniq