记一次Orika导致的堆外OOM的坑

本文介绍了在一个异步接单系统中,由于大量使用Orika进行对象拷贝,导致元空间内存溢出(OOM),进而触发Full GC,甚至引发系统宕机的问题。问题关键在于每次拷贝都新建了MapperFactory,解决方案是改为使用静态MapperFactory实例,确保其只创建一次,避免元空间内存耗尽。文章强调了深入理解新技术原理的重要性。
摘要由CSDN通过智能技术生成

问题描述

本次问题出现在一个异步接单的场景,在每天的整点会有一个定时任务触发一个批量接单的任务,会有大量的订单通过mq的方式下发到本系统。本次问题就是订单下发mq时,消费端服务器均产生频繁的fullgc,初步排查后发现问题为元空间(meta)发生了OOM(内存溢出)

相关技术栈描述

本项目在进行对象拷贝方案选型时,选用了 Orika 的方式进行对象拷贝(依赖如下),这种拷贝方式特性是比较快而且是深度拷贝,但是需要定义映射方法,核心机制就是会先创建一个映射工厂类,映射工厂通过定义好的映射方法创建一个映射类,然后通过这个映射类进行对象拷贝。本次问题产生的原因就在Orika的这种对象拷贝机制上。

<dependency>
    <groupId>ma.glasnost.orika</groupId>
    <artifactId>orika-core</artifactId>
    <version>1.5.1</version>
</dependency>

问题解析

先上一段问题代码片段,这一段的代码是用来做对象拷贝的:

	/**
	  *出问题的代码块
	  */
    public static <S, D> D mapWithSubList(S source, Class<D> destClass,
                  String sourceSubListFiled, Class<?> sourceSubListClass, String destSubListFiled, Class<?> destSubListClass) {
        if (source == null){
            return null;
        }
        //构建映射工厂
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        mapperFactory.classMap(source.getClass(), destClass).byDefault()
                .fieldMap(sourceSubListFiled,destSubListFiled).aElementType(sourceSubListClass).bElementType(destSubListClass)
                .add().register();
        return mapperFactory.getMapperFacade().map(source,destClass);
    }

在执行对象拷贝时会通过这个MapperFactory 创建一个MapperFacade映射类),然后通过这个MapperFacade批量对对象进行拷贝处理,也就是这一段:

	MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    mapper = mapperFactory.getMapperFacade();

问题就出在这里,正常使用的时候映射类是可以重复使用的,但是由于开发者对于这个拷贝机制并不熟悉,在使用的时候新构建了映射工厂,这样就导致每次使用此拷贝方式的时候不仅会重新创建一个映射类还会创建一个映射工厂类,这样的话大量的mq请求进系统后,就会产生大量的映射类文件存储在元空间中,将元空间的内存打爆,从而触发fullgc。而且由于OOM的异常的爆出,mq的broker会判断消费失败,会重新由其他机器消费,因此所有机器无一幸免全部宕机。

解决方案

将创建工厂部分单独提出为私有静态变量,并通过静态代码块进行初始化,让其只创建一次。具体代码如下:

public class BeanMapper {

    private static MapperFacade mapper;

    static {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        mapper = mapperFactory.getMapperFacade();
    }
}

总结

在引入新的技术栈时候一定要深入了解其原理,要是早就了解此原理也不至于出现生产环境堆外OOM。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

摆烂的小趴菜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值