由于数据采集需要,而且流量并不大,不需要使用分布式爬虫,Kaijia使用使用一台服务器同时连接近百个SSH并生成Socket处理采集需求,一开始运行的相当流畅,但是大约数小时后终端便开始不停地弹出“accept: Too many open files”报错。
于是便简单地使用
lsof
命令查看了单个SSH进程使用的文件句柄数量:
结果发现单个SSH比预想中的文件句柄使用率要多很多,连接繁忙(例如并发)的时候可以达到两三百,一般情况下只要Socket有数据传输就可能打开一百个文件句柄。考虑到同时运行的Socket数量较多,同时存在的文件句柄数量可能会超过Linux系统设置的上限,造成“accept: Too many open files”问题。
在Linux系统中,文件句柄上限有两种:全局限制和对单用户限制。
全局最大文件句柄限制
通过
/proc/sys/fs/file-nr
命令可以查看当前全局存在的文件句柄数量:
man
文档给出的介绍是:
This (read-only) file contains three numbers: the number of allocated file handles (i.e., the number of files presently opened); the number of free file handles; and the maximum number of file handles (i.e., the same value as /proc/sys/fs/file-max).
即地此文件包含三个数字:已经分配的文件句柄数;闲置的文件句柄数;最大文件句柄数。全局文件句柄数量限制则是由
/proc/sys/fs/file-max
文件决定的,
man
文档给出的介绍是:
This file defines a system-wide limit on the number of open files for all processes.
对单个进程的文件句柄打开上限由
ulimit
决定的。正如文档介绍的“get and set user limits”,
ulimit
的作用是查看和设置用户资源限制,可以做到防止单一用户滥用影响Linux整体稳定性问题。这里的单个用户可以简单地看做单个Shell(即TTY),在这个Shell中,所有启动的进程打开的文件句柄都记在此Shell的限制中,当此Shell下所有进程打开的文件句柄超过
ulimit
设置的最大文件句柄数时,就会弹出“accept: Too many open files”报错提示。
运行命令:
可以看到当前允许的数量,默认情况下是1024。很大部分的“too many open files”问题都是由于
ulimit
的限制造成的,例如Squid、Java、MySQL等文件句柄大户,如果不放宽限制,此类进程很容易超过默认设置为1024的最大限制。