此文章的前提是:知道hadoop是什麼,知道什麼是分佈式系統,瞭解hdfs和mapreduce的概念和原理。這裏只是把筆者在學習hadoop過程中的一些經驗和自己的看法分享一下。此文章包括兩部分:
1、hadoop 在 redhat linux下的安裝過程
網上有很多講授在windows下通過Cygwin安裝hadoop的,筆者認爲hadoop原始設計就是在linux下安裝使用的,在windows下通過Cygwin安裝也無非是模擬linux環境再在這個模擬的環境上裝hadoop,既然要學hadoop就真槍實彈的在linux下安裝來學習,但是要搞一臺真正的linux系統對一般個人來說不容易,但是我們可以用虛擬機VMware Player,就是在windows下裝一個虛擬機(VMware Player 就是個很好的虛擬機),然後在虛擬機上裝一個linux系統,實現和本機windows的通信,具體的怎麼安裝虛擬機,怎麼在虛擬機上安裝linux,以及怎麼實現和本機windows的通信,這裏就不講了,這個網上有很多資料。
2、在本機windows下,通過eclispe連接到linux虛擬機上安裝好的haoop,進行開發調試
linux上裝好hadoop之後,可以等陸到linux上通過hadoop的shell命令查看hadoop的 hdfs文件系統,執行寫好的mapreduce程序,但是這樣會很不方便,我們通常 的做法是在windows下開發程序,調試成功之後,再發布到linux上執行,這一部分就是來分享一下如何配置windows下的eclipse,可以鏈接到linux下的hadoop。
接下來就先說說第一部分的內容:
hadoop安裝有三種模式:單機模式,僞分佈式,完全分佈式。
1、單機模式: 沒意義,pass掉,不討論。
2、 僞分佈式: 就是在一臺機器上模擬namenode、datanode、jobtracker、tasktracker、secondaryname。每一個存在的形式是一個java進程。
3、完全分佈式:就是一個hadoop集羣,有n臺機器組成,一般組織方式是:一臺機器作爲master,上面 運行 namenode和jobtracker,另外的機器作爲slave,上面運行datanode和tasktracker,至於secondaryname,可以運行在master上,也可以運行在另外一臺機器上。secondaryname是namenode的一個備份裏面同樣保存了名字空間,和文件到文件塊的map關係。建議運行在另外一臺機器上,這樣master死掉之後,還可以通過secondaryname所在的機器找回名字空間,和文件到文件塊得map關係數據,恢復namenode。
這裏條件有限,就只能實現僞分佈式,就是在虛擬機上裝一個linux。其實也可以在虛擬機上裝n個linux,來實現完全分佈式,但是我怕我的小本本,吃不消。就只能裝僞分佈式了。
首先確保windows下已經安裝了虛擬機,並在虛擬機上安裝了linux,且能和windows通信了(在windows的cmd裏ping linux的ip能ping通說明可以通信了,ask:怎麼知道linux的ip?,answer:進入linux終端,ifconfig即可看到)筆者window上已經安裝了虛擬機並在虛擬機上裝了linux系統,裝linux的時候會有一個root用戶,接下來我們就全部用這個root用戶來操作,網上好多資料說新建一個用戶比如hadoop,來安裝hadoop,這裏爲了方便,就用root(其實是偷懶,不想弄得複雜,哇咔咔,(*^__^*) 嘻嘻……)。
安裝hadoop步驟
1、實現linux的ssh無密碼驗證配置.
2、在linux下安裝jdk,並配好環境變量
3、修改linux的機器名,並配置 /etc/hosts
4、在windows下下載hadoop 0.20.0,並修改hadoop-env.sh,core-site.xml,hdfs-site.xml,
mapred-site.xml,masters,slaves文件的配置
5、把修改好的hadoop整個文件夾傳到linux下
6、把hadoop的bin加入到環境變量
7、格式化hadoop,啓動hadoop
8、驗證是否啓動,並執行wordcount
這個順序並不是一個寫死的順序,就得按照這個來,如果你知道原理,可以打亂順序來操作,比如1、2、3,先那個後那個,都沒問題,但是有些步驟還是得依靠一些操作完成了才能進行,新手建議按照順序來。前輩看看交流交流經驗即可。(*^__^*) 嘻嘻……
一、實現linux的ssh無密碼驗證配置
ask:爲什麼要配置ssh無密碼驗證
answer:Hadoop需要使用SSH協議,namenode將使用SSH協議啓動namenode和datanode進程,(datanode向namenode傳遞心跳信息可能也是使用SSH協議,這是我認爲的,還沒有做深入瞭解)。許多教程上介紹Hadoop集羣配置時只說明了namenode上SSH無密碼登錄所有datanode,我在配置時發現必須使datanode上也能SSH無密碼登錄到namenode,Hadoop集羣才能正常啓動(也許這不是必須的,只是我的一個失誤,但是這樣能夠正常啓動Hadoop集羣)。上述藍色字體,是我粘的某個前輩的話,大概意思是,namenode 和datanode之間發命令是靠ssh來發的,發命令肯定是在運行的時候發,發的時候肯定不希望發一次就彈出個框說:有一臺機器連接我,讓他連嗎。所以就要求後臺namenode和datanode無障礙的進行通信,這個無障礙怎麼實現呢?,就是配置ssh無密碼驗證.上述中前輩有個顧慮,說實現了namenode到datanode無障礙鏈接到,那還用實現datanode和namenode的無障礙連接嗎?,這個我就不考慮了,我這裏是僞分佈的,就一臺機器,namenode和datanode都在一個機器上,能實現自己連自己就行了。 不是自己的問題就不去傷腦筋了,哇咔咔~~,讀者如果弄完全分佈式的時候,碰到這個問題,可以自己試試,不行,也就實現datanode到namenode的無障礙的通信,試試又累不死~~~。
ask:實現無密碼驗證就能無障礙連接,這其中原理是神馬捏?
answer:以namenode到datanode爲例子:Namenode作爲客戶端,要實現無密碼公鑰認證,連接到服務端datanode上時,需要在namenode上生成一個密鑰對,包括一個公鑰和一個私鑰,而後將公鑰複製到datanode上。當namenode通過ssh連接datanode時,datanode就會生成一個隨機數並用namenode的公鑰對隨機數進行加密,併發送給namenode。namenode收到加密數之後再用私鑰進行解密,並將解密數回傳給datanode,datanode確認解密數無誤之後就允許namenode進行連接了。這就是一個公鑰認證過程,其間不需要用戶手工輸入密碼。重要過程是將客戶端namenode公鑰複製到datanode上。這也是我粘的某個前輩的話,啥也不說了,前輩說的很清楚,就是這麼回事。
知道why了,現在就開始how吧
我這裏就一臺機器,所以操作很簡單
在linux命令行裏輸入:ssh-keygen -t rsa,然後一路回車。
root@hadoopName-desktop:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/zhangtao/.ssh/id_rsa): //密鑰保存位置,直接回車保持默認;
Created directory '/home/zhangtao/.ssh'.
Enter passphrase (empty for no passphrase): //設置密鑰的密碼,空密碼直接回車即可;
Enter same passphrase again: //確認上一步設置的密碼。
然後進入 /root/.ssh/下面,會看到兩個文件 id_rsa.pub,id_rsa,
然後執行 cp id_rsa.pub authorized_keys
然後 ssh localhost 驗證是否成功,第一次要你輸入yes,以後就不需要了。
二、安裝jdk,並配置環境變量
先在linux下面建一個目錄用來安裝jdk,我建的目錄是 /usr/program,就是以後jdk安裝到這個目錄下面。
先去下載一個linux下面的jdk版本,我的是jdk-6u6-linux-i586.bin, 也有-rpm.bin 結尾的,這種結尾的安裝不如直接.bin的簡單,這個怎麼下,就不說了,網上一大堆的,下載1.6包括1.6以上的哦~~,然後用工具傳到linux的 /usr/program這個目錄下,就是剛纔我新建的那個,上傳工具好多,ftp也行,ssh 客戶端也行,這個不多說,繼續~~。
登錄到linux下,進入 /usr/program 目錄下,發現多了一個文件,就是jdk-6u6-linux-i586.bin,
然後開始安裝。
1、執行 chmod +x jdk-6u6-linux-i586.bin,(這是因爲這個文件傳過來不是可執行的文件,要把他變成可執行文件)。
2、執行 ./jdk-6u6-linux-i586.bin,(1、2步驟都是在 /usr/program 目錄下執行的,2步驟,一路回車,遇到yes/no? 全部yes,最後會done,安裝成功).
3、執行 ls,會發現/usr/program 這個目錄下有個文件,一個是jdk-6u6-linux-i586.bin就是我們上傳上來的,另一個就是dk1.6.0_06,就是jdk的安裝根目錄.
開始配置環境變量
1、執行 cd /etc, 進入/etc 目錄下。
2、執行 vi profile, 修改profile文件
在裏面加入以下四行
- #set java environment
- export JAVA_HOME=/usr/program/jdk1.6.0_06
- export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
- export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
#set java environment
export JAVA_HOME=/usr/program/jdk1.6.0_06
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
3、執行 chmod +x profile ,把profile變成可執行文件
4、執行 source profile,把profile裏的內容執行生效
5、執行,java、javac、java -version 查看是否安裝成功.
三、修改linux機器名
先說說怎麼查看linux下的機器名
在命令行裏輸入hostname回車,展現的即當前linux系統的機器名如下
[root@hadoopName ~]# hostname
hadoopName
[root@hadoopName ~]#
讀者也看到了,命令行的前綴 [root@hadoopName ~], @符號後面的就是機器名,前面的是當前用戶名
下面說說怎麼修改redhat linux下的機器名,下面的方法只適合修改redhat的,別的版本改機器名不是這樣的
1、執行 cd /etc/sysconfig,進入/etc/sysconfig 目錄下
2、執行 vi network,修改network文件,
NETWORKING=yes
HOSTNAME=hadoopName
四、在windows下下載hadoop 0.20.0,並修改hadoop-env.sh,core-site.xml,hdfs-site.xml,
mapred-site.xml,masters,slaves文件的配置
下面要做最重要的操作,下載hadoop,並修改配置文件
下載hadoop 0.20.0 版本 http://apache.etoak.com//hadoop/core/
下載後的文件是hadoop-0.20.2.tar.gz,然後解壓出來
解壓出來後的文件結構是這樣的,進入conf目錄裏面,
修改hadoop-env.sh文件,加入如下一行
- export JAVA_HOME=/usr/program/jdk1.6.0_06
export JAVA_HOME=/usr/program/jdk1.6.0_06
其實hadoop-env.sh裏面有這一行,默認是被註釋的,你只需要把註釋去掉,並且把JAVA_HOME 改成你的java安裝目錄即可。
需要說一下,在0.20.2版本之前,conf裏面有一個 hadoop-site.xml文件,在0.20.0版本里面 conf下沒有這個hadoop-site.xml文件,取而代之的是三個文件,core-site.xml,hdfs-site.xml,mapred.xml。下面要修改這三個文件
修改core-site.xml
默認的core-site.xml是如下這樣的
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <!-- Put site-specific property overrides in this file. -->
- <configuration>
- </configuration>
現在要改成如下
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <!-- Put site-specific property overrides in this file. -->
- <configuration>
- <property>
- <name>hadoop.tmp.dir</name>
- <value>/usr/local/hadoop/hadooptmp</value>
- <description>A base for other temporary directories.</description>
- </property>
- <property>
- <name>fs.default.name</name>
- <value>hdfs://192.168.133.128:9000</value>
- <description>The name of the default file system. A URI whose
- scheme and authority determine the FileSystem implementation. The
- uri's scheme determines the config property (fs.SCHEME.impl) naming
- the FileSystem implementation class. The uri's authority is used to
- determine the host, port, etc. for a filesystem.</description>
- </property>
- </configuration>
修改hdfs-site.xml
默認的hdfs-site.xml是如下這樣的
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <!-- Put site-specific property overrides in this file. -->
- <configuration>
- </configuration>
要改成如下這樣的
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <!-- Put site-specific property overrides in this file. -->
- <configuration>
- <property>
- <name>dfs.replication</name>
- <value>1</value>
- <description>Default block replication.
- The actual number of replications can be specified when the file is created.
- The default is used if replication is not specified in create time.
- </description>
- </property>
- </configuration>
修改mapred-site.xml
默認的mapred-site.xml是如下這樣的
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <!-- Put site-specific property overrides in this file. -->
- <configuration>
- </configuration>
要改成如下這樣的
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <!-- Put site-specific property overrides in this file. -->
- <configuration>
- <property>
- <name>mapred.job.tracker</name>
- <value>192.168.133.128:9001</value>
- <description>The host and port that the MapReduce job tracker runs
- at. If "local", then jobs are run in-process as a single map
- and reduce task.
- </description>
- </property>
- </configuration><SPAN style="FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; COLOR: #000000; FONT-SIZE: 12px">
- </SPAN>
修改完這三個文件了,就一些注意的要點說一下
1、其實core-site.xml 對應有一個core-default.xml, hdfs-site.xml對應有一個hdfs-default.xml,
mapred-site.xml對應有一個mapred-default.xml。這三個defalult文件裏面都有一些默認配置,現在我們修改這三個site文件,目的就覆蓋default裏面的一些配置,
2、hadoop分佈式文件系統的兩個重要的目錄結構,一個是namenode上名字空間的存放地方,一個是datanode數據塊的存放地方,還有一些其他的文件存放地方,這些存放地方都是基於hadoop.tmp.dir目錄的,比如namenode的名字空間存放地方就是 ${hadoop.tmp.dir}/dfs/name, datanode數據塊的存放地方就是 ${hadoop.tmp.dir}/dfs/data,所以設置好hadoop.tmp.dir目錄後,其他的重要目錄都是在這個目錄下面,這是一個根目錄。我設置的是 /usr/local/hadoop/hadooptmp,當然這個目錄必須是存在的。
3、fs.default.name,這個是設置namenode位於哪個機器上,端口號是什麼hdfs://192.168.133.128:9000,格式一定要這樣寫,網上很多資料說ip地址寫localhost也行,筆者建議最好寫ip,因爲後期講到windows下 eclipse連接hadoop 的時候,如果寫localhost,就會連接不到。
4、mapred.job.tracker,這個是設置jobtracker位於哪個機器上,端口號是什麼,192.168.133.128:9001,格式和上一個不一樣,這個也必須這樣寫,同樣localhost和ip的分別和上述一樣
5、dfs.replication,這個是設置數據塊的複製次數,默認是3,因爲筆者這裏就一臺機器,所以只能存在一份,就改成了1
然後修改 masters和slaves文件
master文件裏就把集羣中的namenode所在的機器ip,這裏就寫 192.168.133.128, 不要寫localhost,寫了localhost,windows 下eclipse 連接不到hadoop
slaves文件裏就把集羣中所有的nodedata所在的機器ip,這裏就寫192.168.133.128,因爲這裏是單機,同樣最好別寫localhost
五、把修改好的hadoop整個文件夾傳到linux下
上述文件修改好之後,把haoop整個目錄copy草linux下,記得建個目錄放這個,我建的目錄是 /usr/local/hadoop,把hadoop的整個目錄copy到這個下面,然後就是這樣的形式
[root@hadoopName hadoop]# cd /usr/local/hadoop
[root@hadoopName hadoop]# ls
hadoop-0.20.2 hadooptmp
六、把hadoop的bin加入到環境變量
把hadoop的執行命令加到環境變量裏,這樣就能直接在命令行裏執行hadoop的命令了
操作跟把java的bin加入環境變量一樣
1、執行 cd /etc, 進入/etc 目錄下。
2、執行 vi profile, 修改profile文件
在裏面加入以下四行
- #set java environment
- export JAVA_HOME=/usr/program/jdk1.6.0_06
- export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
- export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
#set java environment
export JAVA_HOME=/usr/program/jdk1.6.0_06
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
3、執行 chmod +x profile ,把profile變成可執行文件
4、執行 source profile,把profile裏的內容執行生效
7、格式化hadoop,啓動hadoop
格式化hadoop
在命令行裏執行,hadoop namenode -format,
筆者在格式化的時候出現了一個錯誤 Invalid byte 2 of 2-byte UTF-8 sequence,經調查,是因爲在修改那3個xml 的時候,用非utf-8 編碼保存了,所以出錯,用editplus打開從新以uft-8的形式保存,在上傳到linux上,再執行 hadoop namenode -format 就行了,執行成功之後,去/usr/local/hadoop/hadooptmp 下會自動生成dfs文件夾,進去會有name文件夾,裏面還有別的其他namenode上保存名字空間的文件
啓動hadoop
在命令行裏執行,start-all.sh,或者執行start-dfs.sh,再執行start-mapred.sh。
在命令行裏輸入 jps,如果出現一下內容,則說明啓動成功。
[root@hadoopName ~]# jps
4505 NameNode
4692 SecondaryNameNode
4756 JobTracker
4905 Jps
4854 TaskTracker
4592 DataNode
執行 hadoop fs -ls命令,查看當前hdfs分佈式文件系統的 文件目錄結構,剛執行會說no such dictionary,
你要先建一個文件夾,用命令 haoop fs -mkdir testdir ,然後再執行hadoop fs -ls,就會展示/user/root/testdir
當前用戶是root,所以hdfs的根目錄就是 /user/root ,
8、執行wordcount
hadoop安裝成功了,來執行一下自帶的例子,
執行之前要有輸入 輸出目錄,
建立輸入目錄: hadoop fs -mkdir input
在這個目錄裏放入文件:hadoop fs -put /usr/test_in/*.txt input(把本地/usr/test_in目錄裏的所有txt文件copy到 hdfs分佈式文件系統的 /user/root/input 目錄裏面,因爲當前目錄就是root 所以 直接寫input 就代表/user/root/input)
進入 /usr/local/hadoop/hadoop 0.20.0目錄下,
執行 hadoop jar hadoop-0.20.2-examples.jar wordcount input ouput
執行完畢之後,執行hadoop fs -ls output,會發現如下
[root@hadoopName hadoop-0.20.2]# hadoop fs -ls output
Found 2 items
drwxr-xr-x - root supergroup 0 2011-05-08 05:20 /user/root/output/_logs
-rw-r--r-- 1 root supergroup 1688 2011-05-08 05:21 /user/root/output/part-r-00000
一、在eclipse下安裝開發hadoop程序的插件
二、插件安裝後,配置一下連接參數
插件裝完了,就可以建一個連接了,就相當於eclipse裏配置一個 weblogic的連接
第一步 如圖所示,打開Map/Reduce Locations 視圖,在右上角有個大象的標誌點擊
第二步,在點擊大象後彈出的對話框進行進行參數的添加,如下圖
location name: 這個隨便填寫,筆者填寫的是:hadoop.
map/reduce master 這個框裏
host:就是jobtracker 所在的集羣機器,筆者這裏是單機僞分佈式,jobtracker就在這個機器上,所以填上這個機器的ip
port:就是jobtracker 的port,這裏寫的是9001
這兩個參數就是 mapred-site.xml裏面mapred.job.tracker裏面的ip和port
DFS master這個框裏
host:就是namenode所在的集羣機器,筆者這裏是單機僞分佈式,namenode就在這個機器上,所以填上這個機器的ip。
port:就是namenode的port,這裏寫9000
這兩個參數就是 core-site.xml裏fs.default.name裏面的ip和port(use M/R master host,這個複選框如果選上,就默認和map/reduce master 這個框裏的 host一樣,如果不選擇,就可以自己定義輸入,這裏jobtracker 和namenode在一個機器上,所以是一樣的,就勾選上)
username:這個是連接hadoop的用戶名,因爲筆者是在linux中用root用戶安裝的hadoop,而且沒建立其他的用戶,所以就用root。
下面的不用填寫。
然後點擊 finish按鈕,此時,這個視圖中就有多了一條記錄,
第三步,重啓eclipse,然後重啓完畢之後,重新編輯剛纔建立的那個連接記錄,如圖,第二步裏面我們是填寫的General,tab頁,現在我們編輯advance parameters tab頁。
讀者可能問,爲什麼不在第二步裏直接把這個tab頁 也編輯了,這是因爲,新建連接的時候,這個advance paramters tab頁面的一些屬性顯示不出來,顯示不出來也就沒法設置,(這個有點 不好哇~~,應該顯示出來,免得又重啓一次,小小鄙視一下~ 哇咔咔~),必須重啓一下eclipse 再進來編輯才能看到。
這裏大部門屬性都已經自動填寫上了,讀者可以看到,這裏其實就是把core-defaulte.xml,hdfs-defaulte.xml,mapred-defaulte.xml裏面的一些配置屬性展示在這,因爲我們安裝hadoop的時候,還在site系列配置文件裏有改動,所以這裏也要弄成一樣的設置。主要關注的有以下屬性
fs.defualt.name:這個在General tab頁已經設置了。
mapred.job.tracker:這個在General tab頁也設置了。
dfs.replication:這個這裏默認是3,因爲我們再hdfs-site.xml裏面設置成了1,所以這裏也要設置成1
hadoop.tmp.dir:這個默認是/tmp/hadoop-{user.name},因爲我們在ore-defaulte.xml 裏hadoop.tmp.dir設置的是/usr/local/hadoop/hadooptmp,所以這裏我們也改成/usr/local/hadoop/hadooptmp,其他基於這個目錄屬性也會自動改
hadoop.job.ugi:剛纔說看不見的那個,就是這個屬性,這裏要填寫:root,Tardis,逗號前面的是連接的hadoop的用戶,逗號後面就寫死Tardis。
然後點擊finish,然後就連接上了,連接上的標誌如圖:
DFS Locations下面會有一隻大象,下面會有一個文件夾(2) 這個就是 hdfs的根目錄,這裏就是展示的分佈式文件系統的目錄結構。
三、寫一個wordcount的程序,在eclipse裏執行
在這個eclipse裏建一個map/reduce 工程,如圖
叫exam,然後在這個工程下面建個java類如下
第一個,MyMap.java
- package org;
- import java.io.IOException;
- import java.util.StringTokenizer;
- import org.apache.hadoop.io.IntWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapreduce.Mapper;
- public class MyMap extends Mapper<Object, Text, Text, IntWritable> {
- private final static IntWritable one = new IntWritable(1);
- private Text word;
- public void map(Object key, Text value, Context context)
- throws IOException, InterruptedException {
- String line = value.toString();
- StringTokenizer tokenizer = new StringTokenizer(line);
- while (tokenizer.hasMoreTokens()) {
- word = new Text();
- word.set(tokenizer.nextToken());
- context.write(word, one);
- }
- }
- }
package org;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class MyMap extends Mapper<Object, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text word;
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
StringTokenizer tokenizer = new StringTokenizer(line);
while (tokenizer.hasMoreTokens()) {
word = new Text();
word.set(tokenizer.nextToken());
context.write(word, one);
}
}
}
第二個,MyReduce.java
- package org;
- import java.io.IOException;
- import org.apache.hadoop.io.IntWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapreduce.Reducer;
- public class MyReduce extends
- Reducer<Text, IntWritable, Text, IntWritable> {
- 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));
- }
- }
package org;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class MyReduce extends
Reducer<Text, IntWritable, Text, IntWritable> {
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));
}
}
第三個,MyDriver.java
- package org;
- import org.apache.hadoop.conf.Configuration;
- 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.input.TextInputFormat;
- import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
- import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
- public class MyDriver {
- public static void main(String[] args) throws Exception,InterruptedException {
- Configuration conf=new Configuration();
- Job job=new Job(conf,"Hello Hadoop");
- job.setJarByClass(MyDriver.class);
- job.setMapOutputKeyClass(Text.class);
- job.setMapOutputValueClass(IntWritable.class);
- job.setOutputKeyClass(Text.class);
- job.setOutputValueClass(IntWritable.class);
- job.setMapperClass(MyMap.class);
- job.setCombinerClass(MyReduce.class);
- job.setReducerClass(MyReduce.class);
- job.setInputFormatClass(TextInputFormat.class);
- job.setOutputFormatClass(TextOutputFormat.class);
- FileInputFormat.setInputPaths(job, new Path(args[0]));
- FileOutputFormat.setOutputPath(job, new Path(args[1]));
- // JobClient.runJob(conf);
- job.waitForCompletion(true);
- }
- }
package org;
import org.apache.hadoop.conf.Configuration;
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.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
public class MyDriver {
public static void main(String[] args) throws Exception,InterruptedException {
Configuration conf=new Configuration();
Job job=new Job(conf,"Hello Hadoop");
job.setJarByClass(MyDriver.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setMapperClass(MyMap.class);
job.setCombinerClass(MyReduce.class);
job.setReducerClass(MyReduce.class);
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// JobClient.runJob(conf);
job.waitForCompletion(true);
}
}
這三個類都是基於最新的 hadoop0.20.0的,
注意了,這一步非常關鍵,筆者折騰了半天才想明白,是在windows下的一些設置,進入C:/Windows/System32/drivers/etc 目錄,打開 hosts文件 加入:192.168.133.128 hadoopName
ip是我linux的機器ip,hadoopName是linux的機器名,這個一定要加,不然,會出錯,這裏其實就是把master的ip和機器名加上了
然後設置MyDriver類的 執行參數,也就是輸入,輸出參數,和在linux下的一樣,要指定輸入的文件夾,和輸出的文件夾
如圖:
input 就是文件存放路徑,outchen就是mapReduce 之後處理的數據 輸出文件夾
然後run on hadoop 如圖
控制檯打印如下信息:
- 11/05/14 19:08:07 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively
- 11/05/14 19:08:08 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
- 11/05/14 19:08:08 INFO input.FileInputFormat: Total input paths to process : 4
- 11/05/14 19:08:09 INFO mapred.JobClient: Running job: job_201105140203_0002
- 11/05/14 19:08:10 INFO mapred.JobClient: map 0% reduce 0%
- 11/05/14 19:08:35 INFO mapred.JobClient: map 50% reduce 0%
- 11/05/14 19:08:41 INFO mapred.JobClient: map 100% reduce 0%
- 11/05/14 19:08:53 INFO mapred.JobClient: map 100% reduce 100%
- 11/05/14 19:08:55 INFO mapred.JobClient: Job complete: job_201105140203_0002
- 11/05/14 19:08:55 INFO mapred.JobClient: Counters: 17
- 11/05/14 19:08:55 INFO mapred.JobClient: Job Counters
- 11/05/14 19:08:55 INFO mapred.JobClient: Launched reduce tasks=1
- 11/05/14 19:08:55 INFO mapred.JobClient: Launched map tasks=4
- 11/05/14 19:08:55 INFO mapred.JobClient: Data-local map tasks=4
- 11/05/14 19:08:55 INFO mapred.JobClient: FileSystemCounters
- 11/05/14 19:08:55 INFO mapred.JobClient: FILE_BYTES_READ=2557
- 11/05/14 19:08:55 INFO mapred.JobClient: HDFS_BYTES_READ=3361
- 11/05/14 19:08:55 INFO mapred.JobClient: FILE_BYTES_WRITTEN=5260
- 11/05/14 19:08:55 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=1688
- 11/05/14 19:08:55 INFO mapred.JobClient: Map-Reduce Framework
- 11/05/14 19:08:55 INFO mapred.JobClient: Reduce input groups=192
- 11/05/14 19:08:55 INFO mapred.JobClient: Combine output records=202
- 11/05/14 19:08:55 INFO mapred.JobClient: Map input records=43
- 11/05/14 19:08:55 INFO mapred.JobClient: Reduce shuffle bytes=2575
- 11/05/14 19:08:55 INFO mapred.JobClient: Reduce output records=192
- 11/05/14 19:08:55 INFO mapred.JobClient: Spilled Records=404
- 11/05/14 19:08:55 INFO mapred.JobClient: Map output bytes=5070
- 11/05/14 19:08:55 INFO mapred.JobClient: Combine input records=488
- 11/05/14 19:08:55 INFO mapred.JobClient: Map output records=488
- 11/05/14 19:08:55 INFO mapred.JobClient: Reduce input records=202
11/05/14 19:08:07 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively
11/05/14 19:08:08 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
11/05/14 19:08:08 INFO input.FileInputFormat: Total input paths to process : 4
11/05/14 19:08:09 INFO mapred.JobClient: Running job: job_201105140203_0002
11/05/14 19:08:10 INFO mapred.JobClient: map 0% reduce 0%
11/05/14 19:08:35 INFO mapred.JobClient: map 50% reduce 0%
11/05/14 19:08:41 INFO mapred.JobClient: map 100% reduce 0%
11/05/14 19:08:53 INFO mapred.JobClient: map 100% reduce 100%
11/05/14 19:08:55 INFO mapred.JobClient: Job complete: job_201105140203_0002
11/05/14 19:08:55 INFO mapred.JobClient: Counters: 17
11/05/14 19:08:55 INFO mapred.JobClient: Job Counters
11/05/14 19:08:55 INFO mapred.JobClient: Launched reduce tasks=1
11/05/14 19:08:55 INFO mapred.JobClient: Launched map tasks=4
11/05/14 19:08:55 INFO mapred.JobClient: Data-local map tasks=4
11/05/14 19:08:55 INFO mapred.JobClient: FileSystemCounters
11/05/14 19:08:55 INFO mapred.JobClient: FILE_BYTES_READ=2557
11/05/14 19:08:55 INFO mapred.JobClient: HDFS_BYTES_READ=3361
11/05/14 19:08:55 INFO mapred.JobClient: FILE_BYTES_WRITTEN=5260
11/05/14 19:08:55 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=1688
11/05/14 19:08:55 INFO mapred.JobClient: Map-Reduce Framework
11/05/14 19:08:55 INFO mapred.JobClient: Reduce input groups=192
11/05/14 19:08:55 INFO mapred.JobClient: Combine output records=202
11/05/14 19:08:55 INFO mapred.JobClient: Map input records=43
11/05/14 19:08:55 INFO mapred.JobClient: Reduce shuffle bytes=2575
11/05/14 19:08:55 INFO mapred.JobClient: Reduce output records=192
11/05/14 19:08:55 INFO mapred.JobClient: Spilled Records=404
11/05/14 19:08:55 INFO mapred.JobClient: Map output bytes=5070
11/05/14 19:08:55 INFO mapred.JobClient: Combine input records=488
11/05/14 19:08:55 INFO mapred.JobClient: Map output records=488
11/05/14 19:08:55 INFO mapred.JobClient: Reduce input records=202
說明執行成功,
去看一下,會多一個outchen目錄,裏面放着執行的結果,和在普通的linux上執行的一樣。
四、聊聊注意事項
1、在安裝hadoop的時候 core-site.xml 和 mapred.site.xml裏面的 fs.defulate.name,和 mapred.job.tracker那個一定要寫ip地址,不要寫localhost,雖然是單機,也不能寫localhost,要寫本機的ip,不然eclipse連接不到。
2、masters 和 slaves文件裏也要寫ip,不要寫localhost
五、一些錯誤分析
1、出現如圖所示
- 11/05/08 21:41:37 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively
- job new ֮ǰ-----------------------------------
- 11/05/08 21:41:40 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 0 time(s).
- 11/05/08 21:41:42 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 1 time(s).
- 11/05/08 21:41:44 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 2 time(s).
- 11/05/08 21:41:46 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 3 time(s).
- 11/05/08 21:41:48 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 4 time(s).
- 11/05/08 21:41:50 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 5 time(s).
- 11/05/08 21:41:52 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 6 time(s).
- 11/05/08 21:41:54 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 7 time(s).
- 11/05/08 21:41:56 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 8 time(s).
- 11/05/08 21:41:58 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 9 time(s).
- Exception in thread "main" java.net.ConnectException: Call to /192.168.133.128:9001 failed on connection exception: java.net.ConnectException: Connection refused: no further information
- at org.apache.hadoop.ipc.Client.wrapException(Client.java:767)
- at org.apache.hadoop.ipc.Client.call(Client.java:743)
- at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220)
- at org.apache.hadoop.mapred.$Proxy0.getProtocolVersion(Unknown Source)
- at org.apache.hadoop.ipc.RPC.getProxy(RPC.java:359)
- at org.apache.hadoop.mapred.JobClient.createRPCProxy(JobClient.java:429)
- at org.apache.hadoop.mapred.JobClient.init(JobClient.java:423)
- at org.apache.hadoop.mapred.JobClient.<init>(JobClient.java:410)
- at org.apache.hadoop.mapreduce.Job.<init>(Job.java:50)
- at org.apache.hadoop.mapreduce.Job.<init>(Job.java:54)
- at org.apache.hadoop.examples.WordCount.main(WordCount.java:59)
- Caused by: java.net.ConnectException: Connection refused: no further information
- at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
- at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:567)
- at org.apache.hadoop.net.SocketIOWithTimeout.connect(SocketIOWithTimeout.java:206)
- at org.apache.hadoop.net.NetUtils.connect(NetUtils.java:404)
- at org.apache.hadoop.ipc.Client$Connection.setupIOstreams(Client.java:304)
- at org.apache.hadoop.ipc.Client$Connection.access$1700(Client.java:176)
- at org.apache.hadoop.ipc.Client.getConnection(Client.java:860)
- at org.apache.hadoop.ipc.Client.call(Client.java:720)
- ... 9 more
11/05/08 21:41:37 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively
job new ֮ǰ-----------------------------------
11/05/08 21:41:40 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 0 time(s).
11/05/08 21:41:42 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 1 time(s).
11/05/08 21:41:44 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 2 time(s).
11/05/08 21:41:46 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 3 time(s).
11/05/08 21:41:48 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 4 time(s).
11/05/08 21:41:50 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 5 time(s).
11/05/08 21:41:52 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 6 time(s).
11/05/08 21:41:54 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 7 time(s).
11/05/08 21:41:56 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 8 time(s).
11/05/08 21:41:58 INFO ipc.Client: Retrying connect to server: /192.168.133.128:9001. Already tried 9 time(s).
Exception in thread "main" java.net.ConnectException: Call to /192.168.133.128:9001 failed on connection exception: java.net.ConnectException: Connection refused: no further information
at org.apache.hadoop.ipc.Client.wrapException(Client.java:767)
at org.apache.hadoop.ipc.Client.call(Client.java:743)
at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220)
at org.apache.hadoop.mapred.$Proxy0.getProtocolVersion(Unknown Source)
at org.apache.hadoop.ipc.RPC.getProxy(RPC.java:359)
at org.apache.hadoop.mapred.JobClient.createRPCProxy(JobClient.java:429)
at org.apache.hadoop.mapred.JobClient.init(JobClient.java:423)
at org.apache.hadoop.mapred.JobClient.<init>(JobClient.java:410)
at org.apache.hadoop.mapreduce.Job.<init>(Job.java:50)
at org.apache.hadoop.mapreduce.Job.<init>(Job.java:54)
at org.apache.hadoop.examples.WordCount.main(WordCount.java:59)
Caused by: java.net.ConnectException: Connection refused: no further information
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:567)
at org.apache.hadoop.net.SocketIOWithTimeout.connect(SocketIOWithTimeout.java:206)
at org.apache.hadoop.net.NetUtils.connect(NetUtils.java:404)
at org.apache.hadoop.ipc.Client$Connection.setupIOstreams(Client.java:304)
at org.apache.hadoop.ipc.Client$Connection.access$1700(Client.java:176)
at org.apache.hadoop.ipc.Client.getConnection(Client.java:860)
at org.apache.hadoop.ipc.Client.call(Client.java:720)
... 9 more
- 11/05/14 20:08:26 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively
- 11/05/14 20:08:46 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
- Exception in thread "main" java.net.UnknownHostException: unknown host: hadoopName
- at org.apache.hadoop.ipc.Client$Connection.<init>(Client.java:195)
- at org.apache.hadoop.ipc.Client.getConnection(Client.java:850)
- at org.apache.hadoop.ipc.Client.call(Client.java:720)
- at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220)
- at $Proxy1.getProtocolVersion(Unknown Source)
- at org.apache.hadoop.ipc.RPC.getProxy(RPC.java:359)
- at org.apache.hadoop.hdfs.DFSClient.createRPCNamenode(DFSClient.java:106)
- at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:207)
- at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:170)
- at org.apache.hadoop.hdfs.DistributedFileSystem.initialize(DistributedFileSystem.java:82)
- at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:1378)
- at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:66)
- at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:1390)
- at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:196)
- at org.apache.hadoop.fs.Path.getFileSystem(Path.java:175)
- at org.apache.hadoop.mapred.JobClient.getFs(JobClient.java:463)
- at org.apache.hadoop.mapred.JobClient.configureCommandLineOptions(JobClient.java:567)
- at org.apache.hadoop.mapred.JobClient.submitJobInternal(JobClient.java:761)
- at org.apache.hadoop.mapreduce.Job.submit(Job.java:432)
- at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:447)
- at org.MyDriver.main(MyDriver.java:40)
11/05/14 20:08:26 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively
11/05/14 20:08:46 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
Exception in thread "main" java.net.UnknownHostException: unknown host: hadoopName
at org.apache.hadoop.ipc.Client$Connection.<init>(Client.java:195)
at org.apache.hadoop.ipc.Client.getConnection(Client.java:850)
at org.apache.hadoop.ipc.Client.call(Client.java:720)
at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220)
at $Proxy1.getProtocolVersion(Unknown Source)
at org.apache.hadoop.ipc.RPC.getProxy(RPC.java:359)
at org.apache.hadoop.hdfs.DFSClient.createRPCNamenode(DFSClient.java:106)
at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:207)
at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:170)
at org.apache.hadoop.hdfs.DistributedFileSystem.initialize(DistributedFileSystem.java:82)
at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:1378)
at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:66)
at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:1390)
at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:196)
at org.apache.hadoop.fs.Path.getFileSystem(Path.java:175)
at org.apache.hadoop.mapred.JobClient.getFs(JobClient.java:463)
at org.apache.hadoop.mapred.JobClient.configureCommandLineOptions(JobClient.java:567)
at org.apache.hadoop.mapred.JobClient.submitJobInternal(JobClient.java:761)
at org.apache.hadoop.mapreduce.Job.submit(Job.java:432)
at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:447)
at org.MyDriver.main(MyDriver.java:40)