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来设置状态。