使用Python出现Too many open files的问题解决方法

将Python部署到服务上运行一段时间之后,总是会报下面的错误:

[Errno 24] Too many open files

增加文件描述符的限制

通常这个错误是因为系统达到了文件描述符的限制,可以使用ulimit -a命令进行查看,结果如下:

real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 13143
max locked memory           (kbytes, -l) 435188
max memory size             (kbytes, -m) unlimited
open files                          (-n) 1024
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 13143
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited

可以看到open files的值是默认的1024。

临时增加限制

增加的方法很简单,可以使用 ulimit -Sn 65535 命令进行增,不过这种方式是临时增加,可以将上述命令加入到 /etc/rc.local 中实现系统启动自动设置。

永久增加限制

如果永久改变文件描述符的限制,需要编辑 /etc/security/limits.conf 文件,添加或修改下面的内容:

* soft nofile 65535
* hard nofile 65535

其中 soft nofile 是软限制,hard nofile 是硬限制。需要注销并重新登录系统才能生效。

修改完成之后可以再次使用ulimit -a命令进行查看。

增加单个服务的文件描述符限制

上面这样修改之后,发现过一段时间还是频繁出现"Too many open files"的错误。因为Python程序是使用Gunicorn启动的,可以找到进程的id,然后使用 cat /proc/<PID>/limits 命令查看(其中 <PID> 是目标进程的ID):

Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             13143                13143                processes
Max open files            1024                1024                files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       13143                13143                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

从上面的结果可以看到服务进程的文件描述符限制依然是1024,可以修改服务的文件 (在 /etc/systemd/system/ 目录下面,以 .service 结尾),在 [Service] 下面增加如下内容:

[Service]
LimitNOFILE=65535

重新加载systemd配置并重启服即可生效:

sudo systemctl daemon-reload
sudo systemctl restart <your-gunicorn-service>

通过以上设置基本上可以解决Too many open files的问题了。

另外需要指出的是,Ubuntu服务器默认是没有设置虚拟内存的,可以参考Azure Ubuntu服务器经常卡死的解决方法这篇文章进行设置。

参考资料:

Python Subprocess: Too Many Open Files
ubuntu下永久设置文件句柄数和虚拟内存,不需重启
net.ipv4.tcp_fin_timeout的错误理解
TCP连接状态详解及TIME_WAIT过多的解决方法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注