Nodemanager堆内内存泄漏问题记录
2017-02-08 12:26
162 查看
一.问题发现:
发现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,/da c7c8 ta6/hadoop/local,/data7/hadoop/local,/data8/hadoop/local,/data10/hadoop/local,/data11/hadoop/local |
和新传进来的的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由于是新的对象
所以得不到更新。
三.解决方法:
相关文章推荐
- 通过命令来查看NameNode的状态(是Active还是Standby)
- node nvm
- 浅析 Node.js 的 vm 模块以及运行不信任代码
- 浅析 Node.js 的 vm 模块以及运行不信任代码
- node包管理工具-----npm
- LintCode Search Graph Node
- Nodejs实现短信验证码
- NodeJS Stream的双工流
- node调用winRAR应用程序解压
- NodeJS Stream 五:双工流
- Route Between Two Nodes in Graph
- 用nodeJS搭建本地文件服务器的几种方法
- 借助Nodejs探究WebSocket
- HPC GPU Node:
- 构建nodejs环境及解决node服务器外网端口无法访问
- Nodejs的exports和module.exports
- NodeMCU启动之后出现短时乱码的解释
- 启动Hadoop时,DataNode启动后一会儿自动消失的解决方法
- 使用Nodejs在Windows上调用CMD命令
- 学习NodeJs一讲——模块