炸裂了:Tomcat服务疯狂GC,CPU1200%

oracle数据库版本升级12后,线上服务突然每天白天不定时抽风。

1、调用端表现为接口调用超时;

2、Tomcat服务假死,查看Catalina.out日志缓慢输出,过几分钟应用OutOfMemory异常;

3、top查看linux负载飙高,tomcat进程CPU占用率超过100%,甚至达到1000%多;

刚开始调整JVM参数,增大持久代大小permsize=2g maxpermsize=4g,运行半天后又挂了;

增加dump输出,查看dump日志,由于太大也看不出啥异样,用MAT分析日志,工具一下就奔溃了;

查看异常日志前后,发现接口返回日志中的json串中,有key为$ref,value为 $xxxx.xxxx的元素,进一步发现json格式化时,会自动检测是否存在重复引用和循环引用的元素,如果存在,为了避免堆栈溢出,自动停止了递归,系统用的是阿里开源的fastjson,阿里还是很强大的,借此发现了程序里一些不规范的写法,进行了修正,但是问题依旧;

快奔溃了,数据库升级前都没做过应用升级,奇怪啊!

用户投诉越来越多,组长说重启主机试试吧。遇到棘手的问题,同事写了个应急脚本,如果cpu使用率超过90%就自动重启服务,虽然解决了用户投诉,但是还有些接口调用得手工处理,不是长久之计。

再想想是不是和数据库有关呢?查看oracle的awr日志,看能不能发现什么端倪。发现部分sql有性能问题,通过建立索引解决一些bug;发现redolog切换频繁,指标异常logfile switch(checkpoint incomplete),通过联系dba,调整logfile大小,程序好几天不挂了;过了几天问题突然又跑出来了,也许是这几天应用比较闲;

重新审视应用,尝试关闭mybatis日志输出:

调整jdbc参数:去掉参数removeAbandoned,removeAbandonedTimeout

问题依旧啊!!!

在自动重启脚本中,增加jstack输出,查看应用刚异常时堆栈问题;

通过几次异常堆栈的分析,总是有一个接口,但状态是RUNNING,不应该啊!!

针对该接口,查看接口调用日志表,查看异常前后,只有请求,没有返回的接口做了下统计,就是上面的这个接口,哪里不对?查看请求参数,接口代码,发现请求参数不按套路来啊, 接口服务端没有校验这种流氓请求,导致对数据库表的全量查询,这不挂才怪呢!!至此问题原因总算找到了,接下来就很简单,增加接口限制,这也提醒我们,编写接口时要规范,避免不确定性,偷懒的下场啊!!!

事情还没结束,反思一下问题核查过程,历时3个月左右,难道我们不能提前发现这样的问题吗??

回想10年行业经验,这种线上问题似乎总会遇到。与数据量有关,系统上线时数据量小,不会有性能问题;与接口编码规范有关,如果接口规范点编写,就不会有这样的问题了,还可以通过代码review机制提前发现;如果没有团队内代码review机制,可以通过在应用中增加检测层来提前发现应用异常;也可以在问题出现后,增加检测手段来尽快发现定位问题。避免人力物力的浪费。

如何检测?

针对dao层,检测sql运行影响的行数,设定阈值,增加预警。

这方面如果使用了Mybatis的话,打开mybatis日志,输出到ELK,或者其他alert工具中,即可有效监控。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值