辅助类GenericOptionsParser,Tool和ToolRunner

本文介绍Hadoop中的配置机制,特别是如何使用GenericOptionsParser和ToolRunner简化命令行操作。通过示例展示如何创建Tool来打印Configuration对象中的属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了简化命令行方式运行作业,Hadoop自带了一些辅助类。GenericOptionsParser是一个类,用来解释常用的Hadoop命令行选项,并根据需要,为Configuration对象设置相应的取值。通常不直接使用GenericOptionsParser,更方便的方式是:实现Tool接口,通过ToolRunner来运行应用程序,ToolRunner内部调用GenericOptionsParser:

 
  1. GenericOptionsParser:  
  2. public interface Tool extends Configurable {  
  3.   int run(String [] args) throws Exception;  
  4. }  

例5-3给出了一个非常简单的Tool的实现,用来打印Tool的Configuration对象中所有属性的键值对。

例5-3. Tool实现示例,用于打印一个Configuration对象的属性

 
  1. public class ConfigurationPrinter extends Configured implements Tool {  
  2.  
  3.   static {  
  4.     Configuration.addDefaultResource("hdfs-default.xml");  
  5.     Configuration.addDefaultResource("hdfs-site.xml");  
  6.     Configuration.addDefaultResource("mapred-default.xml");  
  7.     Configuration.addDefaultResource("mapred-site.xml");  
  8. }  
  9.  
  10. @Override  
  11. public int run(String[] args) throws Exception {  
  12.   Configuration conf = getConf();  
  13.   for (Entry<String, String> entry: conf) {  
  14.     System.out.printf("%s=%s\n", entry.getKey(), entry.getValue());  
  15.   }  
  16.     return 0;  
  17.   }  
  18.  
  19.   public static void main(String[] args) throws Exception {  
  20.     int exitCode = ToolRunner.run(new ConfigurationPrinter(), args);  
  21.     System.exit(exitCode);  
  22.   }  
  23. }  

我们把ConfigurationPrinter作为Configured的一个子类,Configured是Configurable接口的一个实现。Tool的所有实现都需要实现Configurable(因为Tool继承于Configurable),Configured子类通常是一种最简单的实现方式。run()方法通过Configurable的getConf()方法获取Configuration,然后重复执行,将每个属性打印到标准输出。

静态代码部分用来获取HDFS和MapReduce配置和核心配置(Configuration已经取得核心配置)。

ConfigurationPrinter的main()方法没有直接调用自身的run()方法,而是调用ToolRunner的静态run()方法,该方法负责在调用run()方法之前,为Tool建立一个Configuration对象。ToolRunner还使用了GenericOptionsParser来获取在命令行方式中指定的任何标准选项,然后,在Configuration实例上进行设置。运行下列代码,可以看到在conf/hadoop-localhost.xml中设置的属性。

 
  1. % hadoop ConfigurationPrinter -conf conf/hadoop-localhost.xml \  
  2.   | grep mapredmapred.job.tracker=  
  3. mapred.job.tracker=localhost:8021  

可以设置哪些属性?

可以在环境中设置什么属性,一个有用的工具便是ConfigurationPrinter。

也可以在Hadoop安装路径的docs目录中,查看所有公共属性的默认设置,相关文件包括coredefault.html,hdfs-default.html 和mapred-default.html这几个HTML文件。每个属性都有用来解释属性作用和取值范围的描述。

注意:在客户端配置中设置某些属性,将不会产生影响。例如,如果在作业提交时想通过设置mapred.tasktracker.map.tasks.maximum来改变运行作业的tasktracker的任务槽(task slot)数,结果会令你失望,因为这个属性只能在tasktracker的mapred-site.xml文件中进行设置。一般情况下,可以通过属性名来告诉组件该属性应该在哪里进行设置,由于mapred.tasktracker.map.tasks.maximum以mapred.tasktracker开头,因此,我们知道它只能为tasktracker守护进程设置。但是,这不是硬性的,在有些情况下,我们需要进行尝试,甚至去阅读源码。

本书讨论了Hadoop的很多重要的配置属性。在本书的网站(http://www.hadoopbook.com)上可以找到配置属性的参考资料。

GenericOptionsParser也允许设置个别属性。例如:

 
  1. % hadoop ConfigurationPrinter -D color=yellow | grep color  
  2. color=yellow 

-D选项用于将键color的配置属性值设置为yellow。设置为-D的选项优先级要高于配置文件里的其他属性。这一点很有用:可以把默认属性放入配置文件中,然后再在需要时,用-D选项来覆盖它们。一个常见的例子是:通过-D mapred.reduce.tasks=n来设置MapReduce作业中reducer的数量。这样会覆盖集群上或客户端配置属性文件中设置的reducer数量。

GenericOptionsParser和ToolRunner支持的其他选项见表5-1。更多的Hadoop配置API可以在第130页的"配置API"小节中找到。

 用-D property=value选项将Hadoop属性设置为GenericOptionsParser (和 ToolRunner),不同于用-Dproperty=value选项将JVM系统属性设置为Java命令。JVM系统属性的语法不允许D和属性名之间有任何空格,而GenericOptionsParser要求用空格来分隔D和属性名。

JVM系统属性来自于java.lang.System类,而Hadoop属性只能从Configuration对象中获取。所以,下面的命令行将没有任何输出,因为ConfigurationPrinter没有使用System类

 
  1. % hadoop -Dcolor=yellow ConfigurationPrinter | grep color 

如果希望通过系统属性进行配置,则需要在配置文件中反映相关的系统属性。具体讨论见第132页的"可变的扩展"小节。

表5-1. GenericOptionsParser选项和ToolRunner 选项

选项名称

描述

-D property=value

将指定值赋值给确定的Hadoop配置属性。

覆盖配置文件里的默认属性或站点属性,

或通过-conf选项设置的任何属性

-conf filename ...

将指定文件添加到配置的资源列表中。

这是设置站点属性或同时设置一组属性的简便方法

-fs uri

用指定的URI设置默认文件系统。这是

-D fs.default.name=uri的快捷方式

-jt host:port

用指定主机和端口设置jobtracker。这是-

D mapred.job.tracker= host:port的快捷方式

-files file1,file2,...

从本地文件系统(或任何指定模式的文件系统)

中复制指定文件到jobtracker所用的共享文件

系统(通常是HDFS),确保在任务工作目录的

MapReduce程序可以访问这些文件(要想进一步

了解如何复制文件到tasktracker机器的分布式缓

存机制,请参见第253页的“分布式缓存”小节)

-archives
archive1,archive2,..

从本地文件系统(或任何指定模式的文件系统)

复制指定存档到jobtracker所用的共享文件系统

(通常是HDFS),打开存档文件,确保任务工作

目录的MapReduce程序可以访问这些存档


选项名称

描述

-libjars jar1,jar2,…

从本地文件系统(或任何指定模式的文件系统)复制指

定JAR文件到被jobtracker 使用的共享文件系统

(通常是HDFS),把它们加入MapReduce任务的类路

径中。这个选项适用于传输作业需要的JAR文件



<think>我们正在解决一个Hadoop MapReduce作业的导入使用问题。用户遇到了`Tool`、`GenericOptionsParser``ToolRunner`的导入错误。这些属于`org.apache.hadoop.util`包。因此,我们需要确保正确导入这些,并且在代码中正确使用它们。根据用户之前的代码,我们注意到用户尝试创建一个实现`Tool`接口的,并使用了`GenericOptionsParser``ToolRunner`。下面我们将提供修正后的代码框架,并解释如何正确使用这些。步骤:1.确保Hadoop依赖正确添加到项目中(例如,Maven或手动添加JAR)。2.在代码中导入必要的。3.创建一个实现`Tool`接口,并实现`run`方法`main`方法。4.在`run`方法中配置运行MapReduce作业。5.在`main`方法中使用`ToolRunner`来运行这个工具。修正后的代码框架如下: ```javapackage com.dajiangtai.hadoop.tv;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.conf.Configured;import org.apache.hadoop.fs.Path; importorg.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Job;import org.apache.hadoop.mapreduce.Mapper;import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; importorg.apache.hadoop.mapreduce.lib.input.TextInputFormat;import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; importorg.apache.hadoop.mapreduce.lib.output.TextOutputFormat;import org.apache.hadoop.util.GenericOptionsParser;import org.apache.hadoop.util.Tool; importorg.apache.hadoop.util.ToolRunner; importjava.io.IOException;public classParseAndFilterLogextends Configured implementsTool {//...内部Mapper定义 ...@Overridepublicint run(String[]args)throws Exception{Configuration conf= this.getConf(); //使用Configured中的配置//使用GenericOptionsParser解析命令行参数String[] otherArgs =new GenericOptionsParser(conf, args).getRemainingArgs();if(otherArgs.length<2){System.err.println("Usage:ParseAndFilterLog<in> [<in>...] <out>");return2;}//创建Job实例Job job= Job.getInstance(conf,"ParseAndFilterLog");job.setJarByClass(ParseAndFilterLog.class);//设置Mapperjob.setMapperClass(ExtractTVMsgLogMapper.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(Text.class);job.setNumReduceTasks(0);//没有Reducer//输入输出格式job.setInputFormatClass(TextInputFormat.class);job.setOutputFormatClass(TextOutputFormat.class);//设置输入输出路径for (int i=0;i <otherArgs.length -1; i++) {FileInputFormat.addInputPath(job,new Path(otherArgs[i]));}FileOutputFormat.setOutputPath(job,new Path(otherArgs[otherArgs.length-1]));//运行作业并返回状态return job.waitForCompletion(true) ?0:1;}public staticvoid main(String[]args)throws Exception{//使用ToolRunner运行intexitCode= ToolRunner.run(new ParseAndFilterLog(),args);System.exit(exitCode);}// Mapperpublic staticclass ExtractTVMsgLogMapperextends Mapper<LongWritable,Text,Text,Text>{// ...map方法的实现 ...}} ```###关键点解释: 1. **导入包**:-确保导入了以下:```javaimportorg.apache.hadoop.util.Tool;importorg.apache.hadoop.util.ToolRunner;import org.apache.hadoop.util.GenericOptionsParser;```以及`Configured`(它实现了`Configurable`接口,方便我们获取配置)。2.**继承实现**:-`ParseAndFilterLog`继承`Configured`并实现`Tool`接口。`Configured`提供了对`Configuration`对象的访问,而`Tool`接口要求实现`run`方法。 3. **run方法**:-在`run`方法中,我们使用`GenericOptionsParser`来解析命令行参数。它会解析Hadoop通用参数(如`-D`配置属性),并返回剩余的参数(通常是输入输出路径)。-然后,我们使用这些剩余参数来设置作业的输入输出路径。4.**main方法**:-在`main`方法中,我们使用`ToolRunner.run(newParseAndFilterLog(),args);`来运行工具。`ToolRunner`会处理Hadoop命令行中的通用参数,并调用我们的`run`方法。 5. **作业配置**:-使用`this.getConf()`获取配置对象(来自父`Configured`),这样我们就可以使用通过命令行`-D`指定的配置属性。 ###常见问题解决: -**导入错误**:如果IDE仍然提示导入错误,请检查项目的构建路径(build path)是否包含了Hadoop的核心JAR文件。如果使用Maven,请在`pom.xml`中添加依赖:```xml<dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-common</artifactId><version>2.7.3</version><!--根据你的Hadoop版本调整 --></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-mapreduce-client-core</artifactId><version>2.7.3</version></dependency>```- **运行错误**:如果运行时出现错误,请检查Hadoop的安装配置,以及命令行参数是否正确。###示例运行命令:```bashhadoop jaryour-jar.jarcom.dajiangtai.hadoop.tv.ParseAndFilterLog -D mapreduce.output.textoutputformat.separator=@/input/path /output/path``` 在这个命令中,`-D`选项用于设置配置属性(这里设置了输出字段分隔符为`@`),然后是两个路径参数。§§相关问题§§1.如何在Hadoop作业中传递自定义配置参数?2.如何配置Hadoop项目的Maven依赖? 3.如何调试HadoopMapReduce作业?4.为什么使用`ToolRunner`来运行MapReduce作业?</think>### 解决Hadoop工具导入错误的方法 您遇到的`Tool`、`GenericOptionsParser``ToolRunner`导入错误通常是由于Hadoop依赖配置不正确导致的。以下是完整的解决方案: #### 1. 添加必要的Hadoop依赖 在您的构建文件中添加以下依赖(以Maven为例): ```xml <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.3</version> <!-- 匹配您的Hadoop版本 --> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-mapreduce-client-core</artifactId> <version>2.7.3</version> </dependency> ``` #### 2. 修正的代码实现 ```java package com.dajiangtai.hadoop.tv; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.util.GenericOptionsParser; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; import java.io.IOException; public class ParseAndFilterLog extends Configured implements Tool { public static class ExtractTVMsgLogMapper extends Mapper<LongWritable, Text, Text, Text> { private final Text outputKey = new Text(); private final Text outputValue = new Text(); @Override public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] parsedData = parseAndFilterData(value.toString()); if (parsedData != null && parsedData.length == 7) { String keyPart = parsedData[0] + "@" + parsedData[1]; String valuePart = String.join("@", parsedData[2], parsedData[3], parsedData[4], parsedData[5], parsedData[6]); outputKey.set(keyPart); outputValue.set(valuePart); context.write(outputKey, outputValue); } } private String[] parseAndFilterData(String data) { // 实际解析逻辑应在此实现 return data.split(","); // 示例:按逗号分割 } } @Override public int run(String[] args) throws Exception { Configuration conf = getConf(); String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); if (otherArgs.length < 2) { System.err.println("Usage: ParseAndFilterLog <input> <output>"); return 1; } Job job = Job.getInstance(conf, "TV Log Parser"); job.setJarByClass(ParseAndFilterLog.class); job.setMapperClass(ExtractTVMsgLogMapper.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); job.setNumReduceTasks(0); // 无Reducer FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); return job.waitForCompletion(true) ? 0 : 1; } public static void main(String[] args) throws Exception { int exitCode = ToolRunner.run(new ParseAndFilterLog(), args); System.exit(exitCode); } } ``` #### 3. 关键修正点说明 1. **正确导入工具**: ```java import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; import org.apache.hadoop.util.GenericOptionsParser; ``` 2. **实现Tool接口**: ```java public class ParseAndFilterLog extends Configured implements Tool ``` 3. **使用GenericOptionsParser**: ```java String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); ``` 4. **通过ToolRunner运行作业**: ```java int exitCode = ToolRunner.run(new ParseAndFilterLog(), args); ``` #### 4. 环境配置要点 1. **Hadoop安装验证**: ```bash hadoop version ``` 确保输出正确版本信息,避免路径错误[^1] 2. **IDE配置**: - 在MyEclipse/Eclipse中安装Hadoop插件[^3] - 配置Hadoop安装路径:`Window > Preference > Hadoop Map/Reduce` 3. **路径设置**: ```bash export HADOOP_CLASSPATH=${JAVA_HOME}/lib/tools.jar ``` #### 5. 运行示例 ```bash hadoop jar your-jar.jar com.dajiangtai.hadoop.tv.ParseAndFilterLog \ -D mapreduce.output.textoutputformat.separator=@ \ /input/logs /output/parsed ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值