OopsOutOfMemory 盛利's Blog
专注大数据领域,分布式计算,Spark Contributor
<原创文章>

海量小文件网络传输copy优化

盛利的博客
, in 19 November 2014

今天部署集群环境,拷贝了一下编译好的文件

利用scp拷贝这个文件环境,然后分发到2个节点上去,然后就是刷屏的log,小文件一个一个被传输。 但是速度极慢,突然发现我忘记了,编译出来的类文件太多了,这样拷贝非常慢,马上联想到hadoop中要避免map的输出有很多小文件,因为随后要进行网络传输。

查到问题总结出2个原因:

  1. 磁盘IO寻址: 原因: 因为小文件太多,造成了大量的磁盘IO,意味着大量的开和关。磁盘的寻道和寻址都要占据很大一部分时间。 就好比洗衣服一样,洗好多件衣服比洗一件衣服要慢很多,因为很多时间都浪费在你去找衣服的时间里了。

  2. TCP慢启动 原因: 我们对每个文件都采用独立的TCP连接来传输(循环使用scp拷贝就是这个例子的实际场景,很常见的用法)。那么工作过程应该是,每传输一 个文件建立一个连接,然后连接处于慢启动阶段,传输小文件,每个小文件几乎都处于独立连接的慢启动阶段被传输,这样传输过程所用的TCP包的总量就会增 多。更细致的说一说这个事,如果在慢启动过程中传输一个小文件,我们可能需要2至3个小包,而在一个已经完成慢启动的TCP通道中(TCP通道已进入在高 速传输阶段),我们传输这个文件可能只需要1个大包。网络拷贝文件的时间基本上全部消耗都在网络传输的过程中(发数据过去等对端ACK,ACK确认归来继 续再发,这样的数据来回交互相比较本机的文件读写非常耗时间),撇开三次握手和四次握手那些包,粗略来说,慢启动阶段传输这些文件所用的包的数目是高速通 道传输这些文件的包的数目的2-3倍!那么时间上应该也是2-3倍的关系!如果文件的量足够大,这个总时间就会被放大到需求难以忍受的地步。 因此,在迁移海量小文件的需求下,我们不能使用“对每个文件都采用独立的TCP连接来传输(循环使用scp拷贝)“这样的策略,它会使每个文件的传输都处于在一个独立TCP的慢启动阶段。

优化策略:

很简单,尽量把大量小文件放在一个TCP连接中排队传输。起初的一两个文件处于慢启动过程传输,后续的文件传输全部处于高速通道中传输,用这样的方式来减少发包的数目,进而降低时间消耗。

实际上这种传输策略带来的性能提升的功劳不仅仅归于避免慢启动,事实上也避免了大量的3次握手和四次握手,这个对海量小文件传输的性能消耗也非常致命,但是这是另一个问题,本篇不多加介绍。

随着多核服务器的兴起,以及现代网卡的多通道技术的迅猛发展,现在我们解决这一问题的通常做法是绑定多CPU的多核到网卡的多个通道,然后由CPU的核来均分传输这些小文件,每个核用一个TCP连接来排队发送分到的小文件。

[参考文献]

关于本文慢启动的部分,参考自TCP性能优化之避免慢启动。

(The End)
<原创文章> From OopsOutOfMemory 盛利's Blog
转载请注明出自: http://oopsoutofmemory.github.io/hadoop/2014/11/19/hai-liang-xiao-wen-jian-wang-luo-chuan-shu-copy-you-hua