美文网首页我爱编程
Hadoop MapReduce 编写

Hadoop MapReduce 编写

作者: Grits | 来源:发表于2018-04-12 17:35 被阅读0次

    Key Words: Configruation, Combiing Resources, Variable Expansion, dependency, package

    写 MapReduce 的套路,首先写 map 和 reduce 函数,在 IDE 中拿一小部分的数据集进行调试,编写单元测试,调试成功之后,将程序放开(unleash)到集群环境中,期间可能遇到更多的问题,继续丰富单元测试,在分布式环境下进行 mapReduce 程序的调试,是一个挑战,Hadoop 提供了相关通用技巧来使得调试过程相对容易
    在程序能够正常运行之后,需要给 mapReduce 程序进行调优,让其跑的更快,以及对任务(task)进行剖析(profile),对任务进行剖析是通过在执行流程中添加相关钩子(hook)来进行诊断

    Configruation API 要点

    1.xml 文件中不存储类型信息,所以属性可以通过指定的类型被解释
    2.可以为属性指定一个 default 值

    合并资源(Combining Resources)

    1.按照加载的顺序进行合并

    Configuration conf = new Configuration();
    conf.addResource("configuration-1.xml");
    conf.addResource("configuration-2.xml"); 
    

    2.属性被标记为final后,不能被后续的定义覆盖(overridden)

    变量扩展(Variable Expansion)

    1.后续的变量值定义可以使用前者变量的定义值

    <?xml version="1.0"?>
    <configuration>
      <property>
        <name>color</name>
        <value>yellow</value>
        <description>Color</description>
      </property>
      
      <property>
        <name>size</name>
        <value>10</value>
        <description>Size</description>
      </property>
      
      <property>
        <name>weight</name>
        <value>heavy</value>
        <final>true</final>
        <description>Weight</description>
      </property>
      
      <property>
        <name>size-weight</name>
        <value>${size},${weight}</value>
        <description>Size and weight</description>
      </property>
    </configuration>
    

    2.系统属性比资源文件中的属性具有更高的优先级

    所以可以通过 -Dproperty=value的形式来进行覆盖属性文件中的变量定义。但是有个例外,就是被覆盖的属性必须在属性文件中进行了定义,否则配置对象无法获取且给出警告

    System.setProperty("length", "2");
    assertThat(conf.get("length"), is((String) null)); 
    

    配置开发环境

    1.依赖配置(pom.xml)

    <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>2.5.1</hadoop.version>
        </properties>
        <dependencies>
            <!-- Hadoop main client artifact -->
            <dependency>
                <groupId>org.apache.hadoop</groupId>
                <artifactId>hadoop-client</artifactId>
                <version>${hadoop.version}</version>
            </dependency>
            <!-- Unit test artifacts -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</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.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>2.5</version>
                    <configuration>
                        <outputDirectory>${basedir}</outputDirectory>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    

    为了构建 MapReduce 作业,只需引入 hadoop-client 依赖,它包含了 Hadoop 客户端和 HDFS 和 MapReduce 交互的类

    使用 mrunit 来进行 MapReduce 的单元测试

    hadoop-minicluster 类库包含了“mini-”的集群,它们在单机(single JVM)上测试 Hadoop 集群非常有用

    管理配置

    对于 local、pseudo distributed、cluster 环境的配置,最好的做法是,将它们各自的配置文件独立于 Hadoop 的安装目录树,这样的能够容易的切换 Hadoop 的作业环境而不至于重复或是丢失配置

    GenericOptionsParser,Tool,and ToolRunner

    ToolRunner 使用 GenericOptionsParser 来把命令行上指定的选项设置到 Configuration 实例对象中

    注意在命令行中的-D property=value中间的空格符号,以及与标准 JVM 系统属性(system properties)的区别

    路径以及依赖

    客户端路径

    由 hadoop jar <jar> 设置的用户客户端类路径包括以下几个组成部分:

    • 作业 Jar 文件
    • 作业 Jar 文件中 lib 目录下的所有 Jar 文件以及 classes 目录(如果有)
    • 由 HADOOP_CLASSPATH 定义的类路径(如果设置)

    作业路径

    在集群环境中,map 和 reduce 任务各自运行在不同的 JVM 上面,所以他们的 classpath 不能通过 HADOOP_CLASSPATH 来进行控制

    HAOOP_CLASSPATH 是一个客户端设置,且只能为驱动器 JVM 设置 classpath,也就是提交作业的的 JVM

    用户的任务类路径有如下构成:

    • 作业 Jar 文件
    • 作业 Jar 文件中 lib 目录下的所有 Jar 文件以及 classes 目录(如果有)
    • 任何通过 -libjars 选项添加到分布式缓存的文件,或者通过 addFileToClassPath() 方法添加的文件

    打包依赖

    打包依赖有如下实践方法

    • 将库包和重新打包进作业 JAR
    • 将作业 JAR 和 lib 目录中的库打包
    • 保持库与作业 JAR 分开,并且通过 HADOOP_CLASSPATH 将它们添加到客户端类路径,通过 -libjars 将它们添加到任务的类路径

    从创建的角度看,最后使用分布式缓存的选项是最简单的,因为依赖不需要再作业的 JAR 中重新创建。使用分布式缓存意味着在集群上更少的 JAR 文件转移(因为文件可能换在任务之间的一个节点上)

    相关文章

      网友评论

        本文标题:Hadoop MapReduce 编写

        本文链接:https://www.haomeiwen.com/subject/lkjfkftx.html