上一章的 MapReduce 应用中,我们使用了自定义配置,并用 GenericOptionsParser 处理命令行输入的配置,这种方式简单粗暴。但不是 MapReduce 应用常见的写法,本章第一部分将介绍 MapReduce 应用常见的写法,并详细介绍自定义配置以及命令行选项,通过自定义配置我们可以灵活的控制 MapReduce 应用而不需要修改代码并打包。第二部分将介绍开发 MapReduce 应用的单元测试,单元测试的重要性不言而喻,是每个程序员必备技能。

带有自定义配置的 MapReduce 应用程序更常见的写法是实现 Tool 接口, 通过 ToolRunner 来运行应用程序。ToolRunner 内部会调用 GenericOptionsParser 类处理命令行选项,包括自定义配置。代码如下:

package com.cnblogs.duma.mapreduce;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
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; public class WordCountDriver extends Configured implements Tool { @Override
public int run(String[] args) throws Exception {
// Configuration conf = new Configuration();
// GenericOptionsParser optionParser = new GenericOptionsParser(conf, args); //识别命令行参数中的自定义配置
// String[] remainingArgs = optionParser.getRemainingArgs(); //获取处理自定义配置外的其他参数
Job job = Job.getInstance(getConf(), "WordCount"); //第二参数为程序的名字
job.setJarByClass(getClass()); //需要设置类名 job.setMapperClass(WordCountMapper.class); //设置 map 任务的类
// job.setCombinerClass(WordCountReducer.class);
job.setReducerClass(WordCountReducer.class); // 设置 reduce 任务的类 job.setOutputKeyClass(Text.class); //设置输出的 key 类型
job.setOutputValueClass(IntWritable.class); //设置输出的 value 类型 FileInputFormat.addInputPath(job, new Path(args[0])); //增加输入文件
FileOutputFormat.setOutputPath(job, new Path(args[1])); //设置输出目录 return job.waitForCompletion(true) ? 0 : 1;
} public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(new WordCountDriver(), args); //内部调用 GenericOptionsParser 处理配置
System.exit(exitCode);
}
}

在本例子中我们通过 ToolRunner 的 run 方法启动应用程序, run 方法第一个参数就是 Tool 类型的对象, 因此我们在驱动程序实现 Tool 接口,并实现了 Tool 接口的 run 方法, 该方法的处理跟之前版本的驱动程序 main 方法处理的逻辑一样,区别是不需要我们自己初始化 Configuration,也不需要我们自己用 GenericOptionsParser 对象处理配置,只需要调用 getConf 方法即可。getConf 方法是 Configurable 接口中定义的方法,Tool 继承了该接口,因此驱动程序中应该有 getConf 方法的实现, 为什么我们的驱动程序没有实现 getConf 方法呢? 因为我们的驱动程序继承了 Configured 类, 该类实现了 Configurable 接口,因此驱动程序的 getConf 方法是直接从 Configured 类继承过来的。我们可以看下 ToolRunner.run 方法做了什么处理,核心代码如下:

public static int run(Configuration conf, Tool tool, String[] args) throws Exception {
if (CallerContext.getCurrent() == null) {
CallerContext ctx = (new Builder("CLI")).build();
CallerContext.setCurrent(ctx);
} if (conf == null) {
conf = new Configuration();
} GenericOptionsParser parser = new GenericOptionsParser(conf, args);
tool.setConf(conf);
String[] toolArgs = parser.getRemainingArgs();
return tool.run(toolArgs);
}

可以看到 run 方法里面的处理逻辑跟我们之前自己处理的逻辑是一样的, 都是用 GenericOptionsParser 对象里的方法处理。代码最后调用 tool 对象的 run 方法, 那自然调用的就是驱动程序的 run 方法。我们之前添加配置通过命令行 -D 选项来实现, 除了 -D Tool 还支持以下的命令行选项:

选项名称 描述      
-D <property>=<value> 使用 key -value 方式指定配置
-conf <configuration file> 指定配置文件,格式如 core-site.xml
-fs <file:///> or hdfs://namenode:port 指定文件系统URL,覆盖之前配置的 fs.defaulFS
-files <逗号分隔的文件列表> 指定任务用到的本地文件, 如果多个用逗号分隔
-archive <逗号分隔的档案文件> 指定任务用到的档案文件,如果多个用逗号分隔
-libjars <逗号分隔的jar文件> 指定本地文件jar文件,会把他们加入到 MapReduce 任务的calsspath,如果任务用到第三方jar报可以用该选项

为 MapReduce 应用指定配置需要注意优先级, -conf 选项如果有多个配置文件且多个文件中有相同的配置的 key ,则后面的配置文件的值会覆盖前面的配置文件, 除非该配置的 final 标签的值为 true,表示不能被覆盖。其次需要注意 -D 配置的优先级高于配置文件。

以上便是开发 MapReduce 需要用到的配置和命令行选项相关的知识,接下来我们看看 Hadoop中如何编写单元测试。我之前开发 Hadoop 的时候还没出现 MapReduce 的单元测试框架,并且开发 MapReduce 应用基本都在 Windows 环境下开发,所以测试非常不方便,记得之前网上有一个工具可以在 Windows 平台下运行 Hadoop 任务, 可以勉强用来做单元测试,但终究也不太方便。最近发现 apache 开源了一个 MapReduce 应用的单元测试框架,实际用了一把,比较方便, 可以在本地直接测试 map 或 reduce 任务, 还能进行调试,非常好用。个人认为单元测试在工程实践中重要的一环, 一方面不需要打包,提交任务等一系列繁琐的操作过程就能测试代码,高效且能提高程序健壮性。另一方面,如果代码改动了,只需要增加些测试用例,重跑下单元测试即可。短期看编写测试代码花费了时间, 长期看是节省时间的。今天介绍的 MapReduce 单元测试框架叫 mrunit ,apache 开源项目,目前官网显示该项目已经退役,但并不影响我们使用,首先在 pom 文件中添加依赖

<dependency>
<groupId>org.apache.mrunit</groupId>
<artifactId>mrunit</artifactId>
<version>1.1.0</version>
<classifier>hadoop2</classifier> <!--选择hadoop1或hadoop2-->
<scope>test</scope>
</dependency>

我们以 word count map 任务为例,编写 WordCountMapper 的单元测试,代码如下

package com.cnblogs.duma;

import com.cnblogs.duma.mapreduce.WordCount;
import com.cnblogs.duma.mapreduce.WordCountDriver;
import com.cnblogs.duma.mapreduce.WordCountMapper;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mrunit.mapreduce.MapDriver;
import org.junit.Before;
import org.junit.Test; import java.io.IOException; public class WordCountMapperTest {
MapDriver<Object, Text, Text, IntWritable> mapDriver = null; @Before
public void setUp() {
WordCountMapper wdMapper = new WordCountMapper(); //初始化要测试的mapper
mapDriver = MapDriver.newMapDriver(wdMapper); //初始化 MapDriver
Configuration conf = mapDriver.getConfiguration();
conf.set("wordcount.filter.word", "hadoop"); //指定配置信息
} @Test
public void test() throws IOException {
mapDriver.setMapper(new WordCountMapper());
mapDriver.withInput(new IntWritable(1), new Text("a hadoop"))
.withOutput(new Text("hadoop"), new IntWritable(1))
.runTest();
} }

可以看到 mrunit 使用还是比较方便。有两点需要注意,第一,如果是 hadoop2 的测试用例, 需要要引用 org.apache.hadoop.mrunit.mapreduce.MapDriver。第二,withOutput 可以写多个,且顺序跟期望输出的顺序一致。这是 map 任务的测试用例, reduce 任务用法与之类似, 不再赘述。

总结

本章内容主要介绍了 MapReduce 任务常见的写法、Tool 接口支持的命令行选项、配置相关的知识以及单元测试。尤其是单元测试,方便、易用、高效。有意识编写单元测试可以让开发更规范同时可以提高工程质量。

大数据技术 - MapReduce 应用的配置和单元测试的更多相关文章

  1. 大数据技术 - MapReduce的Combiner介绍

    本章来简单介绍下 Hadoop MapReduce 中的 Combiner.Combiner 是为了聚合数据而出现的,那为什么要聚合数据呢?因为我们知道 Shuffle 过程是消耗网络IO 和 磁盘I ...

  2. 大数据技术 - MapReduce的Shuffle及调优

    本章内容我们学习一下 MapReduce 中的 Shuffle 过程,Shuffle 发生在 map 输出到 reduce 输入的过程,它的中文解释是 “洗牌”,顾名思义该过程涉及数据的重新分配,主要 ...

  3. 大数据技术 —— MapReduce 简介

    本文为senlie原创,转载请保留此地址:http://www.cnblogs.com/senlie/ 1.概要很多计算在概念上很直观,但由于输入数据很大,为了能在合理的时间内完成,这些计算必须分布在 ...

  4. 大数据技术 - MapReduce 作业的运行机制

    前几章我们介绍了 Hadoop 的 MapReduce 和 HDFS 两大组件,内容比较基础,看完后可以写简单的 MR 应用程序,也能够用命令行或 Java API 操作 HDFS.但要对 Hadoo ...

  5. 寻找丢失的微服务-HAProxy热加载问题的发现与分析 原创: 单既喜 一点大数据技术团队 4月8日 在一点资讯的容器计算平台中,我们通过HAProxy进行Marathon服务发现。本文记录HAProxy服务热加载后某微服务50%概率失效的问题。设计3组对比实验,验证了陈旧配置的HAProxy在Reload时没有退出进而导致微服务丢失,并给出了解决方案. Keywords:HAProxy热加

    寻找丢失的微服务-HAProxy热加载问题的发现与分析 原创: 单既喜 一点大数据技术团队 4月8日 在一点资讯的容器计算平台中,我们通过HAProxy进行Marathon服务发现.本文记录HAPro ...

  6. 除Hadoop大数据技术外,还需了解的九大技术

    除Hadoop外的9个大数据技术: 1.Apache Flink 2.Apache Samza 3.Google Cloud Data Flow 4.StreamSets 5.Tensor Flow ...

  7. TOP100summit:【分享实录-WalmartLabs】利用开源大数据技术构建WMX广告效益分析平台

    本篇文章内容来自2016年TOP100summitWalmartLabs实验室广告平台首席工程师.架构师粟迪夫的案例分享. 编辑:Cynthia 粟迪夫:WalmartLabs实验室广告平台首席工程师 ...

  8. 【学习笔记】大数据技术原理与应用(MOOC视频、厦门大学林子雨)

    1 大数据概述 大数据特性:4v volume velocity variety value 即大量化.快速化.多样化.价值密度低 数据量大:大数据摩尔定律 快速化:从数据的生成到消耗,时间窗口小,可 ...

  9. 大数据技术 - 为什么是SQL

    在大数据处理以及分析中 SQL 的普及率非常高,几乎是每一个大数据工程师必须掌握的语言,甚至非数据处理岗位的人也在学习使用 SQL.今天这篇文章就聊聊 SQL 在数据分析中作用以及掌握 SQL 的必要 ...

随机推荐

  1. Luogu P2057 [SHOI2007]善意的投票

    题目链接 \(Click\) \(Here\) 考虑模型转换.变成文理分科二选一带收益模型,就一波带走了. 如果没有见过这个模型的话,这里讲的很详细. #include <bits/stdc++ ...

  2. (二叉树 递归) leetcode 144. Binary Tree Preorder Traversal

    Given a binary tree, return the preorder traversal of its nodes' values. Example: Input: [1,null,2,3 ...

  3. 常见Web攻击

    一.SQL注入 1. sql注入的危害 非法读取.篡改.删除数据库中的数据 盗取用户的各类敏感信息,获取利益 通过修改数据库来修改网页上的内容 注入木马等 2. 实例 MYSQLDB # 通过在用户名 ...

  4. JN_0005:PS改变图片指定内容颜色

    1,打开图片. 2,选择选区,抽取出独立图存 选中选区,按ctrl + alt + j ,抽取图层. 3,选中图层,再按住 ctrl,点击图层图标 的白色选区处,即可选中图层中的内容. 4,选中图层内 ...

  5. Django - 模式、简单使用

    著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层:他们之间以一种插件似的,松耦合的方式连接在一起. 模型负责业务对象与数据库的对象(ORM) 视图负责与用户的交 ...

  6. 使用select为描述符设置超时

    int readable_timeo(int fd, int sec) { fd_set rset; struct timeval tv; FD_ZERO(&rset); FD_SET(fd, ...

  7. Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值

    参考链接:https://blog.csdn.net/lander_xiong/article/details/79018737

  8. linux文件系统初始化过程(4)---加载initrd(中)

    一.目的 上文详细介绍了CPIO格式的initrd文件,本文从源代码角度分析加载并解析initrd文件的过程. initrd文件和linux内核一般存储在磁盘空间中,在系统启动阶段由bootload负 ...

  9. 给Ubuntu系统清理垃圾

    原文地址:https://blog.csdn.net/levon2018/article/details/81746613 1.清理下载的软件包  不过与你想象的可能有很大的不同,Ubuntu系统在运 ...

  10. 帆软报表(finereport) 复选框多值查询

    定义数据集 SELECT * FROM 库存 设计模板 设置控件:控件名称 XX  要与 单元格中 取值公式  =$XX   对应,控件值可更改 下拉复选框控件: 设置控件名称(与模板中=$选仓库  ...