事件起因

用户反映发起交易请求后界面一直在超时未响应,开发人员随即进行排查,发现soa远程调用验密接口一直异常,导致所依赖的交易全部失败;

排查思路

  1. 查看生产日志和数据库发现,此次异常全部是调用验密接口Exception:Service not found 未找到可用服务 引起,怀疑对方服务未成功注册到注册中心或服务挂掉,随即联系相关系统负责人进行协助排查;
  2. 同事反映加密服务无异常,注册中心也存在该服务,为保证生产环境平稳运行,对加密服务进行重启,重启后访问验密接口还是报错Exception:Service not found 未找到可用服务;
  3. 处理无果,经讨论后将异常系统服务重启,重新拉取注册中心数据,发现接口调用成功,系统恢复正常;
  4. 随即导出生产日志进行分析排查;

日志分析

经分析发现,下午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 ,持续占用容器资源,达到句柄临界值后导致服务异常。

补充资料

  1. 句柄
    linux 所有资源都以文件形式展现, 不单单包括文件,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle)
  2. 修改句柄数
    临时方式:ulimit -n [需要修改的值],退出当前会话后失效;
    永久方式
    修改系统配置文件:
    vim /etc/security/limits.conf
    #在最后加入
  • soft nofile [需要修改的值]
  • hard nofile [需要修改的值]

后记

拿到对方封装的接口后直接调api了,没有仔细进行研究,犯了低级错误,导致出现了生产事故,作为开发人员,需要重视每一行代码,时刻保持警醒的态度。