V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
killy
V2EX  ›  Java

关于线上 oom 问题的排查,请教大佬们!

  •  1
     
  •   killy · 2021-03-27 12:44:31 +08:00 · 3290 次点击
    这是一个创建于 1318 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在三月中开始的时候,线上突然经常报出 oom,刚开始怀疑那几天提交的代码有问题,因为之前没有报出来过. 代码排查了几遍,没发现有什么问题. 然后把 oom 时的内存信息 dump 下来使用 jvisumalvm 进行分析,发现是 jdbc 查询时,有一个 DataResultSet 对象非常大,占用 1.9g 内存. 感觉是找到了问题的原因,但是找不到问题发生的地方,dump 下来了好几个内存快照,每次 oom 时的栈信息都不一样,但是都有这个 1.9g 的对象. 因为数据库有 600 多张表,整个系统业务很多,根本找不到是哪里查询时的占用的内存.

    然后对其中一台机器尝试过进行 jvm 参数调优,调大了堆,垃圾回收器换成了 CMS+ParNew,日常这种垃圾回收器表现比未调优之前要好,但是依然报出过 oom,报 oom 那段时间一直 fgc,gc 的时间能达到三千多秒...

    最后就是问题不是参数调优可以解决的,感觉就是主要找到那个大对象的代码处,进行优化. 求教各位大佬,怎么通过对象定位代码? 通过代码找感觉有点困难,因为代码非常多,整个项目启动要十分钟. 这种 DataResultSet 对象也是底层封装好的,每个查询可能都用到这个对象,现在感觉不知道从哪下手. 也想过通过数据库里面表数据的大小去反查相关代码, 找到数据库大于 1.9g 的数据表,然后着重查这几个表相关的代码,这种思路不知道行不行的通?

    第 1 条附言  ·  2021-03-28 19:01:07 +08:00
    感谢各位大佬支的招,问题已经找到了,有一张接近 200w 数据的表,在 2 月底一次的提交中,把之前的分页查询给去掉了,直接查了全表.

    过程就是使用 mat 追踪那个 DataResultSet 对象的调用栈,最后找到了对应代码处.

    感谢各位大佬.
    17 条回复    2021-03-28 10:32:14 +08:00
    Livid
        1
    Livid  
    MOD
       2021-03-27 12:45:59 +08:00
    试试这个?

    https://sentry.io/
    wanguorui123
        2
    wanguorui123  
       2021-03-27 12:46:58 +08:00 via iPhone
    内存碎片化?
    chendy
        3
    chendy  
       2021-03-27 13:16:52 +08:00
    试试这个 https://www.eclipse.org/mat/
    能看到大对象的引用关系,帮助定位
    yeqizhang
        4
    yeqizhang  
       2021-03-27 13:48:15 +08:00 via Android
    通过查那个时间点左右的查询语句是否可行?
    specita
        5
    specita  
       2021-03-27 14:05:38 +08:00
    如果确定是 SQL 查询的结果太大导致的,可以看一下数据库的日志,比如慢查询日志,有记录数据大小的。
    或者如果用的是 druid 连接池,打开监控也能看到相关 SQL 的处理信息。
    如果不是 SQL 导致的,那就是应用程序实现的问题了,可以试试用 arthas 线上排查一下。哪个请求报的 OOM 应该知道吧。
    Jooooooooo
        6
    Jooooooooo  
       2021-03-27 14:06:47 +08:00
    能不能尝试分析下 DataResultSet 里面是什么内容.

    然后再看下多次发生 oom 时间点的日志, 有没有固定的查询语句.
    john6lq
        7
    john6lq  
       2021-03-27 14:10:40 +08:00 via iPhone
    目测 sql 问题
    fantastM
        8
    fantastM  
       2021-03-27 14:37:43 +08:00
    是我的话,会先从慢 SQL 日志开始看起
    EminemW
        10
    EminemW  
       2021-03-27 16:02:24 +08:00 via iPhone
    jprofiler 可以看对象内容,你再到倒推出内容存在那张数据库表?
    ychost
        11
    ychost  
       2021-03-27 16:07:34 +08:00
    估计是 SQL 的问题
    lewis89
        12
    lewis89  
       2021-03-27 17:05:41 +08:00
    找到泄漏点的数据结构 通常是 GCRoots,
    然后升级一下依赖的版本 看看之前的依赖版本 release log 里面是不是有解决 OOM 的问题
    lewis89
        13
    lewis89  
       2021-03-27 17:06:39 +08:00
    你能确认 DataResultSet 就是 GCRoots?
    lewis89
        14
    lewis89  
       2021-03-27 17:08:06 +08:00
    像 OOM 这种问题 用 MAT 分析一下基本上就能定位到泄漏点了,然后上网找找是不是有类似的泄漏情况,找不到最后再去处理,一般泄漏点都是 框架的代码,业务仔自己 new 的对象 一般活不过两轮 GC
    xuanbg
        15
    xuanbg  
       2021-03-27 17:38:50 +08:00
    在内存里面找到了 1.9G 的对象,就猜不出是哪张表的数据?找到表就能找到读数据的代码。
    securityCoding
        16
    securityCoding  
       2021-03-28 05:06:00 +08:00 via Android
    按我的经验来看 mat 导进去,一般就能准确定位到内存泄漏代码了
    wapzjn
        17
    wapzjn  
       2021-03-28 10:32:14 +08:00
    我想起了以前一个同事调用别人接口忘记了传递分页信息,正好接口的开发同事也没有处理没有分页信息时的场景,然后用户一查询 OOM
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1206 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:11 · PVG 02:11 · LAX 10:11 · JFK 13:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.