EDAS——如何快速定位OOM问题

简介: 相信很多“程序猿”都能知道,OOM 异常 ——“java.lang.OutOfMemoryError”, 在应用开发中,是比较常见的一种异常,出现OOM的情况,往往会导致应用服务异常、线程异常、程序崩溃。


本期分享专家:滨雨,有多年软件开发 + 项目管理经验,先后在华为、阿里基础架构部任职,在阿里云主要从事存储、cdn、视频、中间件等技术领域的支持,喜欢新技术,喜欢钻研,喜欢各种新的挑战。

什么是OOM?

相信很多“程序猿”都能知道,OOM 异常,就是我们常见的: “java.lang.OutOfMemoryError” 在应用开发中,是比较常见的一种异常,主要分为三种:
1. OutOfMemoryError: PermGen space
2. OutOfMemoryError: Java heap space
3. OutOfMemoryError:unable to create new native thread

OOM的危害

出现OOM的情况,往往会导致:
1、应用服务异常
2、线程异常
3、程序崩溃
以及其他未知的问题,相信看到这几点就能体会到 “ OOM ” 的“ 恐怖 ”了。

如何排查OOM问题

在遇到这OOM问题的时候,要如何分析原因,是直接去死磕代码?还是去调整工程架构?我相信这样的方式很多时候都只会徒劳,那针对这类问题,我们可以如何快速的去排查定位呢?

模拟异常场景

为了说清楚整个排查过程,我们编写一段OutOfMemoryError测试代码,用来模拟出 oom 场景。
servlet 测试代码:

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("heap test begin");

        List<TestCase> cases = new ArrayList<TestCase>();
           while(true){
               cases.add(new TestCase());
           }
        //super.doGet(req, resp);
    }
public class TestCase {
    public int id;
    public String name;
    public String[] array  = new String[1024];
    public List<String> list = new ArrayList<>(1024);

web.xml映射路径:

<servlet>
        <servlet-name>Heaptest</servlet-name>
        <servlet-class>com.alibaba.edas.tradeshop.threadtest.HeapOutOfMemory</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Heaptest</servlet-name>
        <url-pattern>/heap.htm</url-pattern>
    </servlet-mapping>

获取dump文件

Dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中,是开发人员定位jvm问题的“利器”。

方式一:edas控制台部署添加参数

通过edas控制台部署启动应用,可以指定jvm参数,在控制台上指定最大Heap Size 和初始化Heap Size 都为100m  (注意现在配置的值只是为了测试)
另外还可以自定义加上一些参数,例如:

-XX:+PrintGCDetails  -XX:+HeapDumpOnOutOfMemoryError XX:HeapDumpPath=/home/admin/dump/

控制台上设置:

screenshot.png

screenshot.png

PrintGCDetails 会将gc日志打印出来,XX:HeapDumpPath指定dump文件存储路径,当出现OOM问题时,会在/home/admin/dump/生成一个dump文件

方式二:通过jmap获取

jmap 是 jdk自带的一个 jvm 检测工具,为了能让通过jmap方式的时候获取到堆栈溢出的dump文件,我们将代码改为:

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("heap test begin");

        List<TestCase> cases = new ArrayList<TestCase>();
           while(true){
               try{
                   cases.add(new TestCase());
               }catch(Throwable t){
               }
           }
        //super.doGet(req, resp);
    }

访问到测试代码入口,在应用服务器上执行:

jmap -dump:live,format=b,file=heap.bin <pid>

可以获取到heap.bin文件。

测试堆栈溢出

admin用户登录到服务器上,找到tomcat进程ID,执行 ./jstat -gcutil {pid} {时间间隔} ,观察 gc 执行情况:

screenshot.png

可以看到当前YGC 和 FGC 都不频繁,属于正常状态。

当我们访问测试路径: http://{ip}:port/path/heap.htm

执行结束后,可以发现,eden 区和 old 区 都瞬间打满,而且短时间内发生多次 FGC:

screenshot.png

MAT 内存分析

mat 是一个快速分析 java 内存的工具,mat 官网
到服务器上,之前我们指定的路径下面,方式一:/home/admin/dump/ 可以找到生成的 hprof 文件,方式二:生成的heap.bin文件,下载下来后,用 mat 内存分析软件打开

screenshot.png

screenshot.png

经过mat 分析后,马上可以得出一份分析报告,从这可以很清晰的定位到,是由于 “ HeapOutOfMemory.doGet ” 这段代码入口导致的堆栈溢出,终于,我们的“罪魁祸首”付出水面了,原来,是由于代码中出现了一段死循环一直在新建class 类,导致堆栈溢出,接下来,该知道怎么去修改代码了吧。

小结

当遇到jvm问题的时候,不必惊慌,也不要因为是技术底层问题而感到无从下手,我们有很多种方法可以方便定位到原因,除了本文中提到的 mat 内存分析工具,我们还有很多其他的小工具可以利用起来,jdk 本身就提供了很多这样的支持工具,例如: jconsole、jmap、jstat、jinfo、jvisualvm 等等,会利用好这些小工具,下次再遇到类似的问题后,就可以得心应手了。

相关实践学习
使用DAS实现数据库自动SQL优化
本场景介绍如何使用DAS实现数据库自动SQL优化。
SpringMVC框架入门
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts2等。 相关的阿里云产品企业级分布式应用服务 EDAS:企业级分布式应用服务 EDAS(Enterprise Distributed Application Service)是一个应用托管和微服务管理的 PaaS 平台,提供应用开发、部署、监控、运维等全栈式解决方案,同时支持 Spring Cloud、Apache Dubbo(以下简称 Dubbo )等微服务运行环境,助力您的各类应用轻松上云。产品详情: https://www.aliyun.com/product/edas&nbsp;
相关文章
|
安全 Java 关系型数据库
4月14日云栖精选夜读:EDAS-如何快速定位OOM问题【云享团】
不知大家是否经常在写java程序的时候会遇到OutOfMemoryError这个异常,一般在那些大型需要消耗大量内存的软件中这个错误是有可能发生的,相信大多数“程序猿”都知道OOM这个异常会引发的后果,那如何解决这个问题呢?欢迎点击阅读《EDAS-如何快速定位OOM问题【云享团】》,也许你能在这篇文章中找到答案。
2483 0
|
11月前
|
监控 应用服务中间件
如下请问EDAS的这个问题怎么解决? 应用id:2b0e6935-47fb-40ec-a11d-7dac320aecc1 集群中的节点内存是足够的,部署跑不起来 可以帮忙看看吗,以前集群下应用发布都是正常的,最近集群下应用部署基本都报错跑不起来,提示节点不可用
如下请问EDAS的这个问题怎么解决? 应用id:2b0e6935-47fb-40ec-a11d-7dac320aecc1 集群中的节点内存是足够的,部署跑不起来 可以帮忙看看吗,以前集群下应用发布都是正常的,最近集群下应用部署基本都报错跑不起来,提示节点不可用
117 2
|
Kubernetes 负载均衡 Serverless
通过EDAS部署并访问应用
本实验旨在通过使用分布式应用服务EDAS纳管容器服务ASK,掌握微服务应用的部署和访问。
413 1
|
Kubernetes Serverless 应用服务中间件
通过EDAS实现K8s微服务应用的金丝雀发布
本实验旨在通过使用分布式应用服务EDAS纳管容器服务ASK,体验微服务应用的部署、访问和高级发布能力。
314 0
|
弹性计算 Kubernetes Cloud Native
云原生微服务应用平台 EDAS 2022 年度报告
最近一年来,随着我们的客户对于云技术的诉求从资源快速交付的服务,转变为对资源精益运用的服务。EDAS 团队结合公共云上所服务的企业类客户的几万个应用,选取了 8 个最具代表性的指标,进行了一次系统性的分析整理和总结,希望可以给当前正在从事软件架构的从业人员一个侧面的视角,来了解一些当下发生在身边的技术现象。
403 1
云原生微服务应用平台 EDAS 2022 年度报告
|
弹性计算 Kubernetes Cloud Native
云原生微服务应用平台 EDAS 2022 年度报告
最近一年来,随着我们的客户对于云技术的诉求从资源快速交付的服务,转变为对资源精益运用的服务。EDAS 团队结合公共云上所服务的企业类客户的几万个应用,选取了 8 个最具代表性的指标,进行了一次系统性的分析整理和总结,希望可以给当前正在从事软件架构的从业人员一个侧面的视角,来了解一些当下发生在身边的技术现象。
云原生微服务应用平台 EDAS 2022 年度报告
|
应用服务中间件 开发者
EDAS 应用创建、启动和停止|学习笔记
快速学习 EDAS 应用创建、启动和停止
341 0
EDAS 应用创建、启动和停止|学习笔记
|
应用服务中间件 开发者
EDAS 应用部署、启动和停止|学习笔记
快速学习 EDAS 应用部署、启动和停止
616 0
EDAS 应用部署、启动和停止|学习笔记
|
弹性计算 监控 负载均衡
EDAS 应用监控|学习笔记
快速学习 EDAS 应用监控,该功能主要包括三个功能,即监控大盘、基础监控以及服务监控。
244 0
|
应用服务中间件 开发者
EDAS 应用回滚、扩容和删除|学习笔记
快速学习 EDAS 应用回滚、扩容和删除
259 0

热门文章

最新文章