spark 中写hdfs的异常解决

在尝试关闭HDFS的inode 16604时遇到错误,问题源于无法在现有的数据节点管道中替换故障节点。通过修改`dfs.client.block.write.replace-datanode-on-failure.policy`为`NEVER`并启用`dfs.client.block.write.replace-datanode-on-failure.enable`,最终在Spark Shell中使用Scala环境设置这两个属性解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

报错信息:

 

ERROR DFSClient: Failed to close inode 16604
java.io.IOException: Failed to replace a bad datanode on the existing pipeline due to no more good datanodes being available to try. (Nodes: current=[DatanodeInfoWithStorage[192.168.15.201:50010,DS-00e134aa-a7c3-44be-b1e2-0c75ccb7c4bc,DISK]], original=[DatanodeInfoWithStorage[192.168.15.201:50010,DS-00e134aa-a7c3-44be-b1e2-0c75ccb7c4bc,DISK]]). The current failed datanode replacement policy is DEFAULT, and a client may configure this via 'dfs.client.block.write.replace-datanode-on-failure.policy' in its configuration.
at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.findNewDatanode(DFSOutputStream.java:925)
at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.addDatanode2ExistingPipeline(DFSOutputStream.java:988)
at org.apache.hadoop.hdfs.DFSOut

### 解决方案 当使用 Spark Streaming 读取 HDFS 数据流时遇到无响应的问题,可能的原因有多种。以下是常见的原因及其对应的解决方案: #### 1. **HDFS 路径错误** 如果指定的 HDFS 路径不存在或者路径不正确,则 `textFileStream` 不会抛出异常,而是进入等待状态[^1]。 - 确认 HDFS 路径是否存在并具有正确的权限。 - 使用以下命令验证路径: ```bash hdfs dfs -ls /path/to/directory ``` #### 2. **文件入方式不符合要求** Spark Streaming 的 `textFileStream` 方法仅支持新增加的文件,并且这些文件必须是完全入完成后再移动到目标目录下[^5]。如果文件正在被入过程中就被放入监控目录,可能会导致数据丢失或无响应。 - 修改文件入逻辑,确保文件完全入完成后才移至监控目录。 - 推荐使用 Flume 或其他工具来管理日志文件的收集和传输过程[^3]。 #### 3. **时间间隔设置过短** 如果批处理的时间间隔(batch interval)设置得过短,而实际的数据到达频率较低,可能导致长时间未检测到新文件从而表现为“无响应”。 - 增大批次间隔参数 `Seconds(n)` 的值以匹配数据流入速度。 - 示例调整代码如下: ```scala val context: StreamingContext = new StreamingContext(conf, Seconds(30)) ``` #### 4. **网络连接问题** 由于分布式环境中的节点间通信依赖于稳定的网络条件,任何网络延迟或中断都可能影响 Spark Streaming 对 HDFS 文件的操作效率甚至造成失败。 - 检查集群内部各机器之间的连通性和带宽状况; - 查看是否有防火墙阻止必要的端口通讯; #### 5. **资源不足引发性能瓶颈** 当分配给 Spark 应用程序的内存或其他硬件资源配置不足以支撑当前规模的任务执行计划时,也可能表现出卡顿现象。 - 提升 Executor 和 Driver 所需最小 RAM 数量以及 Core 数目; - 合理规划 Partition 分区数目以便更好地利用多线程优势加快 I/O 密集型操作的速度。 ```scala val conf: SparkConf = new SparkConf() .setAppName("test") .setMaster("local[2]") .set("spark.executor.memory", "2g") // 设置executor内存大小 .set("spark.driver.memory", "1g") // 设置driver内存大小 ``` --- ### 实现改进后的完整示例代码 下面提供了一个经过优化后能够有效应对上述潜在风险因素版本的应用实例: ```scala import org.apache.spark.SparkConf import org.apache.spark.streaming.{Seconds, StreamingContext} object ImprovedStreamingApp { def main(args: Array[String]): Unit = { // 初始化配置项 val conf: SparkConf = new SparkConf() .setAppName("ImprovedStreamingApp") .setMaster("local[*]") // 生产环境中应改为yarn模式 .set("spark.executor.memory", "4g") .set("spark.driver.memory", "2g") // 创建Streaming Context对象 并定义每批次时间为60秒 val ssc: StreamingContext = new StreamingContext(conf, Seconds(60)) try{ // 定义输入源为HDFS上的特定目录 val linesDStream = ssc.textFileStream("/user/data/input/") // 进行简单的词频统计作为业务逻辑演示部分 val words = linesDStream.flatMap(_.split(" ")) val pairs = words.map(word => (word, 1)) val wordCounts = pairs.reduceByKey(_ + _) // 输出结果到控制台查看效果 wordCounts.print() // 开始接收事件流直到手动停止为止 ssc.start() ssc.awaitTermination() }catch{ case e : Exception => println(s"Error occurred during processing:${e.getMessage}") } } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值