首先新建一个项目,以便编译MapReduce程序并通过命令或在自己的IDE中以本地(独立,standalone)模式运行他们。在下面范例中的Maven POM项目对象模型(Project Object Model)说明了编译和测试Map-Reduce程序时需要的依赖项(dependency)。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.hadoopbook</groupId>
<artifactId>hadoop-book-mr-dev</artifactId>
<version>4.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<hadoop.version>3.1.0</hadoop.version>
</properties>
<dependencies>
<!--hadoop main client artifact-->
<dependency>
<groupId>org.apahce.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
<!--unit test artifacts-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.mrunit</groupId>
<artifactId>mrunit</artifactId>
<version>1.1.0</version>
<classifier>hadoop2</classifier>
<scope>test</scope>
</dependency>
<!--Hadoop test artifact for running mini clusters-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-minicluster</artifactId>
<version>${hadoop.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>hadoop-examples</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<outputDirectory>${basedir}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
依赖关系是POM中有趣的一部分。(只要你使用此处定义的依赖关系,就可以直接使用其他的构建工具,例如Gradle或者Ant with Ivy。)要想构建MapReduce作业,你只需要有hadoop-client依赖关系,它包含了和HDFS及MapReduce交互所需要的所有Hadoop client-side类。当运行单元测试时,我们要使用junit类;当写MapReduce测试用例时,我们使用mrunit类。hadoop-minicluster库中包含了“mini-”集群,这有助于在一个单JVM中运行Hadoop集群进行测试。
很多IDE可以直接读Maven POM,因此你只需要在包含pom.xml文件的目录中指向这些Maven POM,就可以开始写代码。也可以使用Maven为IDE生成配置文件。例如,如下创建Eclipse配置文件以便将项目导入Eclipse:
mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
1.管理配置
开发Hadoop应用时,经常需要在本地运行和集群之间进行切换。事实上,可能在几个集群上工作,也可能在本地“伪集群”集群上测试。伪分布式集群是其守护进程运行在本机的集群。
应对这些变化的一种方法是使Hadoop配置文件包含每个集群的连接设置,并且在运行Hadoop引用或工具时指定使用哪一个连接设置。最好的做法是,把这些文件放在Hadoop安装目录树之外,以便于轻松地在Hadoop不同版本之间进行切换,从而避免重复或丢失设置信息。
为了方便,我们假设目录conf包含三个配置文件:hadoop-local.xml、hadoop-localhost.xml和hadoop-cluster.xml。注意,文件名没有特殊要求,这样命名只是为了方便打包配置的设置。
针对默认的文件系统和用于运行MapReduce作业的本地(指在JVM中的)框架,hadoop-local.xml包含默认的Hadoop配置:
<?xml version="1.0"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>file:///</value>
</property>
<property>
<name>mapreduce.framework.name</name>
<value>local</value>
</property>
</configuration>
hadoop-localhost.xml文件中的设置指向本地主机上运行的namenode和YARN资源管理器:
<?xml version="1.0"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost/</value>
</property>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>localhost:8932</value>
</propertY>
</configuration>
最后,hadoop-cluster.xml文件包含集群上namenode和YARN资源管理器地址的详细信息(事实上,我们会以集群的名称来命名这个文件,而不是这里显示的那样用cluster泛指):
<?xm lversion="1.0"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://namenode/</value>
</property>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.framework.name</name>
<value>resourcemanager:8932</value>
</property>
</configuration>
还可以根据需要为这些文件添加其他配置信息。
有了这些设置,便可以轻松通过-conf命令行开关来使用各种配置。例如,下面的命令显示了一个在伪分布式模式下运行于本地主机上的HDFS服务器上的目录列表:
%hadoop fs -conf conf/hadoop-localhost.xml -ls .
Found 2 items
drwxr-xr-x-tom supergroup 0 2014-09-08 10:19 input
drwxr-xr-x-tom supergroup 0 2014-09-08 10:19 output
如果省略-conf选项,可以从$HADOOP_HOME的etc/hadoop子目录中找到Hadoop的配置信息。或者如果已经设置了HADOOP_CONF_DIR,Hadoop的配置信息将从那个位置读取。
注意:这里介绍另一种管理配置设置的方法。将etc/hadoop目录从Hadoop的安装位置拷贝至另一个位置,将*-site.xml配置文件也放于该位置(文件中的各项设置应正确),再将HADOOP_CONF_DIR环境变量设置为指向该位置。该方法的主要优点是,不需要每个命令中都指定-conf。并且,由于HADOOP_CONF_DIR路径下有所有配置文件的拷贝,因此,对文件的修改可以与Hadoop XML 配置文件隔离开来(例如,log4j.properties)。Hadoop自带的工具支持-conf选项,也可以直接用程序(例如运行MapReduce作业的程序)通过使用Tool接口来支持-conf选项。
2.辅助类GenericOptionsParser ,Tool和ToolRunner
package org.apache.hadoop.util;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
import org.apache.hadoop.conf.Configurable;
@Public
@Stable
public interface Tool extends Configurable {
int run(String[] var1) throws Exception;
}
如下范例给出了一个非常单的Tool的实现,用来打印Tool的Configuration对象中所有属性的键值对。
public class ConfigurationPrinter extends Configured implements Tool{
static{
Configuration.addDefaultResource("hdfs-default.xml");
Configuration.addDefaultResource("hdfs.site.xml");
Configuration.addDefaultResource("yarn.default.xml");
Configuration.addDefaultResource("yarn-site.xml");
Configuration.addDefaultResource("mapred-default.xml");
Configuration.addDefaultResource("mapred-site.xml");
@Override
public int run(String[] args)throws Exception{
Configuration conf=getConf();
for(Entry<String,String>entry:conf){
System.out.printf("%s=%s\n", entry.getKey(),entry.getvalue());
}
return0;
}
public static void main(String[] args)throws Exception{
int exitCode=ToolRunner.run(new ConfigurationPrinter(),args);
System.exit(exitCode);
}
}
我们把ConfigurationPrinter作为configured的一个子类,Configured是Configurable接冂的一个实现。Tool的所有实现都需要实现Configurable(因为Tool继承于configurable),Configured子类通常是一种最简单的实现方式。run()方法通过Configurable的getConf()方法获取Configuration,然后重复执行,将每个属性打印到标准输出。静态代码部分确保核心配置外的HDFS、YARN和MapReduce配置能够被获取(因为Configuration已经获取了核心配置)。
可以设置哪些属性?
作为一个有用的工具,ConfigurationPrinter可用于了解在环境中某个属性是如何进行设置的。对于运行中的守护进程,例如namenode,可以通过查看其网络服务器上的/页面来了解配置情况。
你也可以在Hadoop安装路径的share/doc目录中,查看所有公共属性的默认设置,相关文件包括core-default.xml,hdfs-demultxml,yam-default.xml和mapred-default.xml这几个文件·每个属性都有用来解释属性作用和取值范围的描述。
默认的配置文档可通过以下网址所链接的页面找到,http://hadoop.apahce.org/docs/current(在导航树中寻找"Configuration”标题)。通过用<version>替换前述URL中的current,可以找到一个特定Hadoop发行版本的默认配置,例如,http://hadoop.apahce.org/docs/r2.5.0。
注意,在客户端配置中设置某些属性,将不会产生影响·例如,如果在作业提交时想通过设置yarn.nodemanager.resource.memory-mb来改变运行作业的节点管理器能够得到的内存数量,结果会让你失望的,因为这个属性只能在节点管理器的yarn-sitexml文件中进行设置·一般情况下,我们可以通过属性名的组成部分来获知该属性应该在哪里进行设置。由于yarn.nodemanager.resource.menory-mb以yarn.nodemanager.resource.memory-mb以yarn.nodemanager开头,因此,我们知道它只能为节点管理器守护进程进行设置·但是,这不是硬性的,在有些情况下,我们需要进行尝试,甚至去阅读源代码。
在Hadoop2中,为了让命名结构看着更常规一些,对配置属性名称进行了修改。例如,namenode相关的HDFS属性名称都改为带一个dfs.namenode前缀,这样原先的dfs.name·dir现在称为dfs.namenode.name.dir。类似的,MapReduce属性用mapreduce前缀代替了较早的mapred前缀,因此,原先的mapred.job.name现在称为mapreduce.jab.name。
ConfigurationPrinter的main()方法没有直接调用自身的run()方法,而是调用ToolRunner的静态run()方法,该方法负责在调用自身的run()方法之前,为Tool建立一个Configuration对象。ToolRunner还使用了Generic0ptionsParser来获取在命令行方式中指定所有标准的选项,然后,在Configuration实例上进行设置。运行下列代码,可以看到在conf/hadoop-localhost.xml中设置的属性。
mvn compile
export HADOOP_CLASSPATH:target/classes
hadoop ConfigurationPrinter -conf conf/hadoop-localhost.xml \n
grep yarn.resourcemanager.address=yarn.resourcemanager.address=localhost:8032
GenericOptionsParser也允许设置个别属性。例如:
hadoop ConfigurationPrinter-D color=yellow | grep color
color=yellow
-D选项用于将键color的配置属性值设置为yellow。设置为-D的选项优先级要高于配置文件里的其他属性。这一点很有用:可以把默认属性放人配置文件中,然后再在需要时用-D选项来覆盖。一个常见的例子是,通过-Dmapreduce.job.reduces=n来设置MapReduce作业中reducer的数量。这样会覆盖集群上或客户端配置属性文件中设置的reducer数量。
GenericOptionsParser和ToolRunner支持的其他选项可以参见下表。
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程序可以访问这些文件 |
-archives | 从本地文件系统(或任何指定模式的文件系统)复制指定存档到jobtracker所用的共享文件系统(通常是HDFS),打开存档文件,确保任务工作目录的MapReduce程序可以访问这些存档 |
-libjars jar1,jar2,… | 从本地文件系统(或任何指定模式的文件系统)复制指定JAR文件到被jobtracker 使用的共享文件系统(通常是HDFS),把它们加入MapReduce任务的类路径中。这个选项适用于传输作业需要的JAR文件 |
JVM系统属性来自于java.lang.System类,而Hadoop属性只能从Configuration对象中获取。所以,下面的命令行将没有任何输出,因为ConfigurationPrinter没有使用System类
hadoop -Dcolor=yellow ConfigurationPrinter | grep color
如果希望通过系统属性进行配置,则需要在配置文件中反映相关的系统属性。