首页 > 其他分享 >生产大文件下载导致 OOM,顺藤摸瓜拿下

生产大文件下载导致 OOM,顺藤摸瓜拿下

时间:2024-03-27 11:36:50浏览次数:25  
标签:GC 文件 OOM 顺藤摸瓜 uri filename 拿下 file new

上周遇到了生产环境 OOM 的问题,找了一番之后基本定位了是大文件下载导致的问题,于是在网上搜罗了一番文章,下面分享一篇优质的解决方案,整个排查思路非常清晰,小白可以直接对照着来排查。

事故发生

上周五下午运营人员反馈,笔者所负责的后台系统从 14 点以后就卡卡的,虽然页面能够正常加载,但是一直处于数据加载中,数据也提交不了,怀疑笔者的系统有BUG,当听到运营人员的反馈我的第一反应是这不可能啊,这么简单的一个后台系统,还能出事故?

处理流程

  • 摘除其中一台服务器用于保留现场,其他服务器先重启,保证系统可用。
  • 下载GC日志,系统dump文件用于分析

GC log分析

系统启动参数,JVM内存分配:-Xmx4096m -Xms4096m -Xmn2560m

观察日志可知系统每隔 40S 发生一次 Full GC,耗时 200 毫秒,回收以后系统老年代占用也不大,才 15M,但是新生代回收完还有 2 个 G。

有点不可思议,竟然不是老年代塞满了数据,而是新生代塞满了数据。

初步推测是新生代数据要晋升到老年代,结果放不进去而引起的 Full GC。

使用 MAT 对 Dump 文件进行分析

通过总图可以看出来目前系统内存占用超过 2 个 G:

点击 Histogram 进行进一步分析,看出系统中占用最多的是byte[]

点击List Objects进入income引用统计界面

层层点开,发现byte[]被 ResponseEntity 对象所引用,且数量不小

翻阅代码

1)在系统中找到唯一ResponseEntity有关的代码

2)这代码看似没什么问题啊,这不是很正常的文件下载么???我去看看用户下载了啥,跑到目录文件查看一下下。

我的天,用户下载的是一份2.4G的大文件,代码中FileUtils.readFileToByteArray(file) 的方式是把整个文件读取到内存再输出流里写入,此时内存不够分配,又塞不进老年代,只能是 Full GC 了。

3)成功破案了,用户下载了一份大文件,文件先加载到内存才往外写,抹泪。。。。

解决方案

使用FileSystemResource

public ResponseEntity download(@RequestParam("uri") String uri) throws IOException {
  File file = new File(uri);
  if (!file.isFile()) {
   throw new ServiceException("文件不存在");
  }

  String filename = FilenameUtils.getName(uri);
  HttpHeaders headers = new HttpHeaders();
  headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
  HttpStatus status = HttpStatus.OK;
  return new ResponseEntity<>(new FileSystemResource(file), headers, status);
}

使用缓存流,边读边写

@GetMapping("/down")
public void download(@RequestParam("uri") String uri, HttpServletResponse response) throws IOException {
 File file = new File(uri);
  if (!file.isFile()) {
   throw new ServiceException("文件不存在");
  }

  String filename = FilenameUtils.getName(uri);
  response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));

  try (FileInputStream fileInputStream = new FileInputStream(file);
    BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream())) {
    FileCopyUtils.copy(bufferedInputStream, bufferedOutputStream);
  } finally {
   // 使用的是try-with-resources

  }
}

或者 文件存储到 oss 或者是七牛云

标签:GC,文件,OOM,顺藤摸瓜,uri,filename,拿下,file,new
From: https://www.cnblogs.com/kisshappyboy/p/18098568

相关文章

  • IT15527: IN SPECIFIC TIMING CONDITIONS WITH MULTIPLE DB2READLOG API CALLERS(CDC,
    IT15527:INSPECIFICTIMINGCONDITIONSWITHMULTIPLEDB2READLOGAPICALLERS(CDC,ETC),"NOROOMFORRETRIEVEDLOG"occursindb2diag.loghttps://www.ibm.com/mysupport/s/defect/aCI0z000000TOfW/dt010963?language=en_USDescription 1.  Proble......
  • 人生房间Life Room
    人生房间(出生-高考-行业-结婚-子女-死亡),3张照片(父母xo-初中xo-妻子女o),一开始打叉叉,后来活着的打圈:“有三毒残害身心,使人沉沦于生死轮回,为恶之根源。”print(MYLIFE);从病床-心脏检测仪-苍老的手上戴着玉,还断了一根手指,朝着窗;又转向看天花板,自己和母亲从手术室分娩房出来;1~4......
  • LRC软件、Adobe Lightroom Classic最新版破解安装下载合集教程
    AdobeLightroomClassic(简称LR)是AdobeCreativeCloud大家庭中的一款专业的图片管理和编辑工具,用于专业摄影师、摄影爱好者以及所有不断优化数码影像的人等。其目标是以丰富的功能提供高效、一致的体验,帮助用户汇聚、组织、管理、编辑和分享数码图片。AdobeLightroomClassi......
  • Photoshop2024(PS)和Lightroom(LR)设计的智能磨皮插件Portraiture下载
     打造完美肤质,PortraiturePS/LR专用智能磨皮插件让你的照片焕发魅力副标题:让你的照片告别粗糙皮肤和毛孔,展现自然细腻的肤质在摄影后期处理中,给照片进行磨皮和肤质优化是一项必不可少的步骤。而今天,我们为你带来了一款专为Photoshop(PS)和Lightroom(LR)设计的智能磨皮插件——......
  • bloom 算法
    该文章翻译自(https://www.enjoyalgorithms.com/blog/bloom-filter/)[https://www.enjoyalgorithms.com/blog/bloom-filter/]Bloom过滤器是一种空间效率高的概率数据结构,它能告诉我们某个元素可能在某个集合中,或者肯定不在某个集合中。如果我们在Bloom过滤器中查找一个项,可以......
  • MK Glow - Bloom & Lens & Glare
    MKGlow(Ultimate)是一种使用简单、功能丰富且效果超级迅速的后处理效果,可以模拟明亮表面的光照散射。除了散光效果之外,还提供一些高度自定义的特效,比如镜头表面、镜头眩光和强光。该着色器兼容传统、轻便、通用和高分辨率渲染管线。两大直观工作流程:阈值:根据像素亮度、阈值和......
  • 工作中Java最常见的6种OOM问题
    前言今天,跟大家一起聊聊线上服务出现OOM问题的6种场景,希望对你会有所帮助。1堆内存OOM堆内存OOM是最常见的OOM了。出现堆内存OOM问题的异常信息如下:java.lang.OutOfMemoryError:Javaheapspace此OOM是由于JVM中heap的最大值,已经不能满足需求了。举个例子:publicclass......
  • Joomla SQL注入漏洞(CVE-2017-8917)
    环境搭建参考vulhub中文文档:https://github.com/vulhub/vulhub/blob/master/joomla/CVE-2017-8917/README.zh-cn.md安装vulhub,然后cdvulhub/joomla/CVE-2017-8917dockercomposeup-d如果报端口冲突的错可以修改文件:docker-compose.yml中的端口此时能访问http://......
  • 工作中最常见的6种OOM问题
    前言最近我写的几篇线上问题相关的文章:《糟糕,CPU100%了》《如何防止被恶意刷接口》《我调用第三方接口遇到的13大坑》发表之后,在全网广受好评。今天接着线上问题这个话题,跟大家一起聊聊线上服务出现OOM问题的6种场景,希望对你会有所帮助。1堆内存OOM堆内存OOM是最常见的OOM了......
  • 什么是布隆过滤器(Bloom Filter)?以及布隆过滤器的详细说明。
    什么是布隆过滤器(BloomFilter)?以及布隆过滤器的详细说明。布隆过滤器(BloomFilter):​ 是一种空间效率高、时间复杂度低的数据结构,用于判断一个元素是否属于一个集合。它通过使用多个哈希函数和位数组来实现快速的成员存在性检测,但有一定的误判率。结构:位数组(BitArray):布隆过......