Hadoop概念学习系列之hadoop Java API、 hadoop Streaming 、hadoop Pipes 三者比较学习(十九)

  1. 云栖社区>
  2. 博客>
  3. 正文

Hadoop概念学习系列之hadoop Java API、 hadoop Streaming 、hadoop Pipes 三者比较学习(十九)

技术小哥哥 2017-11-14 16:18:00 浏览1061
展开阅读全文

1、hadoop  Java  API

    Hadoop的主要编程语言是Java,因而,Java API是最基本的对外编程接口。

 

 

2、 hadoop    Streaming

            1、概述

            它是为方便非java用户编写Mapreduce程序而设计的工具包。

             Hadoop Streaming是Hadoop提供的一个编程工具,它允许用户使用任何可执行文件或者脚本文件作为Mapper和Reducer,

  例如: 

        采用shell脚本语言中的一些命令作为mapper和reducer(cat作为mapper,wc作为reducer)

   $HADOOP_HOME/bin/hadoop  jar $HADOOP_HOME/contrib/streaming/hadoop-*-streaming.jar \
      -input myInputDirs \
      -output myOutputDir \
      -mapper cat \
      -reducer wc

 

 

 

    2、Hadoop Streaming原理

    mapper和reducer会从标准输入中读取用户数据,一行一行处理后发送给标准输出。Streaming工具会创建MapReduce作业,发送给各个tasktracker,同时监控整个作业的执行过程。

    如果一个文件(可执行或者脚本)作为mapper,mapper初始化时,每一个mapper任务会把该文件作为一个单独进程启动,mapper任务运行时,它把输入切分成行并把每一行提供给可执行文件进程的标准输入。 同时,mapper收集可执行文件进程标准输出的内容,并把收到的每一行内容转化成key/value对,作为mapper的输出。 默认情况下,一行中第一个tab之前的部分作为key,之后的(不包括tab)作为value如果没有tab,整行作为key值,value值为null。

    对于reducer,类似。

    以上是Map/Reduce框架和streaming mapper/reducer之间的基本通信协议。

 

 

 

     3、Hadoop Streaming用法

      Usage: $HADOOP_HOME/bin/hadoop jar \

      $HADOOP_HOME/contrib/streaming/hadoop-*-streaming.jar [options]

      options:

      (1)-input:输入文件路径

      (2)-output:输出文件路径

      (3)-mapper:用户自己写的mapper程序,可以是可执行文件或者脚本

      (4)-reducer:用户自己写的reducer程序,可以是可执行文件或者脚本

      (5)-file:打包文件到提交的作业中,可以是mapper或者reducer要用的输入文件,如配置文件,字典等。

      (6)-partitioner:用户自定义的partitioner程序

      (7)-combiner:用户自定义的combiner程序(必须用java实现)

      (8)-D:作业的一些属性(以前用的是-jonconf),具体有:
1)mapred.map.tasks:map task数目
2)mapred.reduce.tasks:reduce task数目
3)stream.map.input.field.separator/stream.map.output.field.separator: map task输入/输出数
据的分隔符,默认均为\t。
4)stream.num.map.output.key.fields:指定map task输出记录中key所占的域数目
5)stream.reduce.input.field.separator/stream.reduce.output.field.separator:reduce task输入/输出数据的分隔符,默认均为\t。
6)stream.num.reduce.output.key.fields:指定reduce task输出记录中key所占的域数目
另外,Hadoop本身还自带一些好用的Mapper和Reducer:
(1)    Hadoop聚集功能
Aggregate提供一个特殊的reducer类和一个特殊的combiner类,并且有一系列的“聚合器”(例如“sum”,“max”,“min”等)用于聚合一组value的序列。用户可以使用Aggregate定义一个mapper插件类,这个类用于为mapper输入的每个key/value对产生“可聚合项”。Combiner/reducer利用适当的聚合器聚合这些可聚合项。要使用Aggregate,只需指定“-reducer aggregate”。
(2)字段的选取(类似于Unix中的‘cut’)
Hadoop的工具类org.apache.hadoop.mapred.lib.FieldSelectionMapReduc帮助用户高效处理文本数据,就像unix中的“cut”工具。工具类中的map函数把输入的key/value对看作字段的列表。 用户可以指定字段的分隔符(默认是tab),可以选择字段列表中任意一段(由列表中一个或多个字段组成)作为map输出的key或者value。 同样,工具类中的reduce函数也把输入的key/value对看作字段的列表,用户可以选取任意一段作为reduce输出的key或value。

  关于Hadoop Streaming高级编程方法,可参考这篇文章:Hadoop Streaming高级编程Hadoop编程实例

 

 

 

3、 hadoop  Pipes   

           它是为方便C/C++用户编写Mapreduce程序而设计的工具包。

        Hadoop pipes允许C++程序员编写mapreduce程序,它允许用户混用C++和Java的RecordReader, Mapper, Partitioner,Rducer和RecordWriter等五个组件。

    1. 什么是Hadoop pipes?

    Hadoop pipes允许用户使用C++语言进行MapReduce程序设计。它采用的主要方法是将应用逻辑相关的C++代码放在单独的进程中,然后通过Socket让Java代码与C++代码通信。从很大程度上说,这种方法类似于Hadoop Streaming,不同之处是通信方式不同:一个是标准输入输出,另一个是socket。

    org.apache.hadoop.mapred.pipes.Submitter包中有一个public static方法用于提交作业,该方法将作业封装成一个JobConf对象和一个main方法(接收一个应用程序,可选的配置文件,输入目录和输出目录等),main方法的CLI(Client Line Interface)如下:

 

bin/hadoop pipes \
 
[-input inputDir] \ #输入数据目录
 
[-output outputDir] \ #输出数据目录
 
[-jar applicationJarFile] \  #应用程序jar包
 
[-inputformat class] \ #Java版的InputFormat
 
[-map class] \ #Java版的Mapper
 
[-partitioner class] \#Java版的Partitioner
 
[-reduce class] \#Java版的Reducer
 
[-writer class] \ #Java版的 RecordWriter
 
[-program program url] \  #C++可执行程序
 
[-conf configuration file] \#xml配置文件
 
[-D property=value] \ #配置JobConf属性
 
[-fs local|namenode:port] \#配置namenode
 
[-jt local|jobtracker:port] \#配置jobtracker
 
[-files comma separated list of files] \ #已经上传文件到HDFS中的文件,它们可以像在本地一样打开
 
[-libjars comma separated list of jars] \#要添加到classpath 中的jar包
 
[-archives comma separated list of archives]#已经上传到HDFS中的jar文件,可以 在程序中直接使用

    本文主要介绍了Hadoop pipes的设计原理,包括设计架构,设计细节等。 

 

 

    2. Hadoop pipes设计架构

    用户通过bin/hadoop pipes将作业提交到org.apache.hadoop.mapred.pipes中的Submmit类,它首先会进行作业参数配置(调用函数setupPipesJob),然后通过JobClient(conf).submitJob(conf)将作业提交到Hadoop集群中。

      在函数setupPipesJob中,Java代码会使用ServerScoket创建服务器对象,然后通过ProcessBuilder执行C++binary, C++binary实际上是一个Socket client,它从Java server中接收key/value数据,经过处理(map,partition或者reduce等)后,返还给Java server,并由Java Server将数据写到HDFS或者磁盘。

 

 

 

 

       3. Hadoop pipes设计细节

      Hadoop pipes允许用户用C++编写五个基本组件:mapper,reducer,partitioner,combiner,recordReader,这五个组件可以是Java编写的,也可以是C++编写的,下面分别介绍这几个函数的执行过程。

    (1) mapper

  Pipes会根据用户的配置定制InputFormat,如果用户要使用Java的InputFormat(hadoop.pipes.java.recordreader=true),则Hadoop会使用户输入的InputFormat(默认为TextInputFormat);如果用户使用C++的InputFormat,则Pipes Java端的代码会读取每个InputSplit,并调用downlink.runMap(reporter.getInputSplit(), job.getNumReduceTasks(), isJavaInput);通过socket传输给C++端的runMap(string _inputSplit, int _numReduces, bool pipedInput)函数。

     在C++端,RecordReader会解析整个InputSplit,获取数据来源(主要是文件路径)和每个key/value对,并交给map函数处理,map将每个key/value的处理结果通过emit(const string& key, const string& value)函数返还给Java Server。

    (2) paritioner

    C++端处理完的结果会通过emit(const string& key, const string& value)函数传给Java Server,以便将数据写到磁盘上。在emit函数中,如果用户定义了自己的paritioner,则Pipes会通过该函数判断当前key/value将给哪个reduce task处理,并调用partitionedOutput(int reduce, const string& key,const string& value)函数将key/value传递给相应的reduce task。

    (3) reducer

    reducer的执行过程与mapper基本一致。

 

 

 

 4. 总结

    Hadoop pipes给C++程序员提供了一个编写MapReduce作业的方案,它使用socket让Java和C++之间进行通信,这类似于thrift RPC的原理,也许Hadoop Pipes用thrift编写会更加简单。

    Hadoop pipes使用Java代码从HDFS上读写数据,并将处理逻辑封装到C++中,数据会通过socket从Java传输给C++,这虽然增加了数据传输的代价,但对于计算密集型的作业,其性能也许会有改进。

 


本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5449082.html,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论
技术小哥哥
+ 关注