一次线上OOM问题分析
现象
线上某个服务有接口非常慢,通过监控链路查看发现,中间的 GAP 时间非常大,实际接口并没有消耗很多时间,并且在那段时间里有很多这样的请求。

原因分析
先从监控链路分析了一波,发现请求是已经打到服务上了,处理之前不知道为什么等了 3s,猜测是不是机器当时负载太大了,通过 QPS 监控查看发现,在接口慢的时候 CPU 突然增高,同时也频繁的 GC ,并且时间很长,但是请求量并不大,并且这台机器很快就因为 Heap满了而被下掉了。

去看了下日志,果然有 OOM 的报错,但是从报错信息上并没办法找到 Root Cause。
system error: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
另外开发同学提供了线索,在发生问题的时候在跑一个大批量的一次性 JOB,怀疑是不是这个 JOB 导致的,马上把 JOB 代码拉下来分析了下,JOB 做了分批处理,代码也没有发现什么问题。
虽然我们系统加了下面的 JVM 参数,但是由于容器部署的原因,这些文件在 pod 被 kill 掉之后没办法保留下来。
-XX:+HeapDumpOnOutOfMemoryError -XX:ErrorFile=/logs/oom_dump/xxx.log -XX:HeapDumpPath=/logs/oom_dump/xxx.hprof
这个现象是最近出现的,猜测是最近提交的代码导致的,于是去分析了最近提交的所有代码,很不幸的都没有发现问题。。。
在分析代码的过程中,该服务又无规律的出现了两次 OOM,只好联系运维同学优先给这个服务加了 EFS (Amazon 文件系统)等待下次出现能抓住这个问题。
刚挂载完 EFS,很幸运的就碰到了系统出现 OOM 的问题。
dump 出来的文件足有 4.8G,话不多说祭出 jvisualvm 进行分析,分析工具都被这个dump文件给搞挂了也报了个java.lang.OutOfMemoryError: Java heap space,加载成功之后就给出了导致OOM的线程。

找到了具体报错的代码行号,翻一下业务代码,竟然是一个查询数据库的count操作,这能有啥问题?
仔细看了下里面有个foreach遍历userId的操作,难道这个userId的数组非常大?

找到class按照大小排序,占用最多的是一个 byte 数组,有 1.07G,char 数组也有1.03G,byte 数组都是数字,直接查看 char 数组吧,点进去查看具体内容,果然是那条count语句,一条 SQL 1.03G 难以想象。。。


这个userId的数据完全是外部传过来的,并没有做什么操作,从监控上看,这个入参有 64M,马上联系对应系统排查为啥会传这么多用户过来查询,经过一番排查确认他们有个bug,会把所有用户都发过来查询。。。到此问题排查清楚。
解决方案
对方系统控制传入userId的数量,我们自己的系统也对userId做一个限制,问题排查过程比较困难,修改方案总是那么的简单。
别急,还有一个
看到这个问题,就想起之前我们还有一个同样类似的问题导致的故障。
也是突然收到很多告警,还有机器 down 机的告警,打开 CAT 监控看的时候,发现内存已经被打满了。

操作和上面的是一样的,拿到 dump 文件之后进行分析,不过这是一个漫长的过程,因为 down了好几台机器,最大的文件有12GB。
通过 MAT 分析 dump 文件发现有几个巨大的 String(熟悉的味道,熟悉的配方)。

接下来就是早具体的代码位置了,去查看了下日志,这台机器已经触发自我保护机制了,把代码的具体位置带了出来。
经过分析代码发现,代码中的逻辑是查询 TIDB(是有同步延迟的),发现在极端情况下会出现将用户表全部数据加载到内存中的现象。

于是找 DBA 拉取了对应时间段 TIDB 的慢查询,果然命中了。

总结
面对 OOM 问题如果代码不是有明显的问题,下面几个JVM参数相当有用,尤其是在容器化之后。
-XX:+HeapDumpOnOutOfMemoryError -XX:ErrorFile=/logs/oom_dump/xxx.log -XX:HeapDumpPath=/logs/oom_dump/xxx.hprof
另外提一个参数也很有用,正常来说如果程序出现 OOM 之后,就是有代码存在内存泄漏的风险,这个时候即使能对外提供服务,其实也是有风险的,可能造成更多的请求有问题,所以该参数非常有必要,可以让 K8S 快速的再拉起来一个实例。
-XX:+ExitOnOutOfMemoryError
另外,针对这两个非常类似的问题,对于 SQL 语句,如果监测到没有where条件的全表查询应该默认增加一个合适的limit作为限制,防止这种问题拖垮整个系统。
一次线上OOM问题分析的更多相关文章
- 记一次线上OOM问题分析与解决
一.问题情况 最近用户反映系统响应越来越慢,而且不是偶发性的慢.根据后台日志,可以看到系统已经有oom现象. 根据jdk自带的jconsole工具,可以监视到系统处于堵塞时期.cup占满,活动线程数持 ...
- 一次线上OOM故障排查经过
转贴:http://my.oschina.net/flashsword/blog/205266 本文是一次线上OOM故障排查的经过,内容比较基础但是真实,主要是记录一下,没有OOM排查经验的同学也可以 ...
- 【转】又一次线上 OOM 排查经过
又一次线上OOM排查经过 最近线上一个服务又出现了频繁Full GC的情况,导致提供的业务经常超时.问题出现非常不稳定,经过两周的时候,终于又捕捉到了一次Full GC,于是联系运维做Heap Dum ...
- 火山引擎MARS-APM Plus x 飞书 |降低线上OOM,提高App性能稳定性
通过使用火山引擎MARS-APM Plus的memory graph功能,飞书研发团队有效分析定位问题线上case多达30例,线上OOM率降低到了0.8‰,降幅达到60%.大幅提升了用户体验,为飞书的 ...
- 记一次log4j日志导致线上OOM问题案例
最近一个服务突然出现 OutOfMemoryError,两台服务因为这个原因挂掉了,一直在full gc.还因为这个问题我们小组吃了一个线上故障.很是纳闷,一直运行的好好的,怎么突然就不行了呢... ...
- 记一次ArrayList产生的线上OOM问题
前言:本以为(OutOfMemoryError)OOM问题会离我们很远,但在一次生产上线灰度的过程中就出现了Java.Lang.OutOfMemoryError:Java heap space异常,通 ...
- 记一次线上 OOM 和性能优化
大家好,我是鸭血粉丝(大家会亲切的喊我 「阿粉」),是一位喜欢吃鸭血粉丝的程序员,回想起之前线上出现 OOM 的场景,毕竟当时是第一次遇到这么 紧脏 的大事,要好好记录下来. 1 事情回顾 在某次周五 ...
- 记一次 android 线上 oom 问题
背景 公司的主打产品是一款跨平台的 App,我的部门负责为它提供底层的 sdk 用于数据传输,我负责的是 Adnroid 端的 sdk 开发. sdk 并不直接加载在 App 主进程,而是隔离在一个单 ...
- 【jvm】来自于线上的fullGC分析
系统最近老年代的内存上升的比较快,三到四天会发生一波fullGC.于是开始对GC的情况做一波分析. 线上老年代2.7G,年轻带1.3G老年代上升较快,3天一波fullGC,并且fullGC会把内存回收 ...
- 一次线上OOM过程的排查
https://blog.csdn.net/qq_16681169/article/details/53296137 一.出现问题 在前一段时间日常环境很不稳定,前端调用mtop接口会出网络异常或服务 ...
随机推荐
- linux系统中安装虚拟机
在linux系统中,利用图形化界面安装虚拟机.首先启动 virt-manager,当然没有安装 virt-manager需要先安装好. 1 $ apt-get install virt-manager ...
- 网络监测工具之Zabbix的搭建与测试方法(二)-- SNMP、OID和MIB概述
概念 SNMP是专门设计用于在 IP 网络管理网络节点的一种标准协议,它是一种应用层协议.SNMP使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长.通过SNMP接收随机消息(及事件报告 ...
- 【转载】【WinAPI】LockWindowUpdate的函数的用法
DelPhi LockWindowUpdate的函数的用法 Application.ProcessMessages; LockWindowUpdate(Self.Handle); //锁住当前窗口 L ...
- 2020强网杯青少赛Pursuing_The_Wind战队WRITEUP
在线文档:https://docs.qq.com/doc/DZkN0RFFaR1ZDdHhD 旧事拾荒,偶遇该文档,既发. 战队信息 战队名称:Pursuing_The_Wind 战队排名:12 ...
- [深度学习] imgaug边界框增强笔记
imgaug边界框增强笔记主要是讲述基于imgaug库对目标检测图像的边界框进行图像增强.本文需要掌握imgaug库的基本使用,imgaug库的基本使用见[深度学习] imgaug库使用笔记. 文章目 ...
- Java学习笔记:2022年1月10日
Java学习笔记:2022年1月10日 摘要:这篇笔记主要记录了学习<Java核心技术 卷一>的第四章时的一些心得,主要阐述了对象与类这一部分的内容.需要注意的是,这一章的内容需要精心 ...
- ORM执行原生SQL语句、双下划线数据查询、ORM外键字段的创建、外键字段的相关操作、ORM跨表查询、基于对象的跨表查询、基于双下划线的跨表查询、进阶查询操作
今日内容 ORM执行SQL语句 有时候ROM的操作效率可能偏低 我们是可以自己编写sql的 方式1: models.User.objects.raw('select * from app01_user ...
- three.js一步一步来--如何画出构造辅助线
可以参考下面代码,粘贴上去就有了~ <template> <div class="container"> <h1>初步构造出辅助线</h1 ...
- 使用pyenv对python进行版本控制—很好用
相对于python自带的virtualenv来说,pyenv的使用要便利些,更不用说自带的插件python-virtualenv,创建虚拟环境就更为方便了,其实最让我心水的功能是创建的虚拟环境,进入设 ...
- python处理apiDoc转swagger
python处理apiDoc转swagger 需要转换的接口 现在我需要转换的接口全是nodejs写的数据,而且均为post传输的json格式接口 apiDoc格式 apiDoc代码中的格式如下: / ...