崩溃了,凌晨两点银行系统出现Too many open fils问题!

分享亲身经历,刚刚上线三天的银行ESB系统,在凌晨两点系统监控中出现了load值飙升的情况,并且系统出现了大面积的调用失败的情况,银行立即启动了备用系统,才导致没有发生其他的损失。半夜三点,项目经理打电话让所有的人到银行解决问题。

问题定位

开始的时候架构师、高工分析可能是出现了应用程序OOM的异常,所以就dump日志,查看JVM内存使用情况,但是花很长时间都没有发现有啥OOM的异常。所有的GC、堆栈日志都显示是正常的。

并且查看了ESB的内部监控平台,也没有发现应用本身出现OOM的异常或者是其他告警,这就有点麻烦了。

架构师坐到电脑前面疯狂的输出之后,又是查看Oracle、又是检查服务器的,最终发现了原来是由于报文记录导致了Too many open file 的错误信息。这是个什么鬼东西?

Too many open files:句柄数超过系统限制,是Linux系统中常见问题,这里的 files 不仅是系统文件,还包括请求连接 socket,端口监听等,这是因为在Linux系统中将所有的一切都看做是一个文件来进行处理,所以要对这些东西进行操作的话就会存在对应的文件描述符。

问题产生的原因

经过一番排查之后,架构师吃完早餐之后,确定了问题所在,因为在ESB系统中会有报文临时存储的情况,在加载完临时报文存储之后,删除文件的句柄没有释放,然后在日志配置中又在使劲的创建日志,导致持有的文件句柄数超过了Linux最大的句柄连接数,导致后续的报文日志无法操作,最终导致应用无法提供服务。

文件句柄的原理

在Linux系统中,将所有的一切的目录、字符设备、块设备、套接字、打印机等都抽象成了一个文件处理。也就是经常会提到的Linux中一切皆文件。

当系统操作这些文件的时候,为了记录每个操作文件访问情况,就会为这文件创建一个文件描述符也就是常说的fd,并且这些fd都是存在于Linux的open files table中,而这个table所能容纳的fd是有限的。如果超过了这个值,那么Linux没有fd的分配了,就会拒绝文件操作请求,最终就出现了Too many open files的异常。

这个异常在服务器进行Socket连接超过服务器最大连接数的时候也会出现。这是因为每一个Socket连接都是一个文件描述符,当超过了65535的之后服务器就会拒绝连接。

如何解决呢?

查看文件句柄连接数

在Linux通过 ulimit -a 命令来查看当前所占用的句柄连接数。这里演示如何使用,而非真实场景。

[root@localhost ~]# 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) 31142
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) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31142
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[root@localhost ~]# 

其中open files 所展示的就是单个进程允许打开的最大句柄连接

找到对应的进程的PID,查看该进程对应的文件句柄。

[root@localhost ~]# ps -ef|grep java
root      7642  7602  0 09:48 pts/0    00:00:00 grep --color=auto java
root     32053     1  0 9月20 ?       00:07:34 java -jar swly-admin-0.0.9-8082.jar
[root@localhost ~]# lsof -p 32053 | wc -l
97
[root@localhost ~]# lsof -p 32053
COMMAND   PID USER   FD      TYPE             DEVICE  SIZE/OFF      NODE NAME
java    32053 root  cwd       DIR              253,0      4096   4721636 /data/swly/admin
java    32053 root  rtd       DIR              253,0       256       128 /
java    32053 root  txt       REG              253,0      8712 101830342 /usr/local/java/jdk/bin/java
java    32053 root  mem       REG              253,0    292520  34594181 /usr/local/java/jdk/jre/lib/amd64/libjpeg.so
java    32053 root  mem       REG              253,0   1048136  34594178 /usr/local/java/jdk/jre/lib/amd64/libmlib_image.so
java    32053 root  mem       REG              253,0    504840  34594192 /usr/local/java/jdk/jre/lib/amd64/libt2k.so

在正常情况下,可以通过增加open files的方式来解决这个问题,但是我们出现的问题并不能通过这种方式来解决,只能是保证临时的解决。要想实际解决还需要查看代码的逻辑,发现是代码逻辑中对日志记录的问题,文件流没有进行close的操作。

临时解决方案可以执行如下的命令来增加句柄连接数。

ulimit -n 2048 # 重启后会恢复默认值,非root用户只能设置到4096

或者通过修改配置文件的方式来永久的进行修改。

[root@localhost ~]# vi /etc/security/limits.conf
 
# 文件末加入
* soft nofile 655360
* hard nofile 655360

总结

最终在架构师和高工的共同努力下,通过查看代码找到了问题,是因为ESB系统在临时存储报文的log日志的时候没有将文件流Stream进行关闭,导致后续的报文进入之后,前面的文件描述符没有释放,在凌晨一点开始核心系统重写的时候,大量的请求经过ESB系统,导致log日志占用文件句柄数过多出现了这么一个生产问题,最终还加入了日志定时删除的操作。

展开阅读全文

页面更新:2024-03-13

标签:报文   句柄   高工   系统   两点   异常   情况   操作   服务器   银行   文件   日志   凌晨

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top