【开发篇】三、并发下的OOM分析

发布时间:2024年01月15日

1、并发下的OOM分析

用户请求过来, 后端查询数据库后封装Vo对象返回给前端后,然后正常这个Vo就可以被GC清理掉了。

在这里插入图片描述

但并发时,如果数据处理时间很长,大量对象存于内存,或者处理用户请求后,没有及时删除用户数据对象,就会导致无用对象在堆内存堆积,进而OOM。关键点:

  • 并发大
  • 方法里保存了大量的数据到内存
  • 请求的处理时间长,导致对象在内存中待的更久

示意Demo:

@RestController
public class LeakController {

    private static Map<Long, Students> userCache = new HashMap<>();

    /**
     * 大量数据 + 处理慢
     */
    @GetMapping("/leak1")
    public String doSome() throws InterruptedException {
        byte[] bytes = new byte[1024 * 1024 * 100];  //100M
        //本来这个bytes对象会释放,但由于后面的代码,这个对象在内存中愣是多待了十秒钟
        Thread.sleep(1000 * 10L);
        return "success";
    }

    /**
     * 没有及时清除用户数据对象
     */
    @PostMapping("/leak2")
    public String doSome2(Long id, String name) {
        //用户不再用这个对象以后,它还在静态变量map中存着
        userCache.put(id, new Students(id, name));
        return "test";
    }
}

@Setter
@Getter
@NoArgsConstructor
public class Students {

    private Long id;

    private String name;

    private byte[] info = new byte[1024 * 1024 * 100];   //模拟大对象

    public Students(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    /**
     * 这里实体类的equals和hashcode都正常,没有前一篇笔记说的那种内存泄漏的错误写法
     * 只比id属性即可,ID相同,则同一个对象
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Students students = (Students) o;
        return Objects.equals(id, students.id);
    }

    /**
     * id属性
     */
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

调整下堆内存大小,方便后面验证。

-Xms5g -Xmx5g

2、Jmeter模拟并发

压测上面的接口,并发下OOM,则系统在用户高峰期一定会崩。

在这里插入图片描述

100线程数并发,循环执行两次:

在这里插入图片描述

接口传参这里用Jmeter的随机函数:

在这里插入图片描述

复制生成的表达式做为传参值:

在这里插入图片描述
在这里插入图片描述

HTTP Request如下,添加结果数和摘要报告组件后启动:

在这里插入图片描述

结果:

在这里插入图片描述
在这里插入图片描述
控制台OOM:

在这里插入图片描述

文章来源:https://blog.csdn.net/llg___/article/details/135559258
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。