日志中出现Too many open files问题的原因及解决

这个问题经常在Linux上出现,而且常见于高并发访问文件系统、多线程网络连接等场景。之所以出现这个问题,大多数情况是你的程序没有正常关闭一些资源引起的。
在Linux系统中,目录、字符设备、块设备、套接字、打印机等都被抽象成了文件,即通常所说的“一切皆文件”。程序操作这些文件时,系统就需要记录每个当前访问file的name、location、access authority等相关信息,这样一个实体被称为file entry。这些实体被记录在open files table中,Linux系统配置了open files table中能容纳多少file entry。如果超过这个配置值,则Linux就会拒绝其他文件操作的请求,并抛出Too many open files。
解决这个问题可以从两方面着手,一是可以修改系统的配置信息;另外一个是从你的程序层面解决。

修改系统配置

根据应用权限,又可以分为系统级和用户级。系统级的修改会对所有用户有效,而用户级只限制每个登录用户的可连接文件数。

系统级

通过命令来查看fs.file-max的配置数量

cat /proc/sys/fs/file-max

或者

sysctl -a
  • 改动可以分为临时改动和永久改动,
  1. 临时改动直接可用
    sysctl -w [变量名]=[值]来解决。例如:
synctl -w fs.file-max=4096
  1. 永久改动就需要修改/etc/sysctl.conf文件
    如果文件中没有fs.file-max属性,则添加。设置完成后,使用sysctl -p来加载系统参数,在不指定文件位置的情况下,默认会从/etc/sysctl.conf文件中加载。

用户级

直接通过命令ulimit -n 设置的数量进行配置,例如:

ulimit -n 2048。

修改代码

上面那种方法在你的代码没有问题的情况下,可能能解决问题。但是如果是你的程序的原因,则很难有效的解决问题。所以出现这个问题,应该首先检查的你程序,是不是打开的文件或socket没有正常关闭。
命令可以查看你进程打开的文件,进程打开的端口(TCP、UDP)。由于该命令需要访问核心内存和各种文件,所以需要root用户才能执行。lsof -c 进程名列出指定进程所打开的文件或者lsof -p 进程号列出指定进程号所打开的文件。

lsof -c PID

例如Go程序中忘记文件流的关闭、解锁一个加锁的资源、关闭数据库链接等。都会造成open too many files的问题,尤其是在高并发的情况下。所以比较好的习惯就是在进行以上资源操作时,紧跟着使用defer语句。它可以用来推迟执行某个语句或函数到任意位置执行return语句之后。

上一篇:php入门到精通精典案例教程


下一篇:Why transformer?(三)