java.io.IOException: Xceiver count xxxx exceeds the limit of concurrent xcievers: xxxx
dfs.datanode.max.transfer.threads
参数用来设置 DataNode 处理读写数据流的线程池大小,默认值为 4096 个。如果该参数设置太小,会导致 DataNode 出现 Xceiver 数量限制的异常。
在 KDP 的 HDFS 应用配置 hdfsSite 节点内查看参数 dfs.datanode.max.transfer.threads
,并适当地调大该参数值,一般建议翻倍增加,例如 8192、16384。
DataXceiver error processing WRITE_BLOCK operation src: /10.*.*.*:35692 dst: /10.*.*.*:50010 java.io.IOException: Premature EOF from inputStream
通常为了不断地向 HDFS 写入新的数据,作业会打开较多的 HDFS 文件写入流(Stream)。但 HDFS 允许同时打开的文件数量是有限的,受限于 DataNode 参数,超过限制就会出现 DataXceiver Premature EOF from inputStream 异常。
查看 DataNode 日志,一般会有如下报错。
java.io.IOException: Xceiver count 4097 exceeds the limit of concurrent xcievers: 4096
at org.apache.hadoop.hdfs.server.datanode.DataXceiverServer.run(DataXceiverServer.java:150)
如果存在报错,在 KDP 的 HDFS 应用配置 hdfsSite 节点内查看参数 dfs.datanode.max.transfer.threads
,并适当地调大该参数值,一般建议翻倍增加,例如 8192、16384。
报错信息如下所示。其中,【X】是当前正在运行的 DataNode 数量,【Y】是被排除在此操作之外的 DataNode 数量。
org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /foo/file1 could only be written to 0 of the 1 minReplication nodes,there are 【X】 datanode(s) running and 【Y】 node(s) are excluded in this operation.
该问题表示在当前的集群状态下,因为无法满足文件的最小副本数量,HDFS 无法将文件写入到指定路径中。
如果【Y】不为 0,说明某些 DataNode 节点被 HDFS 客户端排除,需要检查 DataNode 节点的负载是否过高。DataNode 负载过高时或者 DataNode 本身容量太小,同时写入多个文件会导致 DataNode 无法处理 NameNode 的分块请求,需要对 DataNode 进行扩容。
如果【X】不为 0,并且【X】>【Y】,可检查以下方面。
如果 DataNode 数量较少(少于 10 台)或容量较满,并且集群中存在大量写入小文件的作业,可能会导致 NameNode 无法找到合适的 DataNode 节点进行写入。这种情况常见于 Flink Checkpoint 写入 HDFS;Hive 或 Spark 动态分区写入作业需要大量分区的场景。
为了解决这个问题,您可以增加集群中 DataNode 的数量或者容量。推荐扩容 DataNode 的数量,一般情况下可以快速解决此类问题,并且后续进行缩容也更加方便,从而更好地满足大量小文件的写入需求。
java.io.IOException: Unable to close file because the last block xxx:xxx does not have enough number of replicas.
一般是由于 DataNode 写入负载过大引起的,数据块不能及时上报。
建议按照以下方式排查解决:
查看 HDFS 配置
在 KDP 的 HDFS 应用配置查看 hdfsSite 节点中的 dfs.client.block.write.locateFollowingBlock.retries
(写入块后尝试关闭的次数)参数的配置。默认为 5 次(30 秒),推荐设置为 8 次(2 分钟),负载高的集群可以视情况继续调大。
说明:调大
dfs.client.block.write.locateFollowingBlock.retries
参数值,在节点繁忙时会延长文件 close 的等待时间,正常写入不受影响。
确认集群中是否是只有少量 DataNode 节点,大量 task 节点的情况。如果大量并发提交作业,会有大量 JAR 文件需要上传,可能会导致 DataNode 瞬时压力大,可以继续调大 dfs.client.block.write.locateFollowingBlock.retries
参数值或者增加 DataNode 数量。
说明:调大 dfs.client.block.write.locateFollowingBlock.retries 参数值,在节点繁忙时会延长文件 close 的等待时间,正常写入不受影响。
确认集群中是否有大量消耗 DataNode 的作业。例如 Flink Checkpoint 会大量创建和删除小文件,引起 DataNode 负载过大。此类场景可以把 Flink 运行在独立的集群上,Checkpoint 会使用独立的 HDFS,或者使用 OSS/OSS-HDFS Connector 优化 Checkpoint。
HDFS 依赖 FsImage Checkpoint 进行 editlogs 合并,当 FsImage Checkpoint 出现异常时,会导致 editlogs 无法合并,通常异常情况是由于 FsImage 目录写满或磁盘异常等情况引起的,此时 NameNode 重启时间也会变得很长。NameNode FsImage Checkpoint 失败后,该 FsImage 目录默认不会再次使用,需要设置开启 FsImage 目录自恢复功能。
进入任意 hdfs 容器,手动开启 FsImage 目录自恢复选项。
hdfs dfsadmin -restoreFailedStorage true
说明:手动开启 FsImage 目录自恢复选项,重启后失效。
开启成功后 NameNode 后续自动 FsImage Checkpoint 时,会先尝试恢复 FsImage 目录。
也可以默认开启 FsImage 目录自恢复功能。
在 KDP 的 HDFS 应用配置查看 hdfsSite 节点中,添加参数为 dfs.namenode.name.dir.restore
,值为 true
的自定义配置,下次重启 NameNode 后 FsImage 目录自恢复功能会自动打开。
以下是当 NameNode 启动后,NameNode 无法退出 safemode 状态的原因及解决方案。
NameNode 日志或者 HDFS WebUI 上出现以下报错信息,将无法退出 safemode,导致 HDFS 服务整体基本不可用。
Safemode is ON.The reported blocks xxx needs addition ablocks to reach the threshold 0.9990 of total blocks yyy
该问题通常是由于 DataNode 上报的数据块未达到总量的阈值比例(默认为 0.999f),导致 NameNode 无法退出 safemode。首先需要确认所有 DataNode 是否已正常启动,如果 DataNode 进程没有问题,问题可能出在以下两个方面:
方案一:通过 hdfs 命令手动退出 safemode。
hdfs dfsadmin -safemode leave
方案二:通过修改以下配置项适当调低阈值比例,在 KDP 的 HDFS 应用配置的 hdfsSite 节点中增加
"dfs.namenode.safemode.threshold-pct": "0.9f"
说明:上述参数值 0.9f 只是举例,实际使用中请您根据具体情况来调整 dfs.namenode.safemode.threshold-pct 参数的值。