文档章节

Hadoop Job的提交,到底提交了什么?

震秦
 震秦
发布于 2013/09/22 19:30
字数 1584
阅读 6623
收藏 12

##一个最基本的Hadoo任务 WordCountMapper:

<pre class="prettyprint lang-java"> private final static IntWritable one = new IntWritable(1); @Override public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { StringTokenizer tokenizer = new StringTokenizer(value.toString()); while (tokenizer.hasMoreTokens()) { String str = tokenizer.nextToken(); context.write(new Text(StringUtils.trim(str.replaceAll("\\W", ""))), one); } } </pre>

WordCountReduce:

<pre class="prettyprint lang-java"> @Override public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } context.write(key, new IntWritable(sum)); } </pre>

WordCount:

<pre class="prettyprint lang-java"> final Configuration conf = new Configuration(); Job job = new Job(conf); job.setJobName("wordcount"); job.setJarByClass(WordCount.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); job.setMapperClass(WordCountMapper.class); job.setReducerClass(WordCountReduce.class); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); FileInputFormat.setInputPaths(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); boolean success = job.waitForCompletion(true); </pre>

如你所见, 这是个Hadoop基础的入门例子, 如果你了解Hadoop, 你已经对这些代码熟记于心了.这篇文章我想说明Hadoop提交Job到底提交了那些东西,提交了哪些类,不需要提交那些东西.

##Hadoop任务提交

###传统的Hadoop任务提交

把上面的代码<code> WordCountMapper, WordCountReduce, WordCount</code>打包成jar,放到hadoop目录下, 使用<code>hadoop jar wordcount.jar WordCount</code>运行任务. 这样方式我称为传统的方式,也是《hadoop权威指南》上一贯的方法.

###Eclipse的hadoop插件的Hadoop任务提交

如果你开发过Hadoop的Job, 那么对这个应该很熟悉.大多数开发测试都是用这个提交任务的,如果每次都是打包成jar, 再用hadoop jar ** 这还不把人搞疯.

如果你还细心,你会发现,你选好Hadoop的jobtracker,提交任务的前一刻,Eclipse会弹出一个浮动窗口,上面跳动着显示很多jar名.为什么会这样?它做了什么?

在此输入图片描述

###在Eclipse中当做Java Application运行为什么不可以?

Hadoop的job项目都有main方法,这个是符合JavaApplication运行条件的,那么我们是不是可以使用Eclipse中直接运行呢?当我们尝试运行的时候,程序是可以运行的,但总当运行一会儿(几秒钟)后抛出WordCountMapper <code>ClassNotFount</code>的错误.

那么为什么程序不是直接抛出错误而是过了一会儿才抛出?为什么用Eclipse Hadoop插件运行不会发生这个错误.

##背景

写这篇文章前,我们已经正在开发一个Hadoop的任务调度的系统. 也就是一个项目中提前写好很多个Hadoop Job绑定到里边,如果想要运行哪个Job,我们就从前台配置好参数,并把这个Job提交到Hadoop集群. 并从前台不断的得到Job的运行任务信息,取得Job的执行进度. 不关心进度的话直接去喝茶就可以,完了来看结果.

如果每次都是<code>hadoop jar wordcount.jar WordCount</code>未免太弱智. 如果每次从Eclispe中运行,那专业性太强,也不可取.是不是有更好的方法提交任务?

答案肯定是有的.

##用JVisualVM监视Eclipse hadoop插件的Hadoop任务提交

打开JVisualVM准备着,运行一个Job. 运行后立即就可以看到一个Java进程. 用JVisualVM打开这个进程查看,如图:

在此输入图片描述

在此输入图片描述

我打开我电脑上的目录<code>F:\Eclipse\workspace.metadata.plugins\org.apache.hadoop.eclipse\hadoop-conf-1007657720166395816</code>并且查看了它的上级目录,顿时一些皆明朗了.Eclipse Hadoop插件竟然把我的项目下所有的类,资源文件打包成jar然后运行的.

在此输入图片描述

在此输入图片描述

##使用Hadoop Api提交Job,完美解决方案

其实我也是从这篇文章(http://luliangy.iteye.com/blog/1401453)中找到灵感的.为什么把项目打包,以Java Application的方式就正常运行了.

<pre class="prettyprint lang-java"> ((JobConf) job.getConfiguration()).setJar("wordcount.jar"); job.setJarByClass(WordCount.class); </pre>

冲着这股劲我看了很多Hadoop API,终于找到为什么.

通过<code>job.setJarByClass(WordCount.class); </code>这条路查看源码, 你会找到如下的两个方法.

<pre class="prettyprint lang-java"> private static String findContainingJar(Class my_class) { ClassLoader loader = my_class.getClassLoader(); String class_file = my_class.getName().replaceAll("\\.", "/") + ".class"; try { for(Enumeration itr = loader.getResources(class_file); itr.hasMoreElements();) { URL url = (URL) itr.nextElement(); if ("jar".equals(url.getProtocol())) { String toReturn = url.getPath(); if (toReturn.startsWith("file:")) { toReturn = toReturn.substring("file:".length()); } toReturn = URLDecoder.decode(toReturn, "UTF-8"); return toReturn.replaceAll("!.*$", ""); } } } catch (IOException e) { throw new RuntimeException(e); } return null; } public void setJarByClass(Class cls) { String jar = findContainingJar(cls); if (jar != null) { setJar(jar); } } </pre>

我说说<code>findContainingJar</code>有什么作用? 当使用<code>job.setJarByClass(WordCount.class);</code>设置类的时候, Hadoop Client能从你的classpath中取得<code>WordCount.class</code>所在的jar包的jar File绝对路径.如果找不到jar, <code>setJar(jar);</code>方法没有执行,jar肯定是个空值.

我们在Eclipse中直接以Java Application运行的时候,classpath是一个本地文件夹, findContainingJar肯定找不到项目的jar.也就是Mapper和Reduce所在的jar. 这样在提交任务时候Configuration中<code>mapper.jar</code>属性是一个空值.这也就解释了为什么在Eclipse中当做Java Application运行时总是过一段时间后才发生ClassNotFound的错误原因.

其实到这里Hadoop提交了什么也好解释了.

Hadoop向集群中提交了一个xml和一个携带Mapper/Reduce的jar. xml就是Configuration对象序列化的结果.

说到这里也许你已经发现,这是一个开发上的架构问题.既然Hadoop Job需要Map/Reduce的jar.我们应该把所有的Map/Reduce单独在一个项目中开发.然后打包放入调度系统项目的ClassPath就好了.然后在调度系统中构造Job,并把<code>job.setJarByClass(class);</code>中的class设置为该Job的map clas或者reduce class就行了.

##哪些是在Client执行的?哪些是在Hadoop集群中执行?

一个Hadoop 任务一般都有3个类(Map/Reduce/Job).<code>WordCountMapper, WordCountReduce, WordCount</code>你认为这三个类都会提交到集群中执行吗?

不是! 只有Mapper和Reduce这2个类会提交到Hadoop集群, MapReduce执行也是这2个类. WordCount只是充当一个配置Job的客户端,并且提交任务,之后又定时轮询Job的运行状态输出简单的日志,直到任务完成,WordCount的这个进程会自动退出.

##Hadoop分布式缓存

讲到这里你也许能顺利的实现一个和我相同思路的系统了.

但是我还是想说一个常见错误. 不是Mapper Class NotFound,而是Mapper中使用的Class NotFound. 而你又不想往hadoop集群中添加jar包,也不想重启Hadoop集群. 你可以使用Hadoop提供的一个类:<code>DistributedCache</code>

  1. DistributedCache.addArchiveToClassPath() 添加hdfs上的jar到MapReduce的classpath
  2. DistributedCache.addCacheFile(new URI("/myapp/lookup.dat#lookup.dat"), job);
  3. DistributedCache.addCacheArchive(new URI("/myapp/map.zip", job);
  4. DistributedCache.addFileToClassPath(new Path("/myapp/mylib.jar"), job);
  5. DistributedCache.addCacheArchive(new URI("/myapp/mytar.tar", job);
  6. DistributedCache.addCacheArchive(new URI("/myapp/mytgz.tgz", job);
  7. DistributedCache.addCacheArchive(new URI("/myapp/mytargz.tar.gz", job);

© 著作权归作者所有

震秦
粉丝 190
博文 34
码字总数 35126
作品 0
西安
架构师
私信 提问
加载中

评论(3)

Iuranus
Iuranus

引用来自“震秦”的评论

引用来自“Iuranus”的评论

请问你用的是Hadoop的哪个版本,Eclipse插件不在2.2.0中。

1.0.4

那针对Hadoop这个版本的,一些配置优化上有哪些最佳实践?
震秦
震秦 博主

引用来自“Iuranus”的评论

请问你用的是Hadoop的哪个版本,Eclipse插件不在2.2.0中。

1.0.4
Iuranus
Iuranus
请问你用的是Hadoop的哪个版本,Eclipse插件不在2.2.0中。
初学大数据,一定要知道这些

经常有初学者问我,自己想往大数据方向发展,该学哪些技术,学习路线是什么样的,觉得大数据很火,就业很好,薪资很高。。。。。。。如果自己很迷茫,为了这些原因想往大数据方向发展,也可以...

铁扇公主1
2017/03/22
377
1
hadoop中NameNode、DataNode、Secondary、NameNode、JobTracker TaskTracker介绍

http://www.aboutyun.com/thread-7778-1-1.html 问题导读: 1.job的本质是什么? 2.任务的本质是什么? 3.文件系统的Namespace由谁来管理,Namespace的作用是什么? 4.Namespace 镜像文件(Na...

chenkechao
2016/11/23
29
0
大话大数据(一)

大数据的4V特征: 数据量大,TB->PB 数据类型繁多,结构化、非结构化文本、日志、视频、图片、地理位置等; 商业价值高,但是这种价值需要在海量数据之上,通过数据分析与机器学习更快速的挖...

提广乾
2016/11/25
47
0
hadoop中NameNode、DataNode、Secondary、NameNode、JobTra

Hadoop是一个能够对大量数据进行分布式处理的软件框架,实现了Google的MapReduce编程模型和框架,能够把应用程序分割成许多的 小的工作单元,并把这些单元放到任何集群节点上执行。在MapRedu...

kongjun
2016/02/24
399
1
MapReduce V1:Job提交流程之JobClient端分析

我们基于Hadoop 1.2.1源码分析MapReduce V1的处理流程。 MapReduce V1实现中,主要存在3个主要的分布式进程(角色):JobClient、JobTracker和TaskTracker,我们主要是以这三个角色的实际处理...

脸大的都是胖纸
2015/10/09
548
0

没有更多内容

加载失败,请刷新页面

加载更多

基于CentOS7搭建GitLab

基于CentOS7搭建GitLab 12018.11.02 16:38:51字数 959阅读 3791 本文作者:蓝雄威,叩丁狼高级讲师。原创文章,转载请注明出处。 一、简介 Git Lab GitLab是利用 Ruby on Rails 一个开源的版...

linjin200
20分钟前
4
0
random生成随机数

随机生成0到100之间的10个随机数,然后使用冒泡排序将这10个数按从小到大的顺序排序 生成10个随机数 import randomnum = range(0, 100) # 范围在0到100之间,需要用到range()函数。nums...

彩色泡泡糖
23分钟前
3
0
kubernetes 环境搭建 —— kubeadm

主从节点需要安装的服务 Master 节点 Node 节点 etcd-master Control plane(如:calico,fannel) kube-apiserver kube-proxy kube-controller-manager other apps kube-dns Control plane(如:......

lemos
26分钟前
4
0
php将字符串中的中英文数字分割

$str = "php如何将字 符串中322的字母数字Asf f45d和中文_分割?"; $arr = preg_split("/([a-zA-Z0-9]+)/", $str, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); print_r($arr); Arr......

小小小壮
26分钟前
3
0
茑屋书店理解(一)

说到实体书店,你可能会想到两个字“难做”。一是电子书大为盛行,二是纸书作为标准品,完全可以在网上购买,因此国内许多实体书店的日子是举步维艰。但是在日本有这么一家实体书店,目前已经...

Idea
30分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部