zoukankan      html  css  js  c++  java
  • 生产环境OOM死锁问题排查修复

    OOM:

      1.快速恢复业务:如果是集群中的一台机器故障,先隔离故障服务器;如果是多台,则根据Nginx转发策略,对该功能转发到单独的集群,与其他流量隔离,确保其他业务不受影响

      2.收集内存溢出Dump文件:方式有两种:

        1.设置JVM启动参数

        -XX:+HeapDumpOnOutOfMemoryError

        -XX:HeapDumpPath=/opt/jvmdump

        设置之后,在每次发生内存溢出时,JVM会自动将堆转储,dump文件存放在-XX:HeapDumpPath指定的路径下

        2.使用jmap命令收集

        通过jamp -dump:live,format=b,file=/opt/jvm/dump.hprof pid

      3.分析dump文件:可以通过MAT(Memory Analyzer Tool)进行分析,使用MAT打开Dump文件后,首页截图如下:

    工具按钮介绍:

    :直方图视图,将堆中所有的内存消耗情况统计出来,其如图所示:

    :内存使用树状结构,以线程为维度,树状形式展开,如图所示:

    线程栈,其截图如下:

    根据该图,可以明确,堆的总大小为1.9G,被4个线程全部占据,导致其他线程无法再申请资源,抛出堆内存溢出错误。

    接下来,我通常的做法是直接去看这个视图(以线程为基本维度,查找线程中占用内存的对象),为后续定位排查提供必要的依据。

    从上面的截图中可以得出如下关键信息点:

    • org.apache.ibatis.executor.result.DefaultResultHandler内部持有一个List,其原始为java.util.HashMap,从这个类基本可以看出是与数据库的查询相关,对数据库返回结果的解码并组织成HashMap。

    • 这个List中的元素总共有146033个,初步可以判断出是在一次查询中从数据库中一次查询出了太多数据,造成了内存溢出。

    由于SQL查询代码中,是用HashMap来接收数据库中的返回字段,无法一时间看出是那个查询,那我们能不能精确找到是哪一个查询,哪一行代码,甚至与哪一条SQL语句呢?

    答案是可以的,我们可以从视图一探究竟。

    温馨提示:
    视图使用技巧:展开技巧:沿着使用率最高的项一层一层进行展开,直至发现具体占用内存的对象。

    接下来我们从 视图去寻找是哪个方法,哪条SQL语句触发的。
    具体方法:首先完全展开一个线程,从展开图的底部向上寻找:
    其线程的入口(控制层代码)

    继续往上查找,要找到SQL语句,应该找到Mybatis处理结果集相关的类,如图所示:

    然后展开boundSql即能找到SQL语句:

    然后鼠标可以放在SQL属性中,右键,可以将SQL语句复制出来。

    由于这里涉及到公司的代码机密,故在这里不贴出具体的SQL语句。

    这里根据后面的分析,原来是在做导出功能的时候,没有使用分页对数据进行分页查询,分页写入Excel文件,而是一次将全部数据查询,导致导出功能如果并发数超过4个时,就会将所有内存耗尽。

    解决方案:

    • 首先在运维层面将该请求导入到指定的一台服务器上,是导出任务与其他任务进行隔离,避免对其他重要服务造成影响。

    • 项目组对其代码进行修复,可以使用分页查数据,然后分配写入Excel。

        

    死锁:

      1.查看系统日志,找到对应的死锁方法:

    org.springframework.dao.CannotAcquireLockException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement
    at com.kuding.order.services.ChildOrderService.lambda$modifyChildOrderDeliverStatus$23(ChildOrderService.java:423)
    at com.kuding.order.services.ChildOrderService.modifyChildOrderDeliverStatus(ChildOrderService.java:416)
    at com.kuding.order.controllers.ChildOrderController.modifyDeliveringStatus(ChildOrderController.java:68)
    at com.kuding.common.basestructure.filters.GeetestFilter.doFilter(GeetestFilter.java:102)
    Caused by: org.hibernate.exception.LockAcquisitionException: could not execute statement
    at com.kuding.common.basestructure.interfaces.daointerfacesv2.AbstractDao.create(AbstractDao.java:22)
    Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

    2.在mysql中使用命令:SHOW ENGINE INNODB STATUS;总能获取到最近一些问题信息,通过搜索deadlock 关键字即可找到死锁的相关日志信息。

    分析哪些语句申请锁资源冲突,结合1来确定对应的代码,通过使用分布式锁或者修改获取数据锁顺序来修复

  • 相关阅读:
    面对复杂业务,if-else coder 如何升级?
    为什么StringBuilder是线程不安全的?
    Hashmap中文解释
    mysql 5.6 5.7 8.0新特性
    数据增强,扩充数据集
    神经网络参数优化器
    缓解过拟合
    损失函数
    神经网络的复杂度&指数衰减学习率&激活函数
    GRU&实例股价预测
  • 原文地址:https://www.cnblogs.com/Mr-Rocker/p/11757455.html
Copyright © 2011-2022 走看看