在AWS EMR通过Oozie运行Apache Crunch Job时HDFS写入异常
背景
- 在AWS EMR上运行Apache Crunch任务
- 该任务是Oozie主工作流中子工作流的Java Action,主工作流包含多个顶层Java Action,以及一个带fork/join步骤的子工作流,出问题的是子工作流内的某个Java Action
- 任务逻辑:从HDFS读取数据到PCollection,处理后将PCollection写入HDFS
问题
执行PCollection.write操作后,HDFS目标目录仅生成_SUCCESS文件,无实际数据写入。
测试情况
编写测试逻辑:生成包含3个字符串的PCollection,转大写后写入HDFS。将该逻辑分别加入顶层Java Action和子工作流的目标Java Action:
- 顶层Java Action可正常写入数据
- 子工作流中的目标Java Action仍仅生成
_SUCCESS文件,无数据
Oozie工作流结构示例
- 主工作流
- Java动作1(指定运行的Java类)
- Java动作2(指定运行的Java类)
- Java动作3(指定运行的Java类)
- 子工作流1(包含fork/join步骤)
- 子工作流内Java动作1(指定运行的Java类)→ 出现写入异常的任务
- 子工作流内Java动作2(指定运行的Java类)
- Java动作4(指定运行的Java类)
- Java动作5(指定运行的Java类)
- 其他步骤
排查与解决方向
检查子工作流的Hadoop配置传递
Oozie子工作流可能未正确继承主工作流的Hadoop核心配置,或者子工作流的job.properties缺失必要参数(如mapreduce.framework.name、yarn.resourcemanager.address等)。可在子工作流的Java Action中打印当前配置,对比顶层Java Action的配置差异:Configuration conf = new Configuration(); System.out.println("MapReduce框架模式: " + conf.get("mapreduce.framework.name")); System.out.println("YARN资源管理器地址: " + conf.get("yarn.resourcemanager.address"));强制指定Crunch集群运行模式
若子工作流中Crunch默认使用本地模式运行,数据会写入本地磁盘而非HDFS,最终仅生成_SUCCESS文件。需强制指定集群模式:// 传入集群环境的Configuration对象 Pipeline pipeline = new MRPipeline(YourCrunchClass.class, conf);验证HDFS目录权限与覆盖设置
子工作流运行用户可能无HDFS目标目录的写入权限,或目录已存在但未开启覆盖。可在代码中添加目录清理逻辑,或在Oozie的Java Action配置中设置oozie.action.hdfs.deleteDestination=true:Path outputPath = new Path("hdfs://your-target-path"); FileSystem fs = FileSystem.get(conf); if (fs.exists(outputPath)) { fs.delete(outputPath, true); }查看Crunch作业的YARN日志
在EMR控制台的YARN日志中,查找子工作流Java Action对应的Crunch作业日志,检查是否有Map/Reduce任务执行记录,是否存在静默异常(如数据处理逻辑未触发、任务失败但被Oozie标记为成功)。调整fork/join步骤的资源配置
若fork步骤的并发任务存在资源竞争,可能导致Crunch作业的Map/Reduce任务未被正常调度。可修改fork步骤的并发数,或在子工作流的Java Action中增加资源参数(如mapreduce.map.memory.mb、mapreduce.reduce.memory.mb)。
内容的提问来源于stack exchange,提问作者Stefan Ss

