Hadoop Flink在HDFS上写入生成空文件

Hadoop Flink在HDFS上写入生成空文件,hadoop,apache-flink,Hadoop,Apache Flink,我有一个flink作业,它使用TextOutputFormat将数据写入目标。代码如下所示: String basePath=“/Users/me/out”; //字符串基本路径=”hdfs://10.199.200.204:9000/data"; //确保我们对此有一个格式。 TextOutputFormat=新的TextOutputFormat(新路径(基本路径,选择+“/”+uid)); StreamingRuntimeContext=(StreamingRuntimeContext)ge

我有一个flink作业,它使用TextOutputFormat将数据写入目标。代码如下所示:

String basePath=“/Users/me/out”;
//字符串基本路径=”hdfs://10.199.200.204:9000/data";
//确保我们对此有一个格式。
TextOutputFormat=新的TextOutputFormat(新路径(基本路径,选择+“/”+uid));
StreamingRuntimeContext=(StreamingRuntimeContext)getRuntimeContext();
format.configure(GlobalConfiguration.getConfiguration());
format.open(context.getIndexOfThisSubtask(),context.getnumberofparallelsubtask());
//然后序列化并写入。
String record=serializationFunction.map(值);
日志信息(“写入”+记录);
格式.写入记录(记录);
当使用普通文件系统上的路径作为目标时,这种方法非常有效。但是,当我将基本路径更改为hdfs位置时,它不再像预期的那样工作。实际情况是,输出文件实际上是在HDFS上创建的,但其大小为零字节。我在通话中没有收到任何异常


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

为了将结果刷新到HDFS,在完成记录写入后,必须调用
TextOutputFormat
close
方法

//写
虽然(某些条件){
格式.写入记录(记录);
}
//写完
format.close();

我找到了它发生的原因。其实有两个原因:

  • 输出格式没有刷新,直到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();
        }
    }
    
    此更改使namenode报告datanode的正确可路由主机名。这实际上是一个未记录的设置,但似乎有效

  • 在flink实际运行的系统上,我必须在文件夹中创建一个
    hdfs site.xml
    (例如
    /home/me/conf
    ),然后必须设置一个环境变量
    HADOOP\u conf\u 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>
    
    
    dfs.client.use.datanode.hostname
    真的
    
    此更改指示hadoop客户端使用主机名而不是ip地址来连接到datanode。在这些更改之后,我的数据被正确地写入HDFS

  • <?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>