我想在我的程序中创建一个文件。但是,我不希望这个文件写在HDFS上,而是写在执行map
操作的datanode文件系统上。
我尝试了以下方法:
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
// do some hadoop stuff, like counting words
String path = "newFile.txt";
try {
File f = new File(path);
f.createNewFile();
} catch (IOException e) {
System.out.println("Message easy to look up in the logs.");
System.err.println("Error easy to look up in the logs.");
e.printStackTrace();
throw e;
}
}
使用绝对路径,我将得到文件应该在的位置。但是,如果使用相对路径,这段代码就不会产生任何错误,无论是在运行程序的控制台中还是在作业日志中。但是,我无法找到应该创建的文件(现在,我正在本地集群上工作)。
知道在哪里可以找到文件或错误信息吗?如果确实有错误消息,我应该如何继续向datanode的本地文件系统写入文件?
newFile.txt是一个相对路径,因此该文件将相对于您的map任务进程的工作目录显示。这将落在NodeManager用于容器的目录下的某个地方。这是yarn-site.xml中的配置属性yarn.nodemanager.local-dirs
,或者从yarn-default.xml继承的默认属性,它位于/tmp:
<property>
<description>List of directories to store localized files in. An
application's localized file directory will be found in:
${yarn.nodemanager.local-dirs}/usercache/${user}/appcache/application_${appid}.
Individual containers' work directories, called container_${contid}, will
be subdirectories of this.
</description>
<name>yarn.nodemanager.local-dirs</name>
<value>${hadoop.tmp.dir}/nm-local-dir</value>
</property>
下面是我的测试环境中这样一个目录的具体示例:
/tmp/hadoop-cnauroth/nm-local-dir/usercache/cnauroth/appcache/application_1363932793646_0002/container_1363932793646_0002_01_000001
这些目录是容器执行的临时空间,因此您不能依赖它们来实现持久性。后台线程定期删除已完成容器的这些文件。可以通过在yarn-site.xml:
中设置配置属性yarn.nodemanager.delete.debug-delay-sec
来延迟清理。<property>
<description>
Number of seconds after an application finishes before the nodemanager's
DeletionService will delete the application's localized file directory
and log directory.
To diagnose Yarn application problems, set this property's value large
enough (for example, to 600 = 10 minutes) to permit examination of these
directories. After changing the property's value, you must restart the
nodemanager in order for it to have an effect.
The roots of Yarn applications' work directories is configurable with
the yarn.nodemanager.local-dirs property (see below), and the roots
of the Yarn applications' log directories is configurable with the
yarn.nodemanager.log-dirs property (see also below).
</description>
<name>yarn.nodemanager.delete.debug-delay-sec</name>
<value>0</value>
</property>
但是,请记住,此配置仅用于故障排除问题,以便您可以更容易地查看目录。不建议将其作为永久的生产配置。如果应用程序逻辑依赖于删除延迟,那么很可能在试图访问目录的应用程序逻辑和试图删除目录的NodeManager之间导致竞争条件。在旧容器执行过程中保留文件也有可能使本地磁盘空间混乱。
日志消息将进入映射任务日志的stdout/stderr,但我怀疑执行没有击中这些日志消息。相反,我怀疑您成功地创建了文件,但要么是它不容易找到(目录结构将具有一些不可预测的内容,例如由YARN管理的应用程序ID和容器ID),要么是文件在您可以访问它之前被清理了。
如果您将代码更改为使用指向其他目录的绝对路径,那么这将有所帮助。然而,我并不期望这种方法在实际实践中能够很好地工作。由于Hadoop是分布式的,您可能很难在数百或数千个集群中找到包含所需本地文件的节点。相反,您可能更适合写入HDFS,然后将所需的文件本地拉到启动作业的节点。