[原创] 项目 watch EMFILE 报错处理过程
事件
公司XX游戏 S114服启动失败(使用 pomelo - node.js 框架的项目), 提示 : Caught exception: Error: watch EMFILE
处理过程
-
怀疑是 "单进程可打开的最大文件句柄数" 受限
# 查看单个任务最多可同时打开的文件数 ulimit -n # 65535查看各进程打开的文件句柄数
lsof -n|awk '{print $3}'|sort|uniq -c|sort -nr输出结果:
228 18942 # mysqld 125 1450 89 29749 # 以下皆是游戏进程 77 23603 73 29183 71 6912 71 31880 71 28674 71 28059 71 27888 70 6899 70 3212 70 31866 70 3083 70 29741 ...当前服务器已经启动多个项目实例, 唯独在启动当前这个新的实例时才报错。上面的输出结果显示, 游戏的每个进程打开的文件句柄数也才 80 左右,不可能达到上限。
-
inotify 限制?
查看当前inotify限制:
[root@vm10-140-85-116 ~]# sysctl -a | grep fs.inotify fs.inotify.max_user_instances = 128 fs.inotify.max_user_watches = 8192 fs.inotify.max_queued_events = 16384百度了一下,项目使用 pomelo,”reloadHandlers会监听handler文件的修改,导致了这个fs.watch这个问题“
inotify 是linux的文件系统时间监控机制。
在/proc/sys/fs/inotify目录下有三个文件,对inotify机制有一定的限制
- max_user_watches:设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
- max_user_instances:设置每个用户可以运行的inotifywait或inotifywatch命令的进程数
- max_queued_events:设置inotify实例事件(event)队列可容纳的事件数量。
尝试临时修改该参数配置:
echo 256 > /proc/sys/fs/inotify/max_user_instances再次启动游戏服务端, OJBK 了, 确认没问题, 将上述修改的参数持久化(不然重启一下服务器又得重设)
echo "fs.inotify.max_user_instance=256" >> /etc/sysctl.conf
总结
这个问题在于, 开启过多的 pomelo 实例,导致用户(pomelo进程所属)运行的 inotify 命令数超过默认的阀值,而非单个pomelo进程打开的文件句柄数超过限制。
参考资料
小知识点
单进程文件句柄限制
Linux 是有文件句柄限制的, 默认不高, 一般是 1024。作为生产环境的话很容易超出这个数值,因此大多数时候都需要调高该限制数。
文件句柄数限制是针对:
- 针对单个进程的限制
- 修改该值时不影响当前运行中的程序
查看当前句柄数限制: ulimit -n
-
临时修改句柄数限制 (仅当前Session有效):
ulimit -n 65535此处设置文件句柄数限制为 65535
-
写入配置文件 (永久生效)
vim /etc/security/limits.conf
末尾追加/修改* hard nofile 65535 * soft nofile 65535hard 是硬限制,即实际限制 ;soft 是软限制,即warning
分析句柄数
(1)统计各进程打开句柄数:lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr
(2)统计各用户打开句柄数:lsof -n|awk '{print $3}'|sort|uniq -c|sort -nr
(3)统计各命令打开句柄数:lsof -n|awk '{print $1}'|sort|uniq -c|sort -nr
系统总文件句柄限制
除了对单进程可打开的文件句柄数量限制外, linux还会对系统级别的能够打开的文件句柄的数量进行限制, 即是对整个系统的限制, 而非针对单用户或单进程.
查看当前系统级别能够打开的文件句柄数量:
cat /proc/sys/fs/file-max # 794168 Centos7 的默认值
系统级打开最大文件句柄的数量永久生效的修改方法:
/etc/sysctl.conf文件末尾追加fs.file-max = 2000000- 执行
sysctl -p,使修改配置立即生效
sysctl命令用于运行时配置内核参数,这些参数位于/proc/sys目录下
-w 临时改变某个指定参数的值
-p 从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf中加载
查看系统已分配句柄数: cat /proc/sys/fs/file-nr
已分配文件句柄的数目, 已分配但未使用的文件句柄的数目, 文件句柄的最大数目
对于服务器,一般修改进程级的最大打开文件句柄数即可(系统默认1024,有点小)。一般不需要调整系统级的最大数。
如果出现了达到系统级别最大限制时,也需要同步调整系统级的最大数的。
inotify 文件系统事件监控
inotify 是linux的文件系统时间监控机制。
在/proc/sys/fs/inotify目录下有三个文件,对inotify机制有一定的限制
- max_user_watches:设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
- max_user_instances:设置每个用户可以运行的inotifywait或inotifywatch命令的进程数
- max_queued_events:设置inotify实例事件(event)队列可容纳的事件数量。
如出现 "too many open files" 提示, 记得来确认下是否是该参数配置问题
临时修改该参数配置:
echo 256 > /proc/sys/fs/inotify/max_user_instances
参数持久化
echo "fs.inotify.max_user_instance=256" >> /etc/sysctl.conf
sysctl -p

浙公网安备 33010602011771号