18.3.3 使用Hadoop Streaming常见的问题
1.如何处理多个文件,其中每个文件一个Map?
需要处理多个文件时,用户可以采用多种途径,这里以在集群上压缩(zipping)多个文件为例,用户可以使用以下几种方法:
(1)使用Hadoop Streaming和用户编写的mapper脚本程序。
先生成一个文件,文件中包含所有要压缩的文件在HDFS上的完整路径。每个Map任务获得一个路径名作为输入。
然后创建一个Mapper脚本程序,实现如下功能:获得文件名,把该文件复制到本地,压缩该文件并把它发到期望的输出目录中。
(2)使用现有的Hadoop框架
在main函数中添加如下命令:
FileOutputFormat.setCompressOutput(conf, true);
FileOutputFormat.setOutputCompressorClass(conf, org.apache.Hadoop.io.compress.
GzipCodec.class);
conf.setOutputFormat(NonSplitableTextInputFormat.class);
conf.setNumReduceTasks(0);
编写Map函数:
public void map(WritableComparable key, Writable value,
OutputCollector output,
Reporter reporter)throws IOException{
output.collect((Text)value, null);
}
注意输出的文件名和原文件名不同。
2.如果在Shell脚本里设置一个别名,并放在-mapper之后,Streaming会正常运行吗?例如,alias cl='cut-fl',-mapper"cl"会运行正常吗?
脚本里是无法使用别名的,但是允许变量替换,例如:
$Hadoop dfs-cat samples/student_marks
alice 50
bruce 70
charlie 80
dan 75
$c2='cut-f2';$HADOOP_HOME/bin/Hadoop jar$HADOOP_HOME/Hadoop-streaming.jar\
-input/user/me/samples/student_marks
-mapper\"$c2\"-reducer'cat'
-output/user/me/samples/student_out
-jobconf mapred.job.name='Experiment'
$Hadoop dfs-ls samples/student_out
Found 1 items/user/me/samples/student_out/part-00000<r 3>16
$Hadoop dfs-cat samples/student_out/part-00000
50
70
75
80
3.在Streaming作业中用-file选项运行一个分布式的超大可执行文件(例如,3.6GB)时,如果得到错误信息“No space left on device”如何解决?
由于配置变量stream.tmpdir指定了一个目录,会在这个目录下进行打jar包的操作。stream.tmpdir的默认值是/tmp,用户需要将这个值设置为一个有更大空间的目录:
-D stream.tmpdir=/export/bigspace/……
4.如何设置多个输入目录?
可以使用多个-input选项设置多个输入目录:
Hadoop jar Hadoop-streaming.jar-input'/user/foo/dir1'-input'/user/foo/dir2'
5.如何生成gzip格式的输出文件?
除了纯文本格式的输出,用户还可以让程序生成gzip文件格式的输出,只需将Streaming作业中的选项设置为“-D mapred.output.compress=true-jobconf mapred.output.compression.codec=org.apache.Hadoop.io.compress.GzipCode”。
6.在Streaming中如何自定义input/output format?
在Hadoop 0.14版本以前,不支持多个jar文件。所以当指定自定义的类时,用户需要把它们和原有的streaming jar打包在一起,并用这个自定义的jar包替换默认的Hadoop streaming jar包。在0.14版本以后,就无须打包在一起,只需要正常的编译运行。
7.Streaming如何解析XML文档?
用户可以使用StreamXmlRecordReader来解析XML文档,如下所示:
Hadoop jar Hadoop-streaming.jar-inputreader"StreamXmlRecord, begin=BEGIN_
STRING, end=END_STRING"……
Map任务会把BEGIN_STRING和END_STRING之间的部分看做一条记录。
8.在Streaming应用程序中如何更新计数器?
Streaming进程能够使用stderr发出计数器信息。应该把reporter:counter:<group>,<count er>,<amount>发送到stderr来更新计数器。
9.如何更新Streaming应用程序的状态?
Streaming进程能够使用stderr发出状态信息。可把reporter:status:<message>发送到stderr来设置状态。