现网多台机器都出现了Too many open files这个错误,应用无法访问。
原因一:Linux 的open files 数不够
[root@chances125 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 78454
max locked memory (kbytes, -l) 64
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) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more
#查一下当前已有的连接数,再来判断open files 为1024 是不是小
lsof -p $java_pid | wc -l
#加大打开的文件数
ulimit -n 2048
#用户级别的修改
#系统级设置对所有用户有效。
#可通过两种方式查看系统最大文件限制
cat /proc/sys/fs/file-max
#修改配置/etc/sysctl.conf文件
fs.file-max=2048
#通知系统启用这项配置
sysctl -p
原因二:TCP 参数配置不对
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 7091
CLOSE_WAIT 2
ESTABLISHED 716
LISTEN 10
常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭
服务器保持了大量TIME_WAIT状态
#参数优化
#表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间
net.ipv4.tcp_fin_timeout = 30
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒,原因是:当前都是图片,不需要建立长链接
net.ipv4.tcp_keepalive_time = 300
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
net.ipv4.tcp_syncookies = 1
#表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间
net.ipv4.tcp_tw_reuse = 1
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭,当前TIME-WAIT 过多,所以开启快速回收
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000 65000
配置生效后,观察结果,TIME_WAIT 明显减少。
TIME_WAIT 2492
CLOSE_WAIT 10
ESTABLISHED 730
LISTEN 10
原因三:Tomcat 配置不对
connectionTimeout - 网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
当前配置connectionTimeout=0
根据公式:服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量
待测试验证
原因四:程序打开了许多文件,但未关闭连接
之前一直在找程序哪里打开了文件却未关闭连接,未果。
才想到连接打开后,多久可以关闭。
lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 3011 root 837u IPv6 3513129 0t0 TCP sc-epg-app15:8085->10.223.52.16:38494 (ESTABLISHED)
java 3011 root 838u IPv6 31731 0t0 TCP sc-epg-app15:8085->10.230.160.147:38903 (ESTABLISHED)
java 3011 root 839u IPv6 3667505 0t0 TCP sc-epg-app15:8085->10.251.207.71:35411 (ESTABLISHED)
#NODE 对应的是TCP
#PID 3011,当前服务器上只有一个应用。
待解决的问题是:
1)如何定位到程序代码什么地方打开了文件?
2)打开的这些文件是不是都是必要的?
3)can't identify protocol的原因