Windows下開發Hadoop程式遇到的坑及解決方案
背景
過幾天工作需要用到Hadoop,於是就弄了本PDF看。看了半天也是暈暈乎乎的。乾脆直接動手,這樣還能掌握的快一點。於是我就在本地要搭建一個Hadoop的開發環境。
環境前提
1、Hadoop部署在測試伺服器上。 2、開發人員在Windows上使用eclipse進行開發。(即執行和開發環境是分開的) 3、環境引數Linux:CentOS release 6.7 (Final) x86_64
Java ,version:1.7.0_80 (x86_64)
Hadoop ,version:1.2.1
------------------------------
windows ,version:Windows 7 professional x86_64
eclipse ,version:Luna Service Release 2 (4.4.2)
------------------------------
4、其他需要使用的開源庫
Apache Ant ,version:1.9.4
開始前準備
1、千萬不要有中文路徑!!!
2、如果Windows使用者名稱是中文的,改掉它!!!變成英文的使用者名稱!!!
Linux上的Hadoop安裝
Java安裝
1、Java安裝還是相對簡單的2、首先去oracle官網下載對應的Java程式包,下載的時候需要登入,這個比較麻煩。Java下載頁面
3、下載好之後是一個tar.gz檔案,放到Linux下的某個目錄(此處我放在了/opt下)
4、執行命令,解包
cd /opt
tar xvf 剛剛下載的tar.gz的檔名
// 示例
tar xvf jdk-7u80-linux-x64.tar.gz
// 解壓出來的資料夾名稱太長,這裡我把資料夾重新命名,這一步不是必須的
mv 解壓出的檔名 新檔名
// 示例
mv jdk-7u80-linux-x64 jdk1.7.0_80
5、設定PATH環境變數
vim /etc/profile
// 增加JAVA_HOEM
export JAVA_HOME=/opt/jdk1.7.0_80
export PATH=$PATH:$JAVA_HOME/bin
6、載入當前環境變數
source /etc/profile
7、檢視是否成功
若出現Java的版本資訊等文字,證明安裝成功。java -version
Hadoop安裝
2、與Java安裝一樣,使用tar命令解壓,然後配置環境變數 3、vim /etc/profile
export HADOOP_HOME=/opt/hadoop-1.2.1
export PATH=$PATH:$HADOOP_HOME/bin
source /etc/profile
4、對hadoop進行相關的配置(hadoop資料夾下的conf,這裡我的路徑為/opt/hadoop-1.2.1)
(1)進入conf目錄,vim編輯core-site.xml,編輯如下
<?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>/hadoop</value>
</property>
<property>
<name>dfs.name.dir</name>
<value>/hadoop/name</value>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://hostname:9000</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
</configuration>
這裡我遇到了第一個坑就是hdfs://hostname:9000
這一行配置,我根據網上的教程配置自己的hostname,於是變成了這樣
hdfs://localhost:9000
幾乎網上所有的教程都是這麼寫的。但是。請最好不要這樣,因為這會再你配置eclipse時帶來無盡的麻煩。(不要問我是怎麼知道的)。我的建議是這樣
hdfs://Linux伺服器的IP地址:9000
(2)vim 編輯hadoop-env.sh找到這一行
# export JAVA_HOME=/usr/lib/j2sdk1.5-sun
將它變為
export JAVA_HOME=/opt/jdk1.7.0_80
也就是把剛剛配置的JAVA_HOME的內容複製到此
(3)vim編輯hdfs-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.data.dir</name>
<value>/hadoop/data</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
</configuration>
(4)vim編輯mapred-site.xml
<?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>Linux的IP地址:9001</value>
</property>
</configuration>
說明一下,dfs.permissions配置預設為true,由於是測試用,這裡將其關閉,避免過多的麻煩
這裡的配置是最簡單的一個配置,目的是為了能讓使用者快速開始hadoop的使用。
IP:埠號中的埠號可以進行自定義,不一定非要9000和9001,自己能區分就ok
5、進入/opt/hadoop-1.2.1/bin下
./start-all.sh
會出現讓你輸入root密碼的選項,3次。輸入就ok
之後格式化hdfs
hadoop fs -format
執行jps命令,若出現以下字樣,代表啟成功了(前邊的數字可能不太一樣)
windows下的開發環境搭建
eclipse外掛的安裝
之前一般eclipse外掛都是能在網上下載到的,這次出乎我的意料,很少有下載的,網上的教程幾乎清一色都是要自己編譯的。我偏不信。。下載了幾個。。果然不能用,有幾個能用的,但是各種出錯。最好的辦法還是自己編譯一下。
編譯很簡單的。
首先將剛剛下載的hadoop的tar.gz解壓出來,這裡我解壓到了D盤。
eclipse外掛編譯
(1)進入D:\hadoop-1.2.1\src\contrib\eclipse-plugin目錄下 (2)build.properties檔案最下邊新增2個配置,注意不要有空格eclipse.home=D:/eclipse
version=1.2.1
第一行就是你的eclipse的安裝目錄。第二個的意思就是你的hadoop的版本
(3)修改build.xml
在節點<path id="eclipse-sdk-jars">內新增一個節點
<fileset dir="../../../">
<include name="hadoop*.jar"/>
</fileset>
整個path節點就變成了這樣
<path id="eclipse-sdk-jars">
<fileset dir="${eclipse.home}/plugins/">
<include name="org.eclipse.ui*.jar"/>
<include name="org.eclipse.jdt*.jar"/>
<include name="org.eclipse.core*.jar"/>
<include name="org.eclipse.equinox*.jar"/>
<include name="org.eclipse.debug*.jar"/>
<include name="org.eclipse.osgi*.jar"/>
<include name="org.eclipse.swt*.jar"/>
<include name="org.eclipse.jface*.jar"/>
<include name="org.eclipse.team.cvs.ssh2*.jar"/>
<include name="com.jcraft.jsch*.jar"/>
</fileset>
<fileset dir="../../../">
<include name="hadoop*.jar"/>
</fileset>
</path>
在<target name="jar" depends="compile" unless="skip.contrib">節點內註釋掉2行,新增2行,最終target節點變成了這樣
<target name="jar" depends="compile" unless="skip.contrib">
<mkdir dir="${build.dir}/lib"/>
<!--
<copy file="${hadoop.root}/build/hadoop-core-${version}.jar" tofile="${build.dir}/lib/hadoop-core.jar" verbose="true"/>
<copy file="${hadoop.root}/build/ivy/lib/Hadoop/common/commons-cli-${commons-cli.version}.jar" todir="${build.dir}/lib" verbose="true"/>
-->
<copy file="${hadoop.root}/hadoop-core-${version}.jar" tofile="${build.dir}/lib/hadoop-core.jar" verbose="true"/>
<copy file="${hadoop.root}/lib/commons-cli-${commons-cli.version}.jar" todir="${build.dir}/lib" verbose="true"/>
<jar
jarfile="${build.dir}/hadoop-${name}-${version}.jar"
manifest="${root}/META-INF/MANIFEST.MF">
<fileset dir="${build.dir}" includes="classes/ lib/"/>
<fileset dir="${root}" includes="resources/ plugin.xml"/>
</jar>
</target>
之後使用windows的smd命令列工具,進入D:\hadoop-1.2.1\src\contrib\eclipse-plugin,輸入“ant”命令。等待幾分鐘就ok了(期間需要聯網)。
編譯成功後,進入D:\hadoop-1.2.1\build\contrib\eclipse-plugin目錄下,可以看到有一個hadoop-eclipse-plugin-1.2.1.jar檔案,將其複製到eclipse的安裝目錄下的plugins資料夾內,重啟eclipse即可。
eclipse外掛配置
(1)首先調出hadoop的view,右上角,開啟新的view,選擇藍色的大象,map/reduce
然後選擇windows-->preferences
選擇剛剛解壓到D盤的hadoop路徑 (2)配置Location
右鍵,選擇“new hadoop location”,出現新的選項卡
需要填寫的地方有幾個, Location Name,自己隨便起個名字。 左側的Master Host和Port,寫之前字啊Linux下配置IP與埠號,右側也是,埠號的對應關係是: mapred.job.tracker節點的value對應左側,core-site.xml裡的fs.default.name節點value對應右側。 username寫root,因為我之前在Linux一直是用root使用者操作的。
(3)修改advanced引數
有好多個引數,這裡只要把我們之前在Linux上配置過的節點的值改過來即可。
比如之前我們配置的hadoop.tmp.dir的值是/hadoop,而這裡預設的值不是這個,需要改正過來。改好之後,點選完成即可。
eclipse外掛使用
我們可以看見剛剛建立的location在左側顯示出來了,點選箭頭,可以檢視什麼在HDFS中的目錄結構,在對應目錄上右鍵,可以進行建立,修改檔案之類的操作。
遇到的問題
是不是感覺上邊太容易了?沒有什麼坑嘛,是因為我都拿在這裡說了。。。
(1)剛剛第一步編譯的hadoop-eclipse-plugin-1.2.1.jar,直接使用的話,在配置location時會有各種錯誤,通過分析錯誤日誌可以發現是由於缺少jar包導致的,我們先關閉eclipse,對這個jar處理一下。
(2)用壓縮工具開啟jar包,是開啟,不是解壓,然後進入lib資料夾下,右鍵新增檔案,在D:\hadoop-1.2.1\lib路徑下選擇要增加的jar包,如圖所示
新增這幾個jar包之後,我們回到上級目錄,進入META-INF,修改MANIFEST.MF檔案。
在倒數第二行,將原來的Bundle-ClassPath值修改為
Bundle-ClassPath: classes/,lib/hadoop-core.jar,lib/commons-cli-1.2.jar,lib/commons-configuration-1.6.jar,lib/commons-httpclient-3.0.1.jar,lib/commons-lang-2.4.jar,lib/jackson-core-asl-1.8.8.jar,lib/jackson-mapper-asl-1.8.8.jar
注意,要在一行上寫,也就是說中間不要有空格,不要打回車
弄好之後我們儲存一下,替換原來的jar包即可。
第二個問題是關於許可權問題的,由於在windows上和linux上的檔案許可權不盡相同,會帶來不必要的麻煩,所以我們需要對D:\hadoop-1.2.1\hadoop-core-1.2.1.jar進行修改,不過我按照網上的教程,註釋掉部分原始碼之後,在進行編譯,還是會出現錯誤,不知道是不是我的操作不正確,後來我在網上找到一個修改過的hadoop-core-1.0.3.jar,經測試可以正常使用,我在下邊給出連線,大家可以下載使用
hadoop例項
新建Map/Reduce工程,複製如下程式碼package xavier.hadoop.wordcount;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
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 WordCount {
public static class WordCountMap extends
Mapper<LongWritable, Text, Text, IntWritable> {
private final IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
StringTokenizer token = new StringTokenizer(line);
while (token.hasMoreTokens()) {
word.set(token.nextToken());
context.write(word, one);
}
}
}
public static class WordCountReduce 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));
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = new Job(conf);
job.setJarByClass(WordCount.class);
job.setJobName("wordcount");
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setMapperClass(WordCountMap.class);
job.setReducerClass(WordCountReduce.class);
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
job.waitForCompletion(true);
}
}
這是一個比較簡單的wordcount的入門例子,本人也剛剛接觸,就不在講解程式碼了。
要執行,需要先配置輸入引數,選擇run confignation
裡邊的IP換成自己的就ok。
需要注意的是,input/file01需要自己去建立的,file01隨便寫幾個英文單詞的句子就可以,最後會輸出檔案內每個單詞出現的數量。
感覺最後敘述的有些混亂了。。。大家明白意思就好。不一定非要按我的配置來,可以靈活變動的。
以上是我首次配置hadoop的過程,其中花費我不少時間,希望這篇文章能幫更多的初學者少走一些彎路。
最後奉上連線
連結: http://pan.baidu.com/s/1qY3thZQ 密碼: g53i