Changes between Initial Version and Version 1 of waue/2009/0822


Ignore:
Timestamp:
Aug 19, 2009, 11:01:57 AM (15 years ago)
Author:
waue
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • waue/2009/0822

    v1 v1  
     1[[PageOutline]]
     2{{{
     3#!html
     4<div style="text-align: center;"><big
     5 style="font-weight: bold;"><big><big> hadoop 0.20 程式開發 </big></big></big></div>
     6<div style="text-align: center;"> <big>eclipse plugin + Makefile</big> </div>
     7}}}
     8 = 零. 前言 =
     9 * 開發hadoop 需要用到許多的物件導向語法,包括繼承關係、介面類別,而且需要匯入正確的classpath,否則寫hadoop程式只是打字練習...
     10 * 用類 vim 來處理這種複雜的程式,有可能會變成一場惡夢,因此用eclipse開發,搭配mapreduce-plugin會事半功倍。
     11 * 早在hadoop 0.19~0.16之間的版本,筆者就試過各個plugin,每個版本的plugin都確實有大大小小的問題,如:hadoop plugin 無法正確使用、無法run as mapreduce。hadoop0.16搭配IBM的hadoop_plugin 可以提供完整的功能,但是,老兵不死,只是凋零...
     12 * 子曰:"逝者如斯夫,不捨晝夜",以前寫的文件也落伍了,要跟上潮流,因此此篇的重點在:'''用eclipse 3.4.2 開發hadoop 0.20程式,並且測試撰寫的程式運作在hadoop平台上'''
     13 * 以下是我的作法,如果你有更好的作法,或有需要更正的地方,請與我聯絡
     14
     15 || 單位 || 作者 || Mail ||
     16 || 國家高速網路中心-格網技術組 || Wei-Yu Chen || waue @ nchc.org.tw ||
     17 
     18 * Last Update: 2009/06/25
     19
     20 == 0.1 環境說明 ==
     21 * ubuntu 8.10
     22 * sun-java-6
     23 * eclipse 3.4.2
     24 * hadoop 0.20.0
     25 == 0.2 目錄說明 ==
     26 * 使用者:waue
     27 * 使用者家目錄: /home/waue
     28 * 專案目錄 : /home/waue/workspace
     29 * hadoop目錄: /opt/hadoop
     30 = 一、安裝 =
     31
     32安裝的部份沒必要都一模一樣,僅提供參考,反正只要安裝好java , hadoop , eclipse,並清楚自己的路徑就可以了
     33
     34 == 1.1. 安裝java ==
     35 
     36首先安裝java 基本套件
     37 
     38{{{
     39$ sudo apt-get install java-common sun-java6-bin sun-java6-jdk sun-java6-jre
     40}}}
     41
     42 == 1.1.1. 安裝sun-java6-doc ==
     43 
     44 1 將javadoc (jdk-6u10-docs.zip) 下載下來
     45 [https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jdk-6u10-docs-oth-JPR@CDS-CDS_Developer 下載點]
     46[[Image(1-1.png)]]
     47 
     48 2 下載完後將檔案放在 /tmp/ 下
     49
     50 3 執行
     51 
     52{{{
     53$ sudo apt-get install sun-java6-doc
     54}}}
     55
     56 == 1.2. ssh 安裝設定 ==
     57
     58{{{
     59$ apt-get install ssh
     60$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
     61$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
     62$ ssh localhost
     63}}}
     64
     65執行ssh localhost 沒有出現詢問密碼的訊息則無誤
     66
     67 == 1.3. 安裝hadoop ==
     68
     69安裝hadoop0.20到/opt/並取目錄名為hadoop
     70
     71{{{
     72$ cd ~
     73$ wget http://apache.ntu.edu.tw/hadoop/core/hadoop-0.20.0/hadoop-0.20.0.tar.gz
     74$ tar zxvf hadoop-0.20.0.tar.gz
     75$ sudo mv hadoop-0.20.0 /opt/
     76$ sudo chown -R waue:waue /opt/hadoop-0.20.0
     77$ sudo ln -sf /opt/hadoop-0.20.0 /opt/hadoop
     78}}}
     79
     80 * 編輯 /opt/hadoop/conf/hadoop-env.sh
     81
     82{{{
     83#!sh
     84export JAVA_HOME=/usr/lib/jvm/java-6-sun
     85export HADOOP_HOME=/opt/hadoop
     86export PATH=$PATH:/opt/hadoop/bin
     87}}}
     88
     89 * 編輯 /opt/hadoop/conf/core-site.xml
     90
     91{{{
     92#!sh
     93<configuration>
     94  <property>
     95    <name>fs.default.name</name>
     96    <value>hdfs://localhost:9000</value>
     97  </property>
     98  <property>
     99    <name>hadoop.tmp.dir</name>
     100    <value>/tmp/hadoop/hadoop-${user.name}</value>
     101  </property>
     102</configuration>
     103
     104}}}
     105
     106 * 編輯 /opt/hadoop/conf/hdfs-site.xml
     107
     108{{{
     109#!sh
     110<configuration>
     111  <property>
     112    <name>dfs.replication</name>
     113    <value>1</value>
     114  </property>
     115</configuration>
     116}}}
     117
     118 * 編輯 /opt/hadoop/conf/mapred-site.xml
     119
     120{{{
     121#!sh
     122<configuration>
     123  <property>
     124    <name>mapred.job.tracker</name>
     125    <value>localhost:9001</value>
     126  </property>
     127</configuration>
     128}}}
     129
     130 * 啟動
     131{{{
     132$ cd /opt/hadoop
     133$ source /opt/hadoop/conf/hadoop-env.sh
     134$ hadoop namenode -format
     135$ start-all.sh
     136$ hadoop fs -put conf input
     137$ hadoop fs -ls
     138}}}
     139
     140 * 沒有錯誤訊息則代表無誤
     141
     142 == 1.4. 安裝eclipse ==
     143 
     144 * 在此提供兩個方法來下載檔案
     145   * 方法一:下載 [http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.4.2-200902111700/eclipse-SDK-3.4.2-linux-gtk.tar.gz eclipse SDK 3.4.2 Classic],並且放這檔案到家目錄
     146   * 方法二:貼上指令
     147{{{
     148$ cd ~
     149$ wget http://ftp.cs.pu.edu.tw/pub/eclipse/eclipse/downloads/drops/R-3.4.2-200902111700/eclipse-SDK-3.4.2-linux-gtk.tar.gz
     150}}}
     151
     152 * eclipse 檔已下載到家目錄後,執行下面指令:
     153 
     154{{{
     155$ cd ~
     156$ tar -zxvf eclipse-SDK-3.4.2-linux-gtk.tar.gz
     157$ sudo mv eclipse /opt
     158$ sudo ln -sf /opt/eclipse/eclipse /usr/local/bin/
     159
     160}}}
     161
     162 = 二、 建立專案 =
     163
     164== 2.1 安裝hadoop 的 eclipse plugin ==
     165
     166 * 匯入hadoop 0.20.0 eclipse plugin
     167 
     168{{{
     169$ cd /opt/hadoop
     170$ sudo cp /opt/hadoop/contrib/eclipse-plugin/hadoop-0.20.0-eclipse-plugin.jar /opt/eclipse/plugins
     171}}}
     172
     173{{{
     174$ sudo vim /opt/eclipse/eclipse.ini
     175}}}
     176
     177 * 可斟酌參考eclipse.ini內容(非必要)
     178 
     179{{{
     180#!sh
     181-startup
     182plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20081125.jar
     183--launcher.library
     184plugins/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805
     185-showsplash
     186org.eclipse.platform
     187--launcher.XXMaxPermSize
     188512m
     189-vmargs
     190-Xms40m
     191-Xmx512m
     192}}}
     193
     194== 2.2 開啟eclipse ==
     195
     196 * 打開eclipse
     197 
     198{{{
     199$ eclipse &
     200}}}
     201
     202一開始會出現問你要將工作目錄放在哪裡:在這我們用預設值
     203[[Image(2-1.png)]]
     204-------
     205
     206'''PS: 之後的說明則是在eclipse 上的介面操作'''
     207
     208-------
     209
     210== 2.3 選擇視野 ==
     211
     212|| window -> || open pers.. -> || other.. -> || map/reduce||
     213
     214[[Image(win-open-other.png)]]
     215
     216-------
     217
     218設定要用 Map/Reduce 的視野
     219[[Image(2-2.png)]]
     220
     221---------
     222
     223使用 Map/Reduce 的視野後的介面呈現
     224[[Image(2-3.png)]]
     225
     226--------
     227
     228== 2.4 建立專案 ==
     229
     230 || file ->  || new ->  || project ->  || Map/Reduce ->  || Map/Reduce Project -> ||  next ||
     231[[Image(file-new-project.png)]]
     232
     233--------
     234
     235建立mapreduce專案(1)
     236
     237[[Image(2-4.png)]]
     238
     239-----------
     240
     241建立mapreduce專案的(2)
     242{{{
     243#!sh
     244project name-> 輸入 : icas (隨意)
     245use default hadoop -> Configur Hadoop install... -> 輸入: "/opt/hadoop" -> ok
     246Finish
     247}}}
     248
     249[[Image(2-4-2.png)]]
     250
     251
     252--------------
     253
     254== 2.5 設定專案 ==
     255
     256由於剛剛建立了icas這個專案,因此eclipse已經建立了新的專案,出現在左邊視窗,右鍵點選該資料夾,並選properties
     257
     258--------------
     259
     260 Step1. 右鍵點選project的properties做細部設定
     261
     262[[Image(2-5.png)]]
     263
     264----------
     265
     266 Step2. 進入專案的細部設定頁
     267
     268hadoop的javadoc的設定(1)
     269[[Image(2-5-1.png)]]
     270
     271 * java Build Path -> Libraries -> hadoop-0.20.0-ant.jar
     272 * java Build Path -> Libraries -> hadoop-0.20.0-core.jar
     273 * java Build Path -> Libraries ->  hadoop-0.20.0-tools.jar
     274   * 以 hadoop-0.20.0-core.jar 的設定內容如下,其他依此類推
     275   
     276{{{
     277#!sh
     278source ...-> 輸入:/opt/opt/hadoop-0.20.0/src/core
     279javadoc ...-> 輸入:file:/opt/hadoop/docs/api/
     280}}}
     281
     282------------
     283 Step3. hadoop的javadoc的設定完後(2)
     284[[Image(2-5-2.png)]]
     285
     286------------
     287 Step4. java本身的javadoc的設定(3)
     288 
     289 * javadoc location -> 輸入:file:/usr/lib/jvm/java-6-sun/docs/api/
     290 
     291[[Image(2-5-3.png)]]
     292
     293-----
     294設定完後回到eclipse 主視窗
     295
     296
     297== 2.6 連接hadoop server ==
     298
     299--------
     300 Step1. 視窗右下角黃色大象圖示"Map/Reduce Locations tag" -> 點選齒輪右邊的藍色大象圖示:
     301[[Image(2-6.png)]]
     302
     303-------------
     304 Step2. 進行eclipse 與 hadoop 間的設定(2)
     305[[Image(2-6-1.png)]]
     306
     307{{{
     308#!sh
     309Location Name -> 輸入:hadoop  (隨意)
     310Map/Reduce Master -> Host-> 輸入:localhost
     311Map/Reduce Master -> Port-> 輸入:9001
     312DFS Master -> Host-> 輸入:9000
     313Finish
     314}}}
     315----------------
     316
     317設定完後,可以看到下方多了一隻藍色大象,左方展開資料夾也可以秀出在hdfs內的檔案結構
     318[[Image(2-6-2.png)]]
     319-------------
     320
     321 = 三、 撰寫範例程式 =
     322
     323 * 之前在eclipse上已經開了個專案icas,因此這個目錄在:
     324   * /home/waue/workspace/icas
     325 * 在這個目錄內有兩個資料夾:
     326   * src : 用來裝程式原始碼
     327   * bin : 用來裝編譯後的class檔
     328 * 如此一來原始碼和編譯檔就不會混在一起,對之後產生jar檔會很有幫助
     329 * 在這我們編輯一個範例程式 : WordCount
     330
     331 == 3.1 mapper.java ==
     332 
     333 1. new
     334 
     335 || File ->  || new ->  || mapper ||
     336[[Image(file-new-mapper.png)]]
     337
     338-----------
     339
     340 2. create
     341 
     342[[Image(3-1.png)]]
     343{{{
     344#!sh
     345source folder-> 輸入: icas/src
     346Package : Sample
     347Name -> : mapper
     348}}}
     349----------
     350
     351 3. modify
     352 
     353{{{
     354#!java
     355package Sample;
     356
     357import java.io.IOException;
     358import java.util.StringTokenizer;
     359
     360import org.apache.hadoop.io.IntWritable;
     361import org.apache.hadoop.io.Text;
     362import org.apache.hadoop.mapreduce.Mapper;
     363
     364public class mapper extends Mapper<Object, Text, Text, IntWritable> {
     365
     366        private final static IntWritable one = new IntWritable(1);
     367        private Text word = new Text();
     368
     369        public void map(Object key, Text value, Context context)
     370                        throws IOException, InterruptedException {
     371                StringTokenizer itr = new StringTokenizer(value.toString());
     372                while (itr.hasMoreTokens()) {
     373                        word.set(itr.nextToken());
     374                        context.write(word, one);
     375                }
     376        }
     377}
     378}}}
     379
     380建立mapper.java後,貼入程式碼
     381[[Image(3-2.png)]]
     382
     383------------
     384
     385== 3.2 reducer.java ==
     386
     387 1. new
     388
     389 * File -> new -> reducer
     390[[Image(file-new-reducer.png)]]
     391
     392-------
     393 2. create
     394[[Image(3-3.png)]]
     395
     396{{{
     397#!sh
     398source folder-> 輸入: icas/src
     399Package : Sample
     400Name -> : reducer
     401}}}
     402
     403-----------
     404
     405 3. modify
     406 
     407{{{
     408#!java
     409package Sample;
     410
     411import java.io.IOException;
     412
     413import org.apache.hadoop.io.IntWritable;
     414import org.apache.hadoop.io.Text;
     415import org.apache.hadoop.mapreduce.Reducer;
     416
     417public class reducer extends Reducer<Text, IntWritable, Text, IntWritable> {
     418        private IntWritable result = new IntWritable();
     419
     420        public void reduce(Text key, Iterable<IntWritable> values, Context context)
     421                        throws IOException, InterruptedException {
     422                int sum = 0;
     423                for (IntWritable val : values) {
     424                        sum += val.get();
     425                }
     426                result.set(sum);
     427                context.write(key, result);
     428        }
     429}
     430}}}
     431
     432 * File -> new -> Map/Reduce Driver
     433[[Image(file-new-mr-driver.png)]]
     434----------
     435
     436== 3.3 WordCount.java (main function) ==
     437
     438 1. new
     439
     440建立WordCount.java,此檔用來驅動mapper 與 reducer,因此選擇 Map/Reduce Driver
     441[[Image(3-4.png)]]
     442------------
     443
     444 2. create
     445
     446{{{
     447#!sh
     448source folder-> 輸入: icas/src
     449Package : Sample
     450Name -> : WordCount.java
     451}}}
     452
     453-------
     454 3. modify
     455
     456{{{
     457#!java
     458package Sample;
     459
     460import org.apache.hadoop.conf.Configuration;
     461import org.apache.hadoop.fs.Path;
     462import org.apache.hadoop.io.IntWritable;
     463import org.apache.hadoop.io.Text;
     464import org.apache.hadoop.mapreduce.Job;
     465import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
     466import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
     467import org.apache.hadoop.util.GenericOptionsParser;
     468
     469public class WordCount {
     470
     471        public static void main(String[] args) throws Exception {
     472                Configuration conf = new Configuration();
     473                String[] otherArgs = new GenericOptionsParser(conf, args)
     474                                .getRemainingArgs();
     475                if (otherArgs.length != 2) {
     476                        System.err.println("Usage: wordcount <in> <out>");
     477                        System.exit(2);
     478                }
     479                Job job = new Job(conf, "word count");
     480                job.setJarByClass(WordCount.class);
     481                job.setMapperClass(mapper.class);
     482
     483                job.setCombinerClass(reducer.class);
     484                job.setReducerClass(reducer.class);
     485                job.setOutputKeyClass(Text.class);
     486                job.setOutputValueClass(IntWritable.class);
     487                FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
     488                FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
     489                System.exit(job.waitForCompletion(true) ? 0 : 1);
     490        }
     491}
     492}}}
     493
     494三個檔完成後並存檔後,整個程式建立完成
     495[[Image(3-5.png)]]
     496
     497-------
     498
     499 * 三個檔都存檔後,可以看到icas專案下的src,bin都有檔案產生,我們用指令來check
     500 
     501{{{
     502$ cd workspace/icas
     503$ ls src/Sample/
     504mapper.java  reducer.java  WordCount.java
     505$ ls bin/Sample/
     506mapper.class  reducer.class  WordCount.class
     507}}}
     508
     509 = 四、測試範例程式 =
     510 
     511 * 由於hadoop 0.20 此版本的eclipse-plugin依舊不完整 ,如:
     512   * 右鍵點選WordCount.java -> run as -> run on Hadoop :沒有效果
     513   
     514[[Image(run-on-hadoop.png)]]
     515
     516 * 因此,4.1 提供一個eclipse 上解除 run-on-hadoop 封印的方法。而4.2 則是避開run-on-hadoop 這個功能,用command mode端指令的方法執行。
     517
     518
     519 == 4.1 解除run-on-hadoop封印 ==
     520
     521有一熱心的hadoop使用者提供一個能讓 run-on-hadoop 這個功能恢復的方法。
     522
     523原因是hadoop 的 eclipse-plugin 也許是用eclipse europa 這個版本開發的,而eclipse 的各版本 3.2 , 3.3, 3.4 間也都有或多或少的差異性存在。
     524
     525因此如果先用eclipse europa 來建立一個新專案,之後把europa的eclipse這個版本關掉,換用eclipse 3.4開啟,之後這個專案就能用run-on-mapreduce 這個功能囉!
     526
     527有興趣的話可以試試!(感謝逢甲資工所謝同學)
     528
     529 == 4.2 運用終端指令 ==
     530 === 4.2.1 產生Makefile 檔 ===
     531{{{
     532
     533$ cd /home/waue/workspace/icas/
     534$ gedit Makefile
     535}}}
     536
     537 * 輸入以下Makefile的內容
     538{{{
     539#!sh
     540
     541JarFile="sample-0.1.jar"
     542MainFunc="Sample.WordCount"
     543LocalOutDir="/tmp/output"
     544
     545all:help
     546jar:
     547  jar -cvf ${JarFile} -C bin/ .
     548
     549run:
     550  hadoop jar ${JarFile} ${MainFunc} input output
     551
     552clean:
     553  hadoop fs -rmr output
     554
     555output:
     556  rm -rf ${LocalOutDir}
     557  hadoop fs -get output ${LocalOutDir}
     558  gedit ${LocalOutDir}/part-r-00000 &
     559
     560help:
     561  @echo "Usage:"
     562  @echo " make jar     - Build Jar File."
     563  @echo " make clean   - Clean up Output directory on HDFS."
     564  @echo " make run     - Run your MapReduce code on Hadoop."
     565  @echo " make output  - Download and show output file"
     566  @echo " make help    - Show Makefile options."
     567  @echo " "
     568  @echo "Example:"
     569  @echo " make jar; make run; make output; make clean"
     570
     571}}}
     572
     573 === 4.2.2 執行 ===
     574 
     575 * 執行Makefile,可以到該目錄下,執行make [參數],若不知道參數為何,可以打make 或 make help
     576 * make 的用法說明
     577
     578{{{
     579$ cd /home/waue/workspace/icas/
     580$ make
     581Usage:
     582 make jar     - Build Jar File.
     583 make clean   - Clean up Output directory on HDFS.
     584 make run     - Run your MapReduce code on Hadoop.
     585 make output  - Download and show output file
     586 make help    - Show Makefile options.
     587 
     588Example:
     589 make jar; make run; make output; make clean
     590}}}
     591
     592 * 下面提供各種make 的參數
     593 
     594 === make jar ===
     595 * 1. 編譯產生jar檔
     596 
     597{{{
     598$ make jar
     599}}}
     600
     601 === make run ===
     602 * 2. 跑我們的wordcount 於hadoop上
     603
     604{{{
     605$ make run
     606}}}
     607
     608 * make run基本上能正確無誤的運作到結束,因此代表我們在eclipse編譯的程式可以順利在hadoop0.20的平台上運行。
     609
     610 * 而回到eclipse視窗,我們可以看到下方視窗run完的job會呈現出來;左方視窗也多出output資料夾,part-r-00000就是我們的結果檔
     611 
     612[[Image(4-1.png)]]
     613------
     614 * 因為有設定完整的javadoc, 因此可以得到詳細的解說與輔助
     615[[Image(4-2.png)]]
     616
     617 === make output ===
     618 * 3. 這個指令是幫助使用者將結果檔從hdfs下載到local端,並且用gedit來開啟你的結果檔
     619
     620{{{
     621$ make output
     622}}}
     623
     624 === make clean ===
     625 * 4. 這個指令用來把hdfs上的output資料夾清除。如果你還想要在跑一次make run,請先執行make clean,否則hadoop會告訴你,output資料夾已經存在,而拒絕工作喔!
     626 
     627{{{
     628$ make clean
     629}}}
     630
     631= 五、結論 =
     632
     633 * 搭配eclipse ,我們可以更有效率的開發hadoop
     634 * hadoop 0.20 與之前的版本api以及設定都有些改變,可以看 [wiki:waue/2009/0618 hadoop 0.20 coding (eclipse )]