帮助解决难以捉摸的文件描述符泄漏问题

帮助解决难以捉摸的文件描述符泄漏问题

在过去的 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

相关内容