Nodemanager堆内内存泄漏问题记录
来源:互联网 发布:电商系统源码 编辑:程序博客网 时间:2024/05/17 09:06
一.问题发现:
发现nm堆内存使用率过高:
<图一.1>
这里面可以看到老年代有大量对象未被回收。
<图一.2>
这里面有很多的这种对象,后面会一一指出他们为什么这么多。
而且横向比较这些nm的内存信息,会发现nm的内存的占用多少都是因为这些对象是线性增长的。
二.问题分析:
这些对象是在哪儿创建的呢?为什么不会被回收呢?
好的,先让我们放下这个问题,先来了解一下nm里面的localizing机制。
所谓localizing就是在启动container之前由nm负责做一些资源下载的操作。更具体一点就是container的Private类的资源下载:
比如:
<图二.1>
Nm上的这两个目录。
详细的流程就是这样:
<图二.2>
然后,我们针对最关键的LocalDirAllocator#getLocalPathForWrite方法延伸进去讲:
<图二.3>
首先需要知道,LocalDirsHandlerService是一个服务:
(Nm里多有的模块都是基于对象服务化构建起来的,
更全面的服务层次后面再介绍)
<图二.4>
在这里需要留意一下图二.3中getLocalPathForWrite方法的“getConfig()”参数。
继续往下看,在方法体中:
会先拿到context对象,这个对象负责维护全局唯一的
文件目录情况概览。为什么这么说,因为进入到代码
你会看到context是全局唯一的:
从注释可以看出,context这个map根据上下文名称存储
对应的AllocatorPerContext上下文对象,举个例子“
比如类似mapred.local.dir,或者yarn.nodemanager.local-dirs”
等。
所有nm中需要yarn.nodemanager.local-dirs这个上下文的
服务都会使用相同的AllocatorPerContext对象,比如上面介绍的
LocalDirsHandlerService服务,这一点很重要。
接着调用,context的getLocalPathForWrite(pathStr, size, conf, checkWrite)方法。
在这个方法里面只做两件事:
第一:检查当前的目录情况,
/data0/hadoop/local,/data1/hadoop/local,/data2/hadoop/local,/data3/hadoop/local,/data4/hadoop/local,/data5/hadoop/local,/data6/hadoop/local,/data7/hadoop/local,/data8/hadoop/local,/data10/hadoop/local,/data11/hadoop/local
在confchange方法里面检查的方式就是简单检查变量——savedLocalDirs
和新传进来的的conf对象里面的配置是否一致:
如果不一致,会进到if里面,重新获取本地目录。
可以看到其中有一行代码是获取本地文件系统的:
localFS = FileSystem.getLocal(conf)
那么文章最开始打出的堆栈中那么多的FileSystem对象是不是这里创建的呢?
带着这个疑问进到FileSystem.getLocal(conf)方法里看:
首先:
会构建一个默认的URI去获取FS对象:
这个LocalFileSystem.NAME即是一个“file:///”默认的本地URI
层层跟进代码会发现会创建很多个FS存在map里,即FS的一个
缓存机制,这其中会创建很多的URI,Subject,Key,UGI对象,并且
由于这些对象都是存在map里面的,所以永远不会被回收。
所以,可以确定就是这里引起了Nm内存的泄漏。
此处代码太多,就贴上来了,有兴趣的同学可以自行查看。
根本原因清楚了,现在我们回到最初的confChange方法上,
是什么原因引起了conf配置不一样呢,按理说Nm里面的每个服务都是对应的同一个
Configuration对象啊?为什么会有不一样的?
在解释这个问题之前,先看一下服务对象的层次结构:
所有服务都是由上到下递归的调用serviceInit(Configation)方法,并把Configation参数设到对象内部,所以
可以说每个服务使用的conf都是同一个对象。但是ShuffleHandler不一样,
ShuffleHandler的serviceInit方法中会新创建一个Configation:
super.serviceInit(new Configuration(conf));
在了解了这个情况之后,我们再来看ShuffleHandler会做什么事情:
其实这个类就是负责NIO数据读写的,在内部类Shuffle中
populateHeaders方法:
会去调用LocalDirAllocator类的读方法,前面说过此方法实质会调用
AllocatorPerContext对象的getLocalPathToRead读方法,而且
AllocatorPerContext是全局唯一的。所以如果conf参数不一样,会创建FileSystem
对象.
好了,基本上这个问题已经很清楚了,最后还有一点,两个conf都是出自同源,只不过在ShuffleHandler
里面把他克隆了一份,那么这两个conf(LocalDirsHandlerService和ShuffleHandler)其中哪一个会改变呢?
答案是在LocalDirsHandlerService类中会有一个自检线程,周期的扫描本地磁盘,根据磁盘情况重新组成
yarn.nodemanager.local-dirs参数值并设置到自己的conf中,但是ShuffleHandler的conf由于是新的对象
所以得不到更新。
三.解决方法:
- Nodemanager堆内内存泄漏问题记录
- nodemanager localizer进程泄漏问题
- 捉虫记录:解决内存泄漏问题
- JNI引起的堆外内存泄漏问题分析
- WebView内存泄漏记录
- 匿名内部类持外部引用造成内存泄漏问题
- 内部类Handler引发的内存泄漏问题
- 匿名内部类持外部引用造成内存泄漏问题
- 堆内存泄漏以及诊断
- 内存篇之堆泄漏
- java堆外内存泄漏
- 堆,栈,内存泄漏和内存溢出
- 堆内内存还是堆外内存?
- C#内存泄漏 非托管堆内存泄漏
- 记录一例内存泄漏
- 内存优化-内存泄漏处理内部类
- Java内存泄漏问题
- JAVA内存泄漏问题
- 查找第K大元素
- 从form的enctype属性到Content-Type再到request.getInputStream()
- 网络概述
- 微信小程序之基本配置
- Thinkpad E系列刷BIOS无法启动点亮或开机显示屏不亮解决办法
- Nodemanager堆内内存泄漏问题记录
- Hbase学习2_HBase数据同步到ElasticSearch的方案
- 机器学习实战学习提纲
- Activity与Fragment之间的生命周期方法
- tensorflow——Deep MNIST
- P1403 [AHOI2005]约数研究
- 机器学习基础—— 遗传算法(GA)
- 如何将Excel数据导入MATLAB中
- java面向对象程序设计之封装