前段时间线上的Flume突然不稳定起来,各种socket read/write timeout. Block recover也一直不成功.查看Datanode的日志确实这段时间packresponder各种连接失败,读取失败,各种异常:PrematureEOF from inputStream/Connection reset/Interrupted receiveBlock/,在某些条件下也触发坏块的产生.

奇怪的是这段时间有问题的datanode的负载,网卡IO都不高,只是出问题时datanode会伴随着high session.接着部署个集群的thread监控才发现了原因:

Datanode默认每6dfs.datanode.directoryscan.interval)小时调用DirectoryScanner去做内存和磁盘数据集块校验,而这个过程fdataset这个数据结构一直持有独占锁,导致其他的线程都被BLOCK住,而数据量越大在默认情况1个(dfs.datanode.directoryscan.threads)线程的执行时间越久.虽然在HADOOP-4584后分离了diskscanner和heartbeat sender但是还是存在共享竞争资源,所以严重情况下仍然可能导致假死.知道了原因后,把这个参数调大后可以加速扫描速度,进而降低锁的时间使得datanode快速恢复服务:

可以看到,调整后threadblock数极大降低了:

wKiom1MUsYuQxZu7AAOq5VKvJcY350.jpg


这个问题在HADOOP2.3.0改善了一部分,将getfilelength部分以async disk scan的方式获取,降低了锁定的时间.