DistCp(分布式拷贝)是用于大规模集群内部和集群之间拷贝的工具。 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成。 它把文件和目录的列表作为map任务的输入,每个任务会完成源列表中部分文件的拷贝
问题描述
使用distcp工具将老的hdfs集群上的文件夹迁移到新hdfs集群上,经常出现在map跑到一定阶段后报错"java.lang.OutOfMemoryError: unable to create new native thread",并且因为是提交到yarn上面跑,所以表现出来的是yarn的nodemanager进程挂掉,一般迁移的目录下文件数量超过10万个时极容易出现此问题。
问题分析
1.通过报错的表面信息首先想到的是集群内存不足,查看集群每台机器的内存,可以看到每台机器还有几个G的剩余内存,基本可以排除内存不足的问题。
2.通过网上查资料发现此报错也有可能是创建的线程数过多,达到了系统设置的阀值而无法创建新线程报错。通过网上的资料准备验证下是否因为线程数上限而导致报错。
系统线程数限制有以下因素:
/proc/sys/kernel/pid_max #(操作系统线程ID的最大值)系统支持的最大线程数----即系统PID号数值的限制,全局参数
/proc/sys/kernel/thread-max #表示内核所能使用的线程的最大数目----即系统的总线程数限制,全局参数
max_user_process(ulimit -u) #系统限制某用户下最多可以运行多少进程或线程----此参数受全局参数影响
/proc/sys/vm/max_map_count #单个程序所能使用内存映射空间的数量限制----单个JVM最大能开启的线程数为此值一半
3.查看服务器上相关参数pid_max值为32678,其他几个参数都超过10万,所以准备验证pid_max参数是否为限制所在
4.重新执行distcp拷贝命令,并实时观察每台机器的线程数量,通过pstree -p命令可以列出当前系统中所有的线程
(1)刚开始时,线程数量在5000以下
(2)大约6分钟过后,线程数量已增长到2万多,且其中一台机器已经到了3万 ,此时distcp开始报错,nodemanager进程也开始报错
distcp执行的map阶段开始报错
对应172.24.26.20机器的nodemanager日志也出现报错
(3)172.24.26.20节点的nodemanager进程报错退出后,线程数开始释放,确定在3万左右的时候为线程数极限
(4).修改服务器的pid_max值为50000,重新测试
(5)重新执行distcp操作,观察到线程数可突破到4万 还未报错
问题解决
1.通过分析确定排除集群内存不足问题
2.确定是由于服务器的/proc/sys/kernel/pid_max默认值为32768限制,在文件数量非常多的情况下导致线程数超过系统限制而报错
3.增大/proc/sys/kernel/pid_max的值,同时注意其他几个限制线程的参数
最后此次虽然通过调整线程数解决了这个问题,但是最终的原因还是因为客户的小文件数量过多导致,因为一个小文件就必须由一个map来完成,所以当小文件过多时就会启动非常多的map任务,可通过har归档方式将小文件合并后再进行distcp迁移,可参考http://www.mamicode.com/info-detail-2381918.html