今天是小雪。魔都阳光明媚。
最近手上处理了几个诡异的问题,这里简单记录一下。
“Too many open files” 🔗
售前同事说,某客户的环境里,出现了 “Too many open files”. 一般来说,这种问题都比较简单。用 lsof
查看一下,基本上就水落石出了。不过,这个不一样。
首先,lsof -p pid
的输出中,有大量类型为 sock
,名字显示为prococol: TCP
的记录。类似:
...
python 49720 appuser *665u sock 0,6 0t0 1104529642 protocol: TCP
python 49720 appuser *666u sock 0,6 0t0 1104529643 protocol: TCP
...
其中,/proc/497200/fd/666
指向 socket:[1104529642]
,但进一步搜索grep 19164451 /proc/net/tcp
则又一无所获。
ss -a
只有区区数百条记录。netstat -tunap
和 lsof -i -a -p pid
也类似。
查看了 lsof
的手册,获得如下信息:
TYPE is the type of the node associated with the file
...
or ``IPv4'' for an IPv4 socket;
or ``sock'' for a socket of unknown domain;
or ``unix'' for a UNIX domain socket;
...
邮件列表搜到一个类似的贴子 ,另外 AskUbuntu 上有个解释:
The can't identify protocol is probably a connection that hasn't
been fully set up yet. ... 399u indicates that the fd is numbered
339 and has both read and write access (u).
看起来,是有 socket 没有关闭。因为代码里没有直接操作 socket,因此找了一下相关的库。果然有个“疑犯”,尴尬的是本地不能重现。也从未有别的客户碰到过。成了孤例。
Too many open files … again 🔗
这回不是来自我们的 agent,而是数据库。
最初的现象是管控程序所有的线程都等在了数据库操作。负载很低。systemctl status mariadb
看数据库的状态,很健康。看数据库的日志,妈呀,Too many open files
.
同事很早就把 max_connections
设置为了 1024,然而,数据库运行时并没有给到 1024,而是 214。但是管控的配置是 250,因此就悲剧了。
从某个日本网友的博文
那里学习了 max_connections
, open_files_limit
以及table_open_cache
之间的关系。
open_files_limit 🔗
该值受一下数值影响:
- 10 + max_connections + table_open_cache * 2
- max_connections * 5
- my.cnf 里指定的 open_files_limit
- limits 决定的 RLIMIT_NOFILE
MySQL 5.6/5.7 据说是取上面的最大值,MariaDB 5.5 实测下来是 limits 决定的值。
max_connections 🔗
如果 max_connections
大于open_files_limit - 810
,则为open_files_limit - 810
的值。
因此,默认环境下,open_files_limit = 1024
,此时,max_connections = 214
.
table_open_cache 🔗
取值为 max (400, (open_files_limit - 10 - max_connections)/2)
最后,发现一个贴心的网站可以用来计算 MySQL/MariaDB 的内存消耗。
流水账 🔗
今天傍晚跑了6公里,黄色的月亮在地平线上方20度左右,很漂亮。