事件起因
用户反映发起交易请求后界面一直在超时未响应,开发人员随即进行排查,发现soa远程调用验密接口一直异常,导致所依赖的交易全部失败;
排查思路
- 查看生产日志和数据库发现,此次异常全部是调用验密接口Exception:Service not found 未找到可用服务 引起,怀疑对方服务未成功注册到注册中心或服务挂掉,随即联系相关系统负责人进行协助排查;
- 同事反映加密服务无异常,注册中心也存在该服务,为保证生产环境平稳运行,对加密服务进行重启,重启后访问验密接口还是报错
Exception:Service not found
未找到可用服务; - 处理无果,经讨论后将异常系统服务重启,重新拉取注册中心数据,发现接口调用成功,系统恢复正常;
- 随即导出生产日志进行分析排查;
日志分析
经分析发现,下午15点,jboss的server日志出现一条ERROR级别日志:Java IOException:Too many open files
导致jboss服务器产生了pending文件;
下午17点开始出现大面积接口调用失败现象,引起交易失败;
查询了jboss各种启动状态,查询到jboss 的启动文件含义如下:
.deployed | 服务部署成功 |
.isdeploying | 服务正在部署成功,当部署完成后,将自动删除这个文件 |
.failed | 服务部署失败 |
.undeployed | 表明war包在运行时被删除, 若重新发版则需要删除该文件 |
.isundeploying | deployed文件 被删除后,正在取消部署内容。执行完毕后这个文件也会被删除 |
.pending | 容器发现重大异常,然后处于自我保护 |
jboss进程在发生严重异常时自己生成了pending,可以肯定的是,15点开始,服务器就已经处于异常状态,根据异常报错 Java IOException:Too many open files
推断出原因是因为打开了太多文件资源(句柄), 需要关注是否有大量文件未关闭,如果是正常现象,则考虑调整系统参数,增大最大句柄数;
使用命令 ulimit -a
发现 open files 数值已经达到最优值51200,
随即在pre环境进行压力测试,使用命令lsof -p [jbossID] |wc -l
检测jboss线程的句柄数,也可使用以下shell脚本:
#!/bin/sh
#Setup env
PID=`ps -ef|grep java|grep Standalone |awk -F ' ' ' {print $2}'`
LSOF=`lsof -p $PID |wc -l`
echo $LSOF
发现句柄数随交易数量的增加成线性增加,等达到open files 临界值时,出现服务调度异常问题,完整还原生产场景;
排查代码发现,在异步调用kafka时没有进行关闭连接操作,导致Tcp资源一直在ESTABLISHED
,持续占用容器资源,达到句柄临界值后导致服务异常。
补充资料
- 句柄
linux 所有资源都以文件形式展现, 不单单包括文件,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle) - 修改句柄数
临时方式:ulimit -n [需要修改的值],退出当前会话后失效;
永久方式:
修改系统配置文件:
vim /etc/security/limits.conf
#在最后加入
- soft nofile [需要修改的值]
- hard nofile [需要修改的值]
后记
拿到对方封装的接口后直接调api了,没有仔细进行研究,犯了低级错误,导致出现了生产事故,作为开发人员,需要重视每一行代码,时刻保持警醒的态度。