在过去的 6 个月里,我一直面临着一个似乎无法摆脱的问题:显然是随机的“打开的文件太多”/“无法打开 TCP/IP 套接字(24)”/“getaddrinfo:可以”我的应用程序日志中出现“t open file”错误。
我运行一个堆栈,如下所示:mariadb、postgresql、memcached、redis 和 Docker 容器内的几个基于节点的应用程序、apache with Passenger 运行 Ruby on Rails(ruby 2.5.5、Rails 6)应用程序和 sidekiq,所有这些都在 CentOS 上7 机器 (3.10.0-1127.el7.x86_64),具有 6 核和 16Gb RAM。负载平均约为 10%,在主要工作时间会有小峰值,几乎不会超过 30%。
最初我以为是另一个 Java 应用程序导致了这个问题,将其关闭后,过了一段时间后问题仍然出现。
无论我做什么,我都无法在 CLI 中重现这一点,它显然是随机发生的,机器上没有任何重大负载。
服务重新启动 1 小时后,我有以下统计数据:
打开文件总数
$ lsof | wc -l
30594
按打开文件排列的热门进程
$ lsof | awk '{print $1}' | sort | uniq -c | sort -r -n | head
8260 mysqld
4804 node
2728 Passenger
2491 container
2095 postgres
1445 dockerd
1320 processor
817 php-fpm
720 httpd
709 ruby
Mariadb 变量:
MariaDB [(none)]> Show global variables like 'open_files_limit';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| open_files_limit | 65535 |
+------------------+-------+
1 row in set (0.01 sec)
MariaDB [(none)]> Show global status like 'opened_files';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_files | 6151 |
+---------------+-------+
1 row in set (0.00 sec)
我在 sysctl.conf 中将最大打开文件数设置为 130k,认为这会解决问题,这只为我赢得了一些时间,但稍后它仍然会弹出
$ sysctl fs.file-nr
fs.file-nr = 3360 0 131070
我刚刚做了一个快速的“ab”测试,打开的文件数量并没有增加太多:
$ ab -n 1000 -c 10 http://www.example.com/
9589 mysqld
4804 node
4577 Passenger
3756 httpd
3225 postgres
2491 container
2166 utils.rb:
2080 ruby
1445 dockerd
1364 processor
这可能无关紧要,因为真正的用户不会重复访问主页。
我有预感,罪魁祸首可能是 Docker(我已经运行了更繁忙的服务器,但没有对数据库进行 docker 化),但宁愿在将数据库移出 Docker 之前调查其他可能性,因为这将是一个非常痛苦的过程。
希望得到一些指点
答案1
这是由于只有 4096 个 inotify 处理程序造成的。我增加了限制,问题就消失了。
fs.file-max = 131070
fs.inotify.max_user_watches = 65536