线上系统/tmp 目录不断增长分析与总结
1、问题描述
系统配置为单核4G, web 工程配置堆2G, /tmp目录 二进制文件不断增加,平均一天增加20G, 手动清理/tmp目录,重启系统,问题依旧。
2、分析
2.lsof -p pid 确定tmp文件都被进程id为10791的同一个Java进程打开。
根据上面的分析,这些文件应该是该进程的临时文件,而且不断在增加,有可能是文件句柄泄露。
查看该进程的句柄图
12.15号,系统打开的句柄数量在逐步的增加,而且没有出现相对平稳的迹象,确定是句柄泄露了,这印证了我们的猜想。
下来需要进一步分析究竟是什么原因造成的句柄泄露。
谷歌搜索关键字,确定FlateDecode是解码 PDF stream 的一个工具。查看程序中引用相关pdf的代码,如下图所示:
public static byte[] transfer(byte[] bytes, int pageNum) throws IOException { LOG.info("PDF合同转IMAGE开始...pageNum={}", pageNum); PdfDecoder decode_pdf = new PdfDecoder(true); decode_pdf.scaling = 1.5F; FontMappings.setFontReplacements(); byte[] outbytes = new byte[0]; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { decode_pdf.openPdfArray(bytes); //bytes is byte[] array with PDF BufferedImage img = decode_pdf.getPageAsImage(pageNum); ImageIO.write(img, "jpg", out); outbytes = out.toByteArray(); LOG.info("PDF合同转IMAGE成功...pageNum={}", pageNum); } catch (Exception e) { LOG.error("PDF合同转IMAGE异常...pageNum={},e={}", pageNum, e); } finally { out.close(); } return outbytes;} |
这段代码用来将pdf转化成一个jpg的图片,使用了jpedal第三方库。
jpedal是一个开源的纯Java的PDF文档解析库,可以用来方便的查看和编辑文字和图片。
回到代码, 按照以往编码的经验,有可能是PdfDecoder没有释放资源,导致生成的临时文件一直没有释放掉。查看jpedal文档,发现的确提供了closePdfFile 关闭pdf文件的方法。
finally 块里添加
decode_pdf.flushObjectValues(true);
decode_pdf.closePdfFile();
重新发版,发现之后句柄图达到了相对平稳的状态,tmp目录也不再继续增加临时文件。
虽然问题解决了,但是还有一些困惑。临时文件怎么生成的?page fault为啥这么多?
1、临时文件到底是怎么生成的?
decode_pdf.openPdfArray(bytes) 根据传进来的字节流 打开pdf文件,

jpedal在这里做了一个优化,当pdf文件小于16k时或者alwaysCacheInMemory = -1时,直接内存缓存该pdf。
当pdf文件的大小大于16k时,会在临时目录下生成一个前缀为page,后缀为bin的二进制文件,该临时目录由系统参数 java.io.tmpdir 指定,默认在/tmp目录下。
这样,由于线上环境的pdf基本都大于16k,所以/tmp目录下就会看到不断的临时文件生成。这个临时文件命名规则为page***.bin。
2、添加closePdf文件之后,为啥问题就解决了呢?
closePdf会调用PdfReader的closePdfFile()方法,该方法根据缓存的临时文件名称删除该临时文件。

3、未关闭pdf文件,为啥会引起较多的page fault呢?
page fault 分为 minor page fault 和major page fault。
major page fault也称为hard page fault, 指需要访问的内存不在虚拟地址空间,也不在物理内存中,需要从慢速设备载入。从swap回到物理内存也是hard page fault。
minor page fault也称为soft page fault, 指需要访问的内存不在虚拟地址空间,但是在物理内存中,只需要MMU建立物理内存和虚拟地址空间的映射关系即可。
(通常是多个进程访问同一个共享内存中的数据,可能某些进程还没有建立起映射关系,所以访问时会出现soft page fault)
正常情况下,系统也会有一些pagefault,如下图所示:

,所以pagefault和该问题没有直接关系。minflt表示从内存加载数据时每秒出现的小的错误数目,可以忽略。如果majflt较大,表示从磁盘载入内存页面,发生了swap,此时需要关注。
3、总结
我们详细的回顾了此次线上发生的问题,以及如何去定位,然后去解决问题的整个过程。
(1)问题发现,收到系统磁盘空间不足的报警。
(2)问题定位,先根据du确认是tmp目录增长过快的问题,然后根据lsof和进程句柄图确定是文件句柄泄露,再根据临时文件的文件内容,定位相关的源代码,查看源代码,确认是文件句柄资源没有正确释放。
(3)解决问题,查看api,确认是资源泄露的问题,修复代码上线。
线上系统/tmp 目录不断增长分析与总结的更多相关文章
- CentOS系统/tmp目录里面的文件默认保留多久
一.CentOS系统/tmp目录里面的文件默认保留多久 CentOS6默认保留30天,CentOS7默认保留10天 一.CentOS7系统/tmp目录里面的文件默认保留多久 CentOS7默认保留10 ...
- 线上BUG:MySQL死锁分析实战
原文链接:线上BUG:MySQL死锁分析实战 1 线上告警 我们不需要关注截图中得其他信息,只要能看到打印得org.springframework.dao.DeadlockLoserDataAcces ...
- 有关线上系统点击没有任何相应得问题思考,主要针对PC端应用程序
1.问题得起因 前段时间,客户得某些机器上,点击应用系统得快捷方式,没有任何响应,不弹出程序主界面,也没有任何得报错提示,甚至程序得错误日志也没有任何输出. 当时,听说发生这种情况得时候,有点懵了,不 ...
- 线上redis服务内存异常分析。
项目中,新增了一个统计功能,用来统计不同手机型号的每天访问pv,看了下redis2.6有个setbit的功能,于是打算尝尝鲜把 redis从2.4更新到了2.6 因为是租了vps.服务器的内存只有4g ...
- Linux线上系统程序debug思路及方法
http://blog.csdn.net/wangzuxi/article/details/44766221
- HBase工程师线上工作经验总结----HBase常见问题及分析
阅读本文可以带着下面问题:1.HBase遇到问题,可以从几方面解决问题?2.HBase个别请求为什么很慢?你认为是什么原因?3.客户端读写请求为什么大量出错?该从哪方面来分析?4.大量服务端excep ...
- (转)HBase工程师线上工作经验总结----HBase常见问题及分析
阅读本文可以带着下面问题:1.HBase遇到问题,可以从几方面解决问题?2.HBase个别请求为什么很慢?你认为是什么原因?3.客户端读写请求为什么大量出错?该从哪方面来分析?4.大量服务端excep ...
- 排查Java线上服务故障的方法和实例分析
前言 作为在线系统负责人或者是一个技术专家,你可能刚刚接手一个项目就需要处理紧急故障,或者被要求帮忙处理一些紧急的故障,这个时候的情景是: (1)你可能对这个业务仅仅是听说过,而不怎么真正了解: (2 ...
- erlang 线上分析工具集锦
1.Recon-Erlang线上系统诊断工具(引自): Erlang系统素以稳定可靠闻名,但是它也是c实现的,也是要管理比如内存,锁等等复杂的事情,也会出现Crash,而且crash的时候大部分原因是 ...
随机推荐
- springMVC学习总结(一)快速入门
springMVC学习总结(一)快速入门 一.初步认识 springMVC执行流程 主要组件 DispatcherServlet(中央控制器) 配置在web.xml中的前端控制器,客户端请求的入口,调 ...
- sudo,visudo
visudo修改/etc/sudoers文件 用户名/%组名 主机名/主机别名/网段=(身份)命令 若(ALL)为空则为所有身份,即包含root身份 user1 ALL=/sbin/shutdown ...
- iOS中self与_的区别
同时我们发现在我们访问我们声明的变量时,会有self. 和 以"_"开头的访问方式,那么这两种方式到底有什么样的区别呢? 我们来一起看一下: @property (retain, ...
- Mybatis-Oralce批量插入方法
mybatis-Oralce 中批量插入方法一:<insert id="insertBatchSelective" parameterType="java.util ...
- JDBC 程序实例小练习
JDBC 程序实例问题 编程实现如下功能:在数据库中建立一个表,表名为student,其结构为学号.姓名.性别.年龄.英语.JavaSE程序设计.初级日语.总分,在表中输入多条记录. 学生的总分信息, ...
- mybatis的那些事
转载请注明出处:http://www.cnblogs.com/yidaijiankuanzhongbuhui/p/7003993.html 用mybatis一年多了,一直是别人搭好框架,配置好各种配置 ...
- 关于mysql的loose index scan的几点疑问
本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/102 关于MySQL的loose index scan有几点疑问 ...
- tp3.2 事务处理
事务的机制通常被概括为“ACID”原则即原子性(A).稳定性(C).隔离性(I)和持久性(D). 原子性:构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行. 稳定性:数据库在事 ...
- MYSQL忘记root密码后如何修改
方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...
- QT中定时器的使用方法
前言:因为QT中用死循环会开销很多内存容易崩溃,这时候使用定时器可以很好解决这个问题. 使用定时器需要用到头文件:include<QTimer> (1)定义定时器 QTimer *upda ...