【告警现象】本人在使用hadoop2.7.3 执行hdfs balancer的时候,出现了以下告警:
java.io.IOException: Got error, status message Not able to copy block 1073778252 to /172.13.6.52:30810 because threads quota is exceeded
【告警原因】
1,在小于hadoop2.6的版本,有一个bug,就是:过早退出balancer的迭代过程。所以从hadoop2.6.0开始就修复了该问题。
2,Data nodes会限制负载均衡器的线程数目,以防止耗光hdfs集群的所有资源,这就是产生这个告警的原因(此线程数默认值为5)。在hadoop 2.5及之前的版本,这个线程数目可通过修改dfs.datanode.balance.max.concurrent.moves来配置。
【解决办法】
1,hadoop2.5版本以及之前的版本
# 调大dfs.datanode.balance.max.concurrent.moves的值,例如改成60
# 修改dfs.datanode.balance.bandwidthPerSec的值,例如改成52428800,即50M,如果带宽允许,可调高到100Mb
# 修改dfs.datanode.max.transfer.threads的值,例如4096 (如果运行hbase的话建议改成16384)
# 到HDFS的web UI实时查看DataNode的负载状况,可以查看overview页面的Summary里的Data Nodes usages% (Min/Median/Max/stdDev)然后通过调整Balancer上的上述配置值来控制整体速度即可。
2,hadoop2.6版本及之后的版本,这里附上我的定时脚本,等到集群不忙的时候再执行(注:需要反复执行多次此脚本,以便尽可能地均衡负载、缩小各个data node之间的存储空间使用率差异)
【github代码地址】https://github.com/tonykidkid/MapReduceBackupCodes/tree/master/operateHDFS
-threshold10
此参数表示允许单个节点的存储使用率与集群中各节点平均存储使用率之间有10%的偏差。
“节点的存储使用率”意思是每个数据节点的存储使用率,它表示一个数据节点上已用空间占可用空间的百分比,所谓可用空间指的是分配给HDFS可使用的空间,并非是节点所在机器的全部硬盘空间。比如一个数据节点总共有存储空间2T,分配给HDFS的空间为1T,已经用了600G,那么“节点的存储使用率”就是600/1024=58.6%
理论上,threshold参数设置的值越小,整个集群就越平衡。但是在线上环境中,hadoop集群在进行balance时很可能有同时进行的数据写入和删除,
所以有可能无法到达设定的平衡参数值。
-Ddfs.datanode.balance.bandwidthPerSec
这个参数是设置balancer进程可用的网络带宽。如果不设置这个参数值那么这个balancer会很慢,因为默认不允许balancer占用很大的网络带宽。
【查看运行日志】
# 日志显示,Bytes Already Moved是累计计算的
# 此次rebalancer运行在name node, 耗时14分钟
[hadoop2@nn1 tmp]$ less balancer-10pct-out.log
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being MovedOct 10, 2017 7:50:44 PM Balancing took 13.721266666666667 minutes
# 下面这个rebalancer运行在data node, 耗时只需5分钟,这是因为需要迁移的数据块比刚才少了
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
Oct 10, 2017 10:20:43 PM 0 270.75 MB 345.71 GB 40 GB
Oct 10, 2017 10:20:53 PM 1 270.75 MB 345.60 GB 40 GB
Oct 10, 2017 10:21:02 PM 2 270.75 MB 345.60 GB 40 GB
Oct 10, 2017 10:21:11 PM 3 270.75 MB 345.63 GB 40 GB
Oct 10, 2017 10:21:22 PM 4 284.25 MB 345.63 GB 40 GB
Oct 10, 2017 10:21:31 PM 5 284.25 MB 345.70 GB 40 GB
Oct 10, 2017 10:21:40 PM 6 284.25 MB 345.70 GB 40 GB
Oct 10, 2017 10:21:50 PM 7 284.25 MB 345.70 GB 40 GB
Oct 10, 2017 10:21:59 PM 8 284.25 MB 345.70 GB 40 GB
Oct 10, 2017 10:22:34 PM 9 439.11 MB 345.70 GB 40 GB
Oct 10, 2017 10:22:43 PM 10 439.11 MB 345.54 GB 40 GB
Oct 10, 2017 10:22:53 PM 11 439.11 MB 345.54 GB 40 GB
Oct 10, 2017 10:23:02 PM 12 439.11 MB 345.54 GB 40 GB
Oct 10, 2017 10:23:11 PM 13 439.11 MB 345.54 GB 40 GB
Oct 10, 2017 10:23:59 PM 14 665.73 MB 345.54 GB 40 GB
Oct 10, 2017 10:24:08 PM 15 665.73 MB 345.40 GB 40 GB
Oct 10, 2017 10:24:17 PM 16 665.73 MB 345.40 GB 40 GB
Oct 10, 2017 10:24:26 PM 17 665.73 MB 345.40 GB 40 GB
Oct 10, 2017 10:24:36 PM 18 665.73 MB 345.40 GB 40 GB
No block has been moved for 5 iterations. Exiting...
Oct 10, 2017 10:24:45 PM 19 665.73 MB 345.40 GB 40 GB
Oct 10, 2017 10:24:45 PM Balancing took 4.950083333333334 minutes
【建议】
1,执行balancer的建议:尽量不要在Name Node上执行balancer,而是找一台比较空闲的机器去运行(可以从上面的日志中看到运行耗时的对比了)。
2,上传数据到hdfs集群的建议:若从某个dataNode上传数据到集群,会导致上传的数据优先写满该dataNode的磁盘,不利于运行分布式作业;但是从非dataNode上传,比如从nameNode上传数据,也不好,因为会增加namenode负担,同时造成namenode上面的文件杂乱。所以建议搞一个客户端节点,把hadoop的安装目录复制一份到此节点,不在此节点启动任何有关Hadoop的进程,只作为上传数据到hdfs集群的用途。
【相关延伸】
Hadoop Balancer的执行步骤(HDFS数据负载均衡原理),如图示
0、为避免给Name Node带来过大负担,整个re-balance过程由Rebalancing Server而不是name node来控制,
也就是说Rebalance程序作为一个独立的进程与name node分开执行
1、Rebalance Server从Name Node获取每个Data Node上的磁盘使用情况
2、Rebalance Server计算哪些节点需要将数据移动,哪些节点可接收移动的数据,Rebalance Server从Name Node中获取需要移动的数据分布情况
3、Rebalance Server计算出可将哪个节点的文件块移动到另一个节点中去,再执行移动,完成后删除旧的文件块信息
4~6、需要移动文件块的节点把数据移动到目的节点,再删除本节点上的block数据
7、Rebalance Server获取到本次数据移动的执行结果,并继续执行这个过程,直到没有数据可以移动或者HDFS集群达到平衡的标准(threshold的值)