Flink在HDFS上写入会产生空文件

时间:2015-12-17 07:27:37

标签: hadoop apache-flink

我有一个flink作业,它使用TextOutputFormat将数据写入目标。代码是这样的:

   String basePath = "/Users/me/out";
   // String basePath = "hdfs://10.199.200.204:9000/data";
   // ensure we have a format for this.
   TextOutputFormat<String> format = new TextOutputFormat<>(new Path(basePath, selection + "/" + uid));
   StreamingRuntimeContext context = (StreamingRuntimeContext) getRuntimeContext();
    format.configure(GlobalConfiguration.getConfiguration());
    format.open(context.getIndexOfThisSubtask(), context.getNumberOfParallelSubtasks());
   // then serialize and write.
   String record = serializationFunction.map(value);
   log.info("Writing " + record);
   format.writeRecord(record);

当在普通文件系统上使用路径作为目标时,这非常正常。但是,当我将基本路径更改为hdfs位置时,它不再按预期工作。会发生的是,输出文件实际上是在HDFS上创建的,但它的大小为零字节。我在电话会议期间没有任何例外。

我正在使用Hadoop 2.6.0和Flink 0.10.1。使用命令行工具(hadoop fs -put ...)将文件复制到hdfs是有效的,所以我想我可以排除一些Hadoop配置错误。我也开始使用Wireshark并看到数据被传输到Hadoop服务器,所以在实际写入之前我是否需要提交一些数据?

2 个答案:

答案 0 :(得分:2)

为了将结果清除为HDFS,您必须在完成记录后调用close的{​​{1}}方法。

TextOutputFormat

答案 1 :(得分:0)

我发现了它为什么会发生。实际上有两个原因:

  1. Till Rohrmann指出,输出格式没有刷新。由于我在流媒体作业中使用该格式,因此关闭格式是没有选择的。我使用了自己的格式,可以刷新:

    public class MyTextOutputFormat<T> extends TextOutputFormat<T> {
        public MyTextOutputFormat(Path outputPath) {
            super(outputPath);
        }
    
        public MyTextOutputFormat(Path outputPath, String charset) {
            super(outputPath, charset);
        }
    
        // added a custom flush method here.
        public void flush() throws IOException {
            stream.flush();
        }
    }
    
  2. 我在VM guest虚拟机中运行HDFS并从VM主机连接到它。 Flink的HDFS客户端默认使用datanode的IP地址连接到数据节点。但是,datanode的IP地址报告为127.0.0.1。所以flink尝试连接到127.0.0.1,当然主机系统中没有运行HDFS datanode。然而,这仅在我添加手动冲洗操作后显示。为了解决这个问题,我不得不改变两件事:

    • 在VM来宾中,修改$HADOOP_HOME/etc/hadoop/hdfs-site.xml并添加

      <property>
          <name>dfs.datanode.hostname</name>
          <value>10.199.200.204</value> <!-- IP of my VM guest -->
      </property>
      

      此更改使namenode报告成为datanode的正确可路由主机名。它实际上是一个没有文档的设置,但似乎工作。

    • 在实际运行flink的系统上,我必须在文件夹中创建hdfs-site.xml(例如/home/me/conf),然后必须设置指向的环境变量HADOOP_CONF_DIR /home/me/conf。该文件包含以下内容:

      <?xml version="1.0" encoding="UTF-8"?>
      <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
      <configuration>
          <property>
              <name>dfs.client.use.datanode.hostname</name>
              <value>true</value>
          </property>
      </configuration>
      

      此更改指示hadoop客户端使用主机名而不是ip地址连接到datanode。在这些更改之后,我的数据被正确写入HDFS。