Hadoop偽分布配置與基于Eclipse開(kāi)發(fā)環(huán)境搭建
1、開(kāi)發(fā)配置環(huán)境:
開(kāi)發(fā)環(huán)境:Win7(64bit)+Eclipse(kepler service release 2)
配置環(huán)境:Ubuntu Server 14.04.1 LTS(64-bit only)
輔助工具:WinSCP + Putty
Hadoop版本:2.5.0
Hadoop的Eclipse開(kāi)發(fā)插件(2.x版本適用):http://pan.baidu.com/s/1eQy49sm
服務(wù)器端JDK版本:OpenJDK7.0
以上所有工具請(qǐng)自行下載安裝。
2、Hadoop服務(wù)端配置(Master節(jié)點(diǎn))
最近一直在摸索Hadoop2的配置,因?yàn)镠adoop2對(duì)原有的一些框架API做了調(diào)整,但也還是兼容舊版本的(包括配置)。像我這種就喜歡用新的東西的人,當(dāng)然要嘗一下鮮了,現(xiàn)在網(wǎng)上比較少新版本的配置教程,那么下面我就來(lái)分享一下我自己的實(shí)戰(zhàn)經(jīng)驗(yàn),如有不正確的地歡迎指正:)。
假設(shè)我們已經(jīng)成功地安裝了Ubuntu Server、OpenJDK、SSH,如果還沒(méi)有安裝的話請(qǐng)先安裝,自己網(wǎng)上找一下教程,這里我就說(shuō)一下SSH的無(wú)口令登陸設(shè)置。首先通過(guò)
- $ ssh localhost
測(cè)試一下自己有沒(méi)有設(shè)置好無(wú)口令登陸,如果沒(méi)有設(shè)置好,系統(tǒng)將要求你輸入密碼,通過(guò)下面的設(shè)置可以實(shí)現(xiàn)無(wú)口令登陸,具體原理請(qǐng)百度谷歌:
- $ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
- $ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
其次是Hadoop安裝(假設(shè)已經(jīng)安裝好OpenJDK以及配置好了環(huán)境變量),到Hadoop官網(wǎng)下載一個(gè)Hadoop2.5.0版本的下來(lái),好像大概有100多M的tar.gz包,下載 下來(lái)后自行解壓,我的是放在/usr/mywind下面,Hadoop主目錄完整路徑是/usr/mywind/hadoop,這個(gè)路徑根據(jù)你個(gè)人喜好放吧。
解壓完后,打開(kāi)hadoop主目錄下的etc/hadoop/hadoop-env.sh文件,在最后面加入下面內(nèi)容:
- # set to the root of your Java installation
- export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
- # Assuming your installation directory is /usr/mywind/hadoop
- export HADOOP_PREFIX=/usr/mywind/hadoop
為了方便起見(jiàn),我建設(shè)把Hadoop的bin目錄及sbin目錄也加入到環(huán)境變量中,我是直接修改了Ubuntu的/etc/environment文件,內(nèi)容如下:
- PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/jvm/java-7-openjdk-amd64/bin:/usr/mywind/hadoop/bin:/usr/mywind/hadoop/sbin"
- JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64"
- CLASSPATH=".:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"
也可以通過(guò)修改profile來(lái)完成這個(gè)設(shè)置,看個(gè)人習(xí)慣咯。假如上面的設(shè)置你都完成了,可以在命令行里面測(cè)試一下Hadoop命令,如下圖:
假如你能看到上面的結(jié)果,恭喜你,Hadoop安裝完成了。接下來(lái)我們可以進(jìn)行偽分布配置(Hadoop可以在偽分布模式下運(yùn)行單結(jié)點(diǎn))。
接下來(lái)我們要配置的文件有四個(gè),分別是/usr/mywind/hadoop/etc/hadoop目錄下的yarn-site.xml、mapred-site.xml、hdfs-site.xml、core-site.xml(注意:這個(gè)版本下默認(rèn)沒(méi)有yarn-site.xml文件,但有個(gè)yarn-site.xml.properties文件,把后綴修改成前者即可),關(guān)于yarn新特性可以參考官網(wǎng)或者這個(gè)文章http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-yarn/。
首先是core-site.xml配置HDFS地址及臨時(shí)目錄(默認(rèn)的臨時(shí)目錄在重啟后會(huì)刪除):
- <configuration>
- <property>
- <name>fs.defaultFS</name>
- <value>hdfs://192.168.8.184:9000</value>
- <description>same as fs.default.name</description>
- </property>
- <property>
- <name>hadoop.tmp.dir</name>
- <value>/usr/mywind/tmp</value>
- <description>A base for other temporary directories.</description>
- </property>
- </configuration>
然后是hdfs-site.xml配置集群數(shù)量及其他一些可選配置比如NameNode目錄、DataNode目錄等等:
- <configuration>
- <property>
- <name>dfs.namenode.name.dir</name>
- <value>/usr/mywind/name</value>
- <description>same as dfs.name.dir</description>
- </property>
- <property>
- <name>dfs.datanode.data.dir</name>
- <value>/usr/mywind/data</value>
- <description>same as dfs.data.dir</description>
- </property>
- <property>
- <name>dfs.replication</name>
- <value>1</value>
- <description>same as old frame,recommend set the value as the cluster DataNode host numbers!</description>
- </property>
- </configuration>
接著是mapred-site.xml配置啟用yarn框架:
- <configuration>
- <property>
- <name>mapreduce.framework.name</name>
- <value>yarn</value>
- </property>
- </configuration>
最后是yarn-site.xml配置NodeManager:
- <configuration>
- <!-- Site specific YARN configuration properties -->
- <property>
- <name>yarn.nodemanager.aux-services</name>
- <value>mapreduce_shuffle</value>
- </property>
- </configuration>
注意,網(wǎng)上的舊版本教程可能會(huì)把value寫(xiě)成mapreduce.shuffle,這個(gè)要特別注意一下的,至此我們所有的文件配置都已經(jīng)完成了,下面進(jìn)行HDFS文件系統(tǒng)進(jìn)行格式化:
- $ hdfs namenode -format
然后啟用NameNode及DataNode進(jìn)程:
- $ start-yarn.sh
然后創(chuàng)建hdfs文件目錄
- $ hdfs dfs -mkdir /user
- $ hdfs dfs -mkdir /user/a01513
注意,這個(gè)a01513是我在Ubuntu上的用戶名,最好保持與系統(tǒng)用戶名一致,據(jù)說(shuō)不一致會(huì)有許多權(quán)限等問(wèn)題,我之前試過(guò)改成其他名字,報(bào)錯(cuò),實(shí)在麻煩就改成跟系統(tǒng)用戶名一致吧。
然后把要測(cè)試的輸入文件放在文件系統(tǒng)中:
- $ hdfs dfs -put /usr/mywind/psa input
文件內(nèi)容是Hadoop經(jīng)典的天氣例子的數(shù)據(jù):
- 12345679867623119010123456798676231190101234567986762311901012345679867623119010123456+001212345678903456
- 12345679867623119010123456798676231190101234567986762311901012345679867623119010123456+011212345678903456
- 12345679867623119010123456798676231190101234567986762311901012345679867623119010123456+021212345678903456
- 12345679867623119010123456798676231190101234567986762311901012345679867623119010123456+003212345678903456
- 12345679867623119010123456798676231190201234567986762311901012345679867623119010123456+004212345678903456
- 12345679867623119010123456798676231190201234567986762311901012345679867623119010123456+010212345678903456
- 12345679867623119010123456798676231190201234567986762311901012345679867623119010123456+011212345678903456
- 12345679867623119010123456798676231190501234567986762311901012345679867623119010123456+041212345678903456
- 12345679867623119010123456798676231190501234567986762311901012345679867623119010123456+008212345678903456
把文件拷貝到HDFS目錄之后,我們可以通過(guò)瀏覽器查看相關(guān)的文件及一些狀態(tài):
http://192.168.8.184:50070/
這里的IP地址根據(jù)你實(shí)際的Hadoop服務(wù)器地址啦。
好吧,我們所有的Hadoop后臺(tái)服務(wù)搭建跟數(shù)據(jù)準(zhǔn)備都已經(jīng)完成了,那么我們的M/R程序也要開(kāi)始動(dòng)手寫(xiě)了,不過(guò)在寫(xiě)當(dāng)然先配置開(kāi)發(fā)環(huán)境了。
3、基于Eclipse的Hadoop2.x開(kāi)發(fā)環(huán)境配置
關(guān)于JDK及ECLIPSE的安裝我就不再介紹了,相信能玩Hadoop的人對(duì)這種配置都已經(jīng)再熟悉不過(guò)了,如果實(shí)在不懂建議到谷歌百度去搜索一下教程。假設(shè)你已經(jīng)把Hadoop的Eclipse插件下載下來(lái)了,然后解壓把jar文件放到Eclipse的plugins文件夾里面:
重啟Eclipse即可。
然后我們?cè)侔惭bHadoop到Win7下,在這不再詳細(xì)說(shuō)明,跟安裝JDK大同小異,在這個(gè)例子中我安裝到了E:\hadoop。
啟動(dòng)Eclipse,點(diǎn)擊菜單欄的【W(wǎng)indows/窗口】→【Preferences/首選項(xiàng)】→【Hadoop Map/Reduce】,把Hadoop Installation Directory設(shè)置成開(kāi)發(fā)機(jī)上的Hadoop主目錄:
點(diǎn)擊OK。
開(kāi)發(fā)環(huán)境配置完成,下面我們可以新建一個(gè)測(cè)試Hadoop項(xiàng)目,右鍵【NEW/新建】→【Others、其他】,選擇Map/Reduce Project
輸入項(xiàng)目名稱點(diǎn)擊【Finish/完成】:
創(chuàng)建完成后可以看到如下目錄:
然后在SRC下建立下面包及類:
#p#
以下是代碼內(nèi)容:
TestMapper.java
- package com.my.hadoop.mapper;
- import java.io.IOException;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.hadoop.io.IntWritable;
- import org.apache.hadoop.io.LongWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapred.MapReduceBase;
- import org.apache.hadoop.mapred.Mapper;
- import org.apache.hadoop.mapred.OutputCollector;
- import org.apache.hadoop.mapred.Reporter;
- public class TestMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
- private static final int MISSING = 9999;
- private static final Log LOG = LogFactory.getLog(TestMapper.class);
- public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output,Reporter reporter)
- throws IOException {
- String line = value.toString();
- String year = line.substring(15, 19);
- int airTemperature;
- if (line.charAt(87) == '+') { // parseInt doesn't like leading plus signs
- airTemperature = Integer.parseInt(line.substring(88, 92));
- } else {
- airTemperature = Integer.parseInt(line.substring(87, 92));
- }
- LOG.info("loki:"+airTemperature);
- String quality = line.substring(92, 93);
- LOG.info("loki2:"+quality);
- if (airTemperature != MISSING && quality.matches("[012459]")) {
- LOG.info("loki3:"+quality);
- output.collect(new Text(year), new IntWritable(airTemperature));
- }
- }
- }
TestReducer.java
- package com.my.hadoop.reducer;
- import java.io.IOException;
- import java.util.Iterator;
- import org.apache.hadoop.io.IntWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapred.MapReduceBase;
- import org.apache.hadoop.mapred.OutputCollector;
- import org.apache.hadoop.mapred.Reporter;
- import org.apache.hadoop.mapred.Reducer;
- public class TestReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
- @Override
- public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output,Reporter reporter)
- throws IOException{
- int maxValue = Integer.MIN_VALUE;
- while (values.hasNext()) {
- maxValue = Math.max(maxValue, values.next().get());
- }
- output.collect(key, new IntWritable(maxValue));
- }
- }
TestHadoop.java
- package com.my.hadoop.test.main;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.io.IntWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapred.FileInputFormat;
- import org.apache.hadoop.mapred.FileOutputFormat;
- import org.apache.hadoop.mapred.JobClient;
- import org.apache.hadoop.mapred.JobConf;
- import com.my.hadoop.mapper.TestMapper;
- import com.my.hadoop.reducer.TestReducer;
- public class TestHadoop {
- public static void main(String[] args) throws Exception{
- if (args.length != 2) {
- System.err
- .println("Usage: MaxTemperature <input path> <output path>");
- System.exit(-1);
- }
- JobConf job = new JobConf(TestHadoop.class);
- job.setJobName("Max temperature");
- FileInputFormat.addInputPath(job, new Path(args[0]));
- FileOutputFormat.setOutputPath(job, new Path(args[1]));
- job.setMapperClass(TestMapper.class);
- job.setReducerClass(TestReducer.class);
- job.setOutputKeyClass(Text.class);
- job.setOutputValueClass(IntWritable.class);
- JobClient.runJob(job);
- }
- }
為了方便對(duì)于Hadoop的HDFS文件系統(tǒng)操作,我們可以在Eclipse下面的Map/Reduce Locations窗口與Hadoop建立連接,直接右鍵新建Hadoop連接即可:
連接配置如下:
然后點(diǎn)擊完成即可,新建完成后,我們可以在左側(cè)目錄中看到HDFS的文件系統(tǒng)目錄:
這里不僅可以顯示目錄結(jié)構(gòu),還可以對(duì)文件及目錄進(jìn)行刪除、新增等操作,非常方便。
當(dāng)上面的工作都做好之后,就可以把這個(gè)項(xiàng)目導(dǎo)出來(lái)了(導(dǎo)成jar文件放到Hadoop服務(wù)器上運(yùn)行):
點(diǎn)擊完成,然后把這個(gè)testt.jar文件上傳到Hadoop服務(wù)器(192.168.8.184)上,目錄(其實(shí)可以放到其他目錄,你自己喜歡)是:
- /usr/mywind/hadoop/share/hadoop/mapreduce
如下圖:
4、運(yùn)行Hadoop程序及查看運(yùn)行日志
當(dāng)上面的工作準(zhǔn)備好了之后,我們運(yùn)行自己寫(xiě)的Hadoop程序很簡(jiǎn)單:
- $ hadoop jar /usr/mywind/hadoop/share/hadoop/mapreduce/testt.jar com.my.hadoop.test.main.TestHadoop input output
注意這是output文件夾名稱不能重復(fù)哦,假如你執(zhí)行了一次,在HDFS文件系統(tǒng)下面會(huì)自動(dòng)生成一個(gè)output文件夾,第二次運(yùn)行時(shí),要么把output文件夾先刪除($ hdfs dfs -rmr /user/a01513/output),要么把命令中的output改成其他名稱如output1、output2等等。
如果看到以下輸出結(jié)果,證明你的運(yùn)行成功了:
- a01513@hadoop :~$ hadoop jar /usr/mywind/hadoop/share/hadoop/mapreduce/testt.jar com.my.hadoop.test.main.TestHadoop input output
- 14/09/02 11:14:03 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0 :8032
- 14/09/02 11:14:04 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0 :8032
- 14/09/02 11:14:04 WARN mapreduce.JobSubmitter: Hadoop command-line option parsin g not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this.
- 14/09/02 11:14:04 INFO mapred.FileInputFormat: Total input paths to process : 1
- 14/09/02 11:14:04 INFO mapreduce.JobSubmitter: number of splits:2
- 14/09/02 11:14:05 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_14 09386620927_0015
- 14/09/02 11:14:05 INFO impl.YarnClientImpl: Submitted application application_14 09386620927_0015
- 14/09/02 11:14:05 INFO mapreduce.Job: The url to track the job: http://hadoop:80 88/proxy/application_1409386620927_0015/
- 14/09/02 11:14:05 INFO mapreduce.Job: Running job: job_1409386620927_0015
- 14/09/02 11:14:12 INFO mapreduce.Job: Job job_1409386620927_0015 running in uber mode : false
- 14/09/02 11:14:12 INFO mapreduce.Job: map 0% reduce 0%
- 14/09/02 11:14:21 INFO mapreduce.Job: map 100% reduce 0%
- 14/09/02 11:14:28 INFO mapreduce.Job: map 100% reduce 100%
- 14/09/02 11:14:28 INFO mapreduce.Job: Job job_1409386620927_0015 completed successfully
- 14/09/02 11:14:29 INFO mapreduce.Job: Counters: 49
- File System Counters
- FILE: Number of bytes read=105
- FILE: Number of bytes written=289816
- FILE: Number of read operations=0
- FILE: Number of large read operations=0
- FILE: Number of write operations=0
- HDFS: Number of bytes read=1638
- HDFS: Number of bytes written=10
- HDFS: Number of read operations=9
- HDFS: Number of large read operations=0
- HDFS: Number of write operations=2
- Job Counters
- Launched map tasks=2
- Launched reduce tasks=1
- Data-local map tasks=2
- Total time spent by all maps in occupied slots (ms)=14817
- Total time spent by all reduces in occupied slots (ms)=4500
- Total time spent by all map tasks (ms)=14817
- Total time spent by all reduce tasks (ms)=4500
- Total vcore-seconds taken by all map tasks=14817
- Total vcore-seconds taken by all reduce tasks=4500
- Total megabyte-seconds taken by all map tasks=15172608
- Total megabyte-seconds taken by all reduce tasks=4608000
- Map-Reduce Framework
- Map input records=9
- Map output records=9
- Map output bytes=81
- Map output materialized bytes=111
- Input split bytes=208
- Combine input records=0
- Combine output records=0
- Reduce input groups=1
- Reduce shuffle bytes=111
- Reduce input records=9
- Reduce output records=1
- Spilled Records=18
- Shuffled Maps =2
- Failed Shuffles=0
- Merged Map outputs=2
- GC time elapsed (ms)=115
- CPU time spent (ms)=1990
- Physical memory (bytes) snapshot=655314944
- Virtual memory (bytes) snapshot=2480295936
- Total committed heap usage (bytes)=466616320
- Shuffle Errors
- BAD_ID=0
- CONNECTION=0
- IO_ERROR=0
- WRONG_LENGTH=0
- WRONG_MAP=0
- WRONG_REDUCE=0
- File Input Format Counters
- Bytes Read=1430
- File Output Format Counters
- Bytes Written=10
- a01513@hadoop :~$
我們可以到Eclipse查看輸出的結(jié)果:
或者用命令行查看:
- $ hdfs dfs -cat output/part-00000
假如你們發(fā)現(xiàn)運(yùn)行后結(jié)果是為空的,可能到日志目錄查找相應(yīng)的log.info輸出信息,log目錄在:/usr/mywind/hadoop/logs/userlogs 下面。
好了,不太喜歡打字,以上就是整個(gè)過(guò)程了,歡迎大家來(lái)學(xué)習(xí)指正。