HDFS的读写限流方案
前言
其实对于HDFS中的限流问题,我在之前的一篇文章Hadoop内部的限流机制已经提到过一次.上次我在文章末尾提到了针对Hadoop内部普通读写操作限流的假设以及由此可能会造成的问题.但是我后来还是仔细想了一下,有的时候还是需要进行测试一下才能得到真正的结果.而且正巧的是,最近我们碰到了一个严峻的问题,我们的集群有的时候一跑几个大的任务,就会把机房网络带宽瞬间打满,导致线上部分服务抖动.所以我们就想到了在HDFS对普通读写的限流.所以说,本文可以实质上说是一篇总结报告,阐述了方案的设想,实现以及结果.
使用场景
集群大任务运行时,打满网络带宽,导致影响到其他业务方的服务运行.
限流方案实现要点以及可能造成的影响
这里其实有2个子方面的内容,1个是方案实现中要考虑的因素和可能后果影响.这里先来看第一个方面.
实现要点
以下是我总结出的几个需要额外注意的点
限流的途径应该是远程读和普通写操作而不应该包括本地读的操作.在HDFS中,任何读写操作都会尽可能的选择本地的方式进行读写,这样可以避免走网络通信,所以本地读在读操作中占的比例还是很高的.所以在这一点上,需要进行过滤,否则很容易”误伤”,导致无效的带宽限制.而普通的写操作我们大体上可以看作是分布式的写操作了,直接限流就可以了.
需要新增动态调整限流带宽的管理命令,操作命令应该类似设置带宽的命令dfsadmin -setBandwidth.因为有的时候,我们对集群进行限流只是在特定的期间或特定的时段,其余正常的时段能够进行关闭,需要能够有动态的调整手段,而不是每次需要重启DataNode进程服务.
IPC通信的超时时间需要增大.这一点是之前Hadoop内部限流文章我没有提到的一点,这点也是我们在真实测试使用时发现的一个问题.当限流功能打开的时候,因为一个写操作都是以pipeline的形式写到3个节点中的,所以限流会导致拖慢当前节点,进而拖慢这节点的下游节点,所以有的时候会引起IPC通信的超时,会出现Socket Timeout的现象.而且如果许许多多的文件读写变慢,也会使整体集群的吞吐量下降.
限流方案实现
限流方案的实现我不会仔细给出具体的代码实现细节,我会给出一份patch补丁文件在文章的末尾,这个patch的原型是Hadoop社区上的Issue HDFS-9796,基于这个最初的改动,我们加入了自身的额外需求.(patch可能不能直接apply到别的版本的HDFS源码中,但是读者们可以看着做对照的更改).下面我主要说明一下其中的细节原理以及实现.
1.DataXceiver的readBlock,writeBlock的限流.之前也提到过,在HDFS中做普通读写的限流其实非常简单,只要在所有读写操作的方法的前一步,传入一个限流器对象即可.这个限流器对象与Balance数据限流器是同一个实现类.而读操作经过的是readBlock方法,而写操作则是writeBlock.所以我们要新建一个dataThrottler的限流器对象,以参数的形式传入这2个方法,同时在readBlock的时候,一定要判定是否为本地读的情况,如果是则传入null代表不限流.判断的核心是下面这行代码,通过Socket连接对象类型来做依据
DataTransferThrottler dataThrottler = peer.isLocal() ? null : dataXceiverServer.dataThrottler;
2.新增动态设置限流带宽速率的命令.动态设置限流带宽命令的目的在上文中已经提到过了,还是非常有必要的,实现的原理几乎与setBandwidth如出一辙,通过dfsadmin设置带宽的命令将目标带宽值发送给Namenode,然后NameNode通过心跳的方式将更新的带宽发送到每个DataNode上并进行更新,但是这种方式唯一的缺点是都是统一设置的,不会有差异性.如何新增dfsadmin管理命令,可以阅读我的另外一篇类似文章YARN批处理方式kill Applications解决方案,需要更改pb协议的.
限流测试结果
这个patch完成之后,我们把他打入到了我们内部的hadoop版本中,并重新进行了编译,打包,发布.我们发现了一些有意思的现象.
当我们只对其中的1台节点打开限流操作后,影响其实看不出来有多大,我们用hadoop fs -put大文件的方式进行测试,一切正常.而当我们对集群中所有的hdfs的jar进行更新并全部进行限流到10m的测试,试验结果还是很明显的,put大文件的时候从之前的耗时几秒到测试时的几分钟.
总结回顾
线上集群测试的结果还是能够显示出在中小规模集群中对HDFS进行限流还是能够起到一定作用的.但是注意我这里带上了一个前提,中小规模集群,如果是集群节点数过1w+的大规模集群,可能会遇到如上文中提到的拖慢整个集群的问题.所以在这一点上,社区也没有将HDFS-9796合入到主干代码,原因也大致在于此,对于HDFS的内部限流,仍然需要更好的,考虑更周全的限流方案.
相关链接
1.https://issues.apache.org/jira/browse/HDFS-9796
2.https://github.com/linyiqun/open-source-patch/blob/master/hdfs/others/HDFS-dataThrottler/HDFS-dataThrottler.patch