Hadoop pipes设计原理

来源:互联网 发布:java 引用 编辑:程序博客网 时间:2024/05/22 02:11

1. 什么是Hadoop pipes?

Hadooppipes允许用户使用C++语言进行MapReduce程序设计。它采用的主要方法是将应用逻辑相关的C++代码放在单独的进程中,然后通过Socket让Java代码与C++代码通信。从很大程度上说,这种方法类似于HadoopStreaming,不同的是,它采用Writable序列化方法将数据转化为byte,然后通过socket传给C++进程。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
bin/hadoop pipes \
  
[-input inputDir] \ #输入数据目录
  
[-output outputDir] \ #输出数据目录
  
[-jarapplicationJarFile] \  #应用程序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配置文件
  
[-Dproperty=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 ofarchives]#已经上传到HDFS中的jar文件,可以 在程序中直接使用

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

2. Hadoop pipes设计架构

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

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

3. Hadoop pipes设计细节

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

(1) mapper

Pipes会根据用户的配置定制InputFormat,如果用户要使用Java的InputFormat(hadoop.pipes.java.recordreader=true),则Hadoop会使用户输入的InputFormat(默认为TextInputFormat);如果用户使用C++的InputFormat,则PipesJava端的代码会读取每个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(conststring& key, const string&value)函数返还给Java Server。

(2) paritioner

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

(3) reducer

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

4. 总结

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

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

5. 参考资料

http://wiki.apache.org/hadoop/HowToDebugMapReducePrograms

http://cs.smith.edu/dftwiki/index.php/Hadoop_Tutorial_2.2_–_Running_C++_Programs_on_Hadoop

http://www.itberry.com/?p=42

原创文章,转载请注明: 转载自董的博客

本文链接地址: http://dongxicheng.org/mapreduce/hadoop-pipes-architecture/


原创粉丝点击