JVM内存异常OOM异常引发应用僵死问题排查全过程

某部署在阿里云的Java开发应用接口出现耗时长及无响应问题。通过JVM监控、主机监控、日志分析、dump文件分析等排查,发现是SQL查询扫描全表致内存撑爆。根本原因是代码未判空、服务接口未设分页限制,后续需测试调试并优化代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题描述

        某开发应用接口出现耗时长的问题,后面直接就未响应了。导致调用出现异常。部署在阿里云环境下,我们可以通过阿里云的相关监控和告警,从而进行异常问题的排查和确认。下面是问题的排查过程。希望能帮到大家排查这类型的问题。

二、问题排查

1.JVM监控显示异常。

出现FullGC 和YoungGC的次数和耗时都急剧增加,从而导致服务器调用耗时比较长。

2.观察主机监控。

 相关cpu的使用率也在提高,最高达到38%左右。

3、jvm的线程数也提高

4.异常分析。EDAS异常监控和日志异常分析。

        发现有存在一些异常,但是没有大批量刷的情况。也检查了相关异常的出现原因。并未发现有导致gc频繁的原因。

5.Nginx超时时间设置:

proxy_connect_timeout 30;

proxy_send_timeout 60;

proxy_read_timeout 60;

        Nginx配置设置了超时时间为30s,因为服务应用代码gc频繁占用cpu资源,导致耗时过长直接返回超时。

6、gc日志文件分析

7、通过dump文件分析问题原因

        在生产环境运行一段时间,发现没多久就挂掉了。在通过命令打出对应的dump文件进行分析。常用的命令有 jstack 和 jmap 就行。一般安装了jdk都有带相关的命令。

1.jstack命令打出线程运行情况:
/opt/edas/jdk/java/bin/jstack -l  ${pid}> /home/admin/jstack.prof
2.jmap命令打出dump文件:
su - admin/opt/edas/jdk/java/bin/jmap -dump:live,format=b,file=/tmp/dump.hprof  ${pid}

        然后我们再根据相关的文件进行分析问题的原因。需要把dump文件下载到本地,然后再用相关的工具进行分析。这里我们采用的是jdk自带的工具  jvisualvm.exe 进行分析dump堆栈文件。

直接导入进来就行了。发现存在执行sql查询的结果内存在很多的对象。

从而确认问题的原因是SQL查询的时候扫描全表的几百万条数据返回到应用里,导致应用的内存直接撑爆了。应用变成僵死状态。

通过排查应用sql执行日志文件。确认是哪个sql语句

 再通过sql语句来排查代码里的版本修改有没有涉及相关的SQL语句。

 来确定这个问题的根本原因是:代码没有进行判断是否为空,底层的服务接口也没有设置默认分页的条数限制。从而导致了这次的事故异常。

三、问题总结

        发现服务器出现了频繁的FullGC和YoungGC,导致服务器调用耗时变长。对服务器进行了性能分析,发现服务器内存使用率高,且堆内存不足。针对这个问题,需要进行代码优化,对服务器的内存进行了调整,从而解决了这个问题。代码中可能存在一些性能瓶颈,如循环嵌套过多、重复计算等问题。我也看了下这个版本的提交代码,暂时没发现有哪些明显的类似问题。

四、后续处理方案

        具体出现问题的原因需要在测试环境进行测试和调试:为了确保服务器的稳定性和性能,需要对服务器进行了测试和调试,模拟了大量的并发请求,测试了服务器的响应时间、吞吐量、JVM的GC情况等指标。打出对应的dump堆栈文件进行原因分析。找出有问题的代码持续进行优化和改进。可以添加shell脚本定时监控Java进程是否正常运行,以及自动打dump文件和kill掉重启等功能。

        以下是一个示例脚本,它将检查Java进程是否正在运行,并在应用程序无法访问时生成堆栈转储文件和堆转储文件:

#!/bin/bash

# 检查Java进程是否正在运行
if ! pgrep -x "java" > /dev/null
then
    echo "Java应用程序未启动"
    exit 1
fi

# 获取Java进程ID
PID=$(pgrep -x "java")

# 使用curl命令发送HTTP请求以验证应用程序是否可用
if curl --silent --fail http://localhost:8080/health > /dev/null
then
    echo "Java应用程序正在运行"
else
    echo "Java应用程序无法访问"
    # 生成堆栈转储文件
    jstack $PID > heap_dump.txt
    # 生成堆转储文件
    jmap -dump:format=b,file=heap.bin $PID
    # 杀死Java进程
    kill $PID
    echo "已生成堆栈转储文件和堆转储文件,并杀死Java进程"
fi

        该脚本与前面的示例脚本类似,但添加了一个jmap命令来生成Java进程的堆转储文件。jmap命令使用-dump选项指定转储文件的格式(在此示例中为二进制格式)和转储文件的名称(在此示例中为heap.bin)。在生成堆转储文件之后,脚本将使用kill命令杀死Java进程。

        请注意,在此示例脚本中,jstack命令和jmap命令都输出到文件中。如果您希望将输出发送到标准输出或其他文件,请相应地修改脚本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JavinLu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值