關(guān)于hadoop hdfs配置請參考hadoop學(xué)習(xí)筆記二
內(nèi)容概括:在筆記二所在的環(huán)境上配置 YARN
和 MapReduce
茅逮。然后在eclipse中遠(yuǎn)程連接hdfs并運行一個簡單的demo鹅心。這有一篇IBM的文章寫得非常好關(guān)于YARN的值得一看。
個人觀點:由于我們平時使用的服務(wù)器上大多有多個網(wǎng)卡也就是可能會有多個ip所以在配置關(guān)于ip時還是配置特定的ip比較保險奴拦,在多網(wǎng)卡環(huán)境下不同網(wǎng)卡可能處在不同的網(wǎng)絡(luò)中對于不明確的配置對遠(yuǎn)程連接有一定的誤導(dǎo)性。所以這里先改下之前帶有ip配置的配置文件,改為固定某個ip。
- 在hosts中添加ip和名字的映射馅巷,這樣就可以在配置文件中使用同一個名稱就可以代表同一個ip,同時方便修改名字所對應(yīng)的ip地址草姻。
編輯/etc/hosts添加下面內(nèi)容到末尾
172.16.94.128 master
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/usr/local/hadoop/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
<property>
<name>fs.defaultFS</name>
<!-- 修改localhost為master-->
<value>hdfs://master:9000</value>
</property>
</configuration>
配置YARN:
重命名mapred-site.xml.template
mv ./etc/hadoop/mapred-site.xml.template ./etc/hadoop/mapred-site.xml
修改mapred-site.xml為:
<configuration>
<!--新框架支持第三方 MapReduce 開發(fā)框架以支持如 SmartTalk/DGSG 等非 Yarn 架構(gòu)钓猬,注意通常情況下這個配置的值都設(shè)置為 Yarn,如果沒有配置這項撩独,那么提交的 Yarn job 只會運行在 locale 模式敞曹,而不是分布式模式账月。-->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!--添加此屬性以便遠(yuǎn)程創(chuàng)建MapReduce Job使用-->
<property>
<name>mapreduce.jobtracker.address</name>
<value>master:9001</value>
</property>
</configuration>
修改yarn-site.xml為:
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
啟動yarn(必須保證hdfs已經(jīng)啟動),查看hadoop啟動了哪些可以用jps
命令澳迫。hadoop啟動后有相應(yīng)的web頁面可以查看關(guān)于hadoop的hdfs相關(guān)信息局齿,在瀏覽器輸入http://172.16.94.128:50070 就可以看到如下頁面:
$ jps
4564 NameNode
4692 DataNode
4857 SecondaryNameNode
8861 Jps
--啟動yarn
$ ./sbin/start-yarn.sh
--查看是否啟動成,出現(xiàn)ResourceManager和NodeManager表示yarn啟動成功
$ jps
9042 NodeManager
9347 Jps
4564 NameNode
4692 DataNode
4857 SecondaryNameNode
8925 ResourceManager
--如果要記錄job執(zhí)行日志則需要啟動historyserver
$ ./sbin/mr-jobhistory-daemon.sh start historyserver
$ jps
9042 NodeManager
4564 NameNode
4692 DataNode
9605 JobHistoryServer
4857 SecondaryNameNode
8925 ResourceManager
9647 Jps
--出現(xiàn)JobHistoryServer就表示啟動成橄登,關(guān)于historyserver的目錄或者ip和端口可以在mapred-site.xml中配置抓歼,這里先用默認(rèn)的配置。
yarn啟動后可以用web頁面查看任務(wù)拢锹,在瀏覽器里面輸入http://172.16.94.128:8088 就可看見如下界面:
historyServer 也有web界面可以查看記錄谣妻,在瀏覽器里面輸入http://172.16.94.128:19888 就可以看見如下界面:
如果無法訪問請查看網(wǎng)絡(luò)和端口是否被防火墻屏蔽,一開始學(xué)習(xí)建議關(guān)閉防火墻卒稳。centos 7防火墻操作
到這里基礎(chǔ)模塊都啟動完成蹋半,下面先跑一個hadoop自帶的例子然后再在eclipse上面配置hdfs和一個demo。
同linux文件系統(tǒng)一樣在使用hdfs之前先創(chuàng)建用戶目錄:
-- -p創(chuàng)建多層目錄
$ ./bin/hdfs dfs -mkdir -p /user/hadoop
--創(chuàng)建好用戶目錄后我們在當(dāng)前用戶目錄下面建一個存儲mapreduce輸入文件的目錄
$ ./bin/hdfs dfs -mkdir input
運行hadoop自帶的demo:
--為了測試我們把hadoop的配置文件導(dǎo)入到 input中
$ ./bin/hdfs dfs -put ./etc/hadoop/*.xml input
--查看是否成功導(dǎo)入
$ ./bin/hdfs dfs -ls input
-rw-r--r-- 1 hadoop supergroup 4436 2016-07-15 00:50 input/capacity-scheduler.xml
-rw-r--r-- 1 hadoop supergroup 1071 2016-07-15 00:50 input/core-site.xml
-rw-r--r-- 1 hadoop supergroup 9683 2016-07-15 00:50 input/hadoop-policy.xml
-rw-r--r-- 1 hadoop supergroup 1233 2016-07-15 00:50 input/hdfs-site.xml
-rw-r--r-- 1 hadoop supergroup 620 2016-07-15 00:50 input/httpfs-site.xml
-rw-r--r-- 1 hadoop supergroup 3518 2016-07-15 00:50 input/kms-acls.xml
-rw-r--r-- 1 hadoop supergroup 5511 2016-07-15 00:50 input/kms-site.xml
-rw-r--r-- 1 hadoop supergroup 938 2016-07-15 00:50 input/mapred-site.xml
-rw-r--r-- 1 hadoop supergroup 792 2016-07-15 00:50 input/yarn-site.xml
--運行hadoop的一個例子充坑,找出所有符合正則表達(dá)式的詞語并存儲在output(由程序新建减江,如果已經(jīng)存在需刪除后再運行demo)目錄下面
$ ./bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar grep input output 'dfs[a-z.]+'
--運行后可以在對應(yīng)的web界面看到任何的運行狀態(tài)
--查看執(zhí)行后的output目錄
$ ./bin/hdfs dfs -ls output/
-rw-r--r-- 1 hadoop supergroup 0 2016-07-15 00:53 output/_SUCCESS
-rw-r--r-- 1 hadoop supergroup 95 2016-07-15 00:53 output/part-r-00000
--我們所需要的運行結(jié)果存儲在part*所在的文件中,打開這些文件就可看到我們需要的結(jié)果
$ ./bin/hdfs dfs -cat output/part-r-00000
1 dfsadmin
1 dfs.replication
1 dfs.permissions
1 dfs.namenode.name.dir
1 dfs.datanode.data.dir
--列出了出現(xiàn)次數(shù)和對應(yīng)的詞語匪傍,這里可以把在hdfs中的文件提取到系統(tǒng)文件系統(tǒng)中來您市。
$ ./bin/hdfs dfs -get output ./output
--hdfs還有很多命令用來完成不同的功能這里就不一一說了。
遠(yuǎn)程eclipse查看當(dāng)前hadoop hdfs中的文件配置:
1 在hdfs-site.xml中添加一個關(guān)于權(quán)限的配置屬性并設(shè)置成false(因為在eclipse hadoop插件訪問hdfs是獲取的eclipse所在的計算機的用戶名只要不和hadoop hdfs的用戶名(hadoop)不一致就無法進(jìn)行讀取和上傳操作)
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
2 下載eclipse ide和hadoop eclipse 插件役衡,這里我貼出我所使用的eclipse 版本和 hadoop eclipse 插件版本茵休,直接到eclipse官網(wǎng)下載,插件到hadoop github上下載就行:
插件:hadoop2x-eclipse-plugin-2.6.0.zip
3 解壓插件并將 release 中的 hadoop-eclipse-kepler-plugin-2.6.0.jar 復(fù)制到 Eclipse 安裝目錄的 plugins 文件夾中手蝎,重啟eclipse 插件安裝成功榕莺,并會出現(xiàn)以下圖標(biāo)。
4 在eclipse顯示出hdfs的配置窗口和配置相應(yīng)參數(shù)
點擊eclipse 菜單Window -> Show View -> Ohter則會出現(xiàn)下面界面并選擇Map/Reduce Locations然后ok棵介。
在上圖中右擊選擇New Hadoop location...
說明:Location name自定義
Map/Reduce(V2) Master 同mapred-site.xml mapreduce.jobtracker.address屬性配置钉鸯。
DFS Master 同core-site.xml fs.defaultFS屬性的配置。
User name 填寫hadoop hdfs用戶名邮辽。
5 點擊Finish并在Project Explorer中查看hdfs的內(nèi)容,如果沒有出現(xiàn)以下內(nèi)容可以右鍵刷新
在eclipse中實現(xiàn)一個遠(yuǎn)程MapReduce demo(WordCount)
先了解下如何提交job和job的執(zhí)行過程,以及java對hdfs的CRUD的一些api demo唠雕。還有關(guān)于hdfs中文件的權(quán)限說明多用戶對文件的權(quán)限設(shè)置。在這個測試之前一定要確保hadoop環(huán)境中的防火墻是關(guān)閉了或者h(yuǎn)adoop所使用的端口都加入防火墻端口信任列表了(血的教訓(xùn)啊吨述,為一個端口沒有加入信任列表無法遠(yuǎn)程提交job害我找了好久的問題)岩睁。
1 創(chuàng)建一個maven project并在pom.xml添加如下依賴和編譯和打包插件。(這里我們使用maven來管理hadoop的依賴和項目打包)
--添加依賴
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.2</version>
</dependency>
--添加編譯和打包插件
<build>
<plugins>
<!--打包工具-->
<plugin>
<groupId> org.apache.maven.plugins </groupId>
<artifactId> maven-jar-plugin </artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!--指定程序入口-->
<mainClass>WordCount</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!--指定編譯jdk版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2 創(chuàng)建一個M/R job(這里代碼是從其他地方拷貝過來修改了一點點):
import java.text.SimpleDateFormat;
import java.util.Date;
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.output.FileOutputFormat;
public class WordCount {
public static void main(String[] args) throws Exception {
/**
* 連接hadoop集群配置,也可以直接把hadoop的配置文件拷貝到當(dāng)前項目的resource目錄下并修改里面帶有IP的配置為服務(wù)器的IP地址揣云,然后使用Configuration的api加載那些配置文件(這里就不舉例了)捕儒,在代碼中沒有配置或者在你復(fù)制出來的配置文件中沒有配置的屬性都是使用的默認(rèn)配置,也就是說里面包含一些默認(rèn)IP的配置大多都是0.0.0.0,請把可能用到的帶有ip的配置都把ip改為服務(wù)器真實ip刘莹,以免在測試過程中導(dǎo)致無法連接而失敗阎毅,這里我通過代碼把我所可能用到的都重新配置了。對于這些配置的解釋可以看對應(yīng)配置文件的說明点弯。
*/
Configuration conf = new Configuration(true);
conf.set("fs.defaultFS", "hdfs://172.16.94.128:9000");
conf.set("hadoop.job.user", "hadoop");
conf.set("mapreduce.framework.name", "yarn");
//配置job提交的目錄 '/user'表示提交到當(dāng)前用戶(這里是hadoop)的目錄下
conf.set("yarn.app.mapreduce.am.staging-dir", "/user");
conf.set("mapreduce.jobhistory.address", "172.16.94.128:10020");
conf.set("mapreduce.jobtracker.address", "172.16.94.128:9001");
conf.set("yarn.resourcemanager.hostname", "172.16.94.128");
conf.set("yarn.resourcemanager.admin.address", "172.16.94.128:8033");
conf.set("yarn.resourcemanager.address", "172.16.94.128:8032");
conf.set("yarn.resourcemanager.resource-tracker.address", "172.16.94.128:8031");
conf.set("yarn.resourcemanager.scheduler.address", "172.16.94.128:8030");
//使支持跨系統(tǒng)提交job
conf.set("mapreduce.app-submission.cross-platform", "true");
//指定我們打包后的jar包位置扇调,在eclipse中運行此項目時會根據(jù)這個路徑找到j(luò)ar包上傳到hadoop中yarn.app.mapreduce.am.staging-dir所對應(yīng)的地方,否則會出現(xiàn)CLass Not Found的錯誤蒲拉。
// 所以在執(zhí)行前應(yīng)該先使用maven clean install把當(dāng)前項目打包肃拜,才能在運行時找到j(luò)ar包。
//網(wǎng)上還有介紹了一些通過代碼實現(xiàn)打包的方法雌团,這里不介紹燃领,因為在正常開發(fā)時都是把生成的jar包之間上傳到想要的目錄,只是測試時我們用得到而已锦援,所以如果是要手動上傳jar包下面這句可以注釋掉猛蔽。
conf.set("mapred.jar","target/baosh-storage-hadoop-0.0.1-SNAPSHOT.jar");
String[] otherArgs = new String[2];
otherArgs[0] = "hdfs://172.16.94.128:9000/user/hadoop/input";//計算原文件目錄,需提前在里面存入文件
String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
otherArgs[1] = "hdfs://172.16.94.128:9000/user/hadoop/test_out/" + time;//計算后的計算結(jié)果存儲目錄灵寺,每次程序執(zhí)行的結(jié)果目錄不能相同曼库,所以添加時間標(biāo)簽
/*
* setJobName()方法命名這個Job。對Job進(jìn)行合理的命名有助于更快地找到Job略板,
* 以便在JobTracker和Tasktracker的頁面中對其進(jìn)行監(jiān)視
*/
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
System.out.println(job.getJar());
// job.setMaxMapAttempts(100);//設(shè)置最大試圖產(chǎn)生底map數(shù)量毁枯,該命令不一定會設(shè)置該任務(wù)運行過車中的map數(shù)量
// job.setNumReduceTasks(5);//設(shè)置reduce數(shù)量,即最后生成文件的數(shù)量
/*
* Job處理的Map(拆分)叮称、Combiner(中間結(jié)果合并)以及Reduce(合并)的相關(guān)處理類种玛。
* 這里用Reduce類來進(jìn)行Map產(chǎn)生的中間結(jié)果合并,避免給網(wǎng)絡(luò)數(shù)據(jù)傳輸產(chǎn)生壓力瓤檐。
*/
job.setMapperClass(TokenizerMapper.class);// 執(zhí)行用戶自定義map函數(shù)
job.setCombinerClass(IntSumReducer.class);// 對用戶自定義map函數(shù)的數(shù)據(jù)處理結(jié)果進(jìn)行合并赂韵,可以減少帶寬消耗
job.setReducerClass(IntSumReducer.class);// 執(zhí)行用戶自定義reduce函數(shù)
/*
* 接著設(shè)置Job輸出結(jié)果<key,value>的中key和value數(shù)據(jù)類型,因為結(jié)果是<單詞,個數(shù)>挠蛉,
* 所以key設(shè)置為"Text"類型祭示,相當(dāng)于Java中String類型
* 。Value設(shè)置為"IntWritable"谴古,相當(dāng)于Java中的int類型质涛。
*/
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
/*
* 加載輸入文件夾或文件路徑,即輸入數(shù)據(jù)的路徑
* 將輸入的文件數(shù)據(jù)分割成一個個的split掰担,并將這些split分拆成<key,value>對作為后面用戶自定義map函數(shù)的輸入
* 其中汇陆,每個split文件的大小盡量小于hdfs的文件塊大小
* (默認(rèn)64M),否則該split會從其它機器獲取超過hdfs塊大小的剩余部分?jǐn)?shù)據(jù)恩敌,這樣就會產(chǎn)生網(wǎng)絡(luò)帶寬造成計算速度影響
* 默認(rèn)使用TextInputFormat類型瞬测,即輸入數(shù)據(jù)形式為文本類型數(shù)據(jù)文件
*/
System.out.println("Job start!");
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
/*
* 設(shè)置輸出文件路徑 默認(rèn)使用TextOutputFormat類型横媚,即輸出數(shù)據(jù)形式為文本類型文件纠炮,字段間默認(rèn)以制表符隔開
*/
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
/*
* 開始運行上面的設(shè)置和算法
*/
if (job.waitForCompletion(true)) {
System.out.println("ok!");
} else {
System.out.println("error!");
System.exit(0);
}
}
}
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;
/*
* 用戶自定義map函數(shù)月趟,對以<key, value>為輸入的結(jié)果文件進(jìn)行處理
* Map過程需要繼承org.apache.hadoop.mapreduce包中Mapper類,Mapper類是一個泛型類恢口,帶有4個參數(shù)(輸入的鍵孝宗,輸入的值,輸出的鍵耕肩,輸出的值,并重寫其map方法因妇。
* 通過在map方法中添加兩句把key值和value值輸出到控制臺的代碼
* ,可以發(fā)現(xiàn)map方法中value值存儲的是文本文件中的一行(以回車符為行結(jié)束標(biāo)記)猿诸,而key值為該行的首字母相對于文本文件的首地址的偏移量婚被。
* 然后StringTokenizer類將每一行拆分成為一個個的單詞
* ,并將<word,1>作為map方法的結(jié)果輸出梳虽,其余的工作都交有MapReduce框架處理址芯。 每行數(shù)據(jù)調(diào)用一次 Tokenizer:單詞分詞器
*/
public class TokenizerMapper extends
Mapper<Object, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
/*
* 重寫Mapper類中的map方法
*/
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
//System.out.println(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());// 獲取下個字段的值并寫入文件
context.write(word, one);
}
}
}
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/*
* 用戶自定義reduce函數(shù),如果有多個熱度測窜觉,則每個reduce處理自己對應(yīng)的map結(jié)果數(shù)據(jù)
* Reduce過程需要繼承org.apache.hadoop.mapreduce包中Reducer類谷炸,Reducer類是一個泛型類,帶有4個參數(shù)(輸入的鍵禀挫,輸入的值旬陡,輸出的鍵,輸出的值)语婴。并重寫其reduce方法描孟。
* Map過程輸出<key,values>中key為單個單詞,而values是對應(yīng)單詞的計數(shù)值所組成的列表腻格,Map的輸出就是Reduce的輸入画拾,
* 所以reduce方法只要遍歷values并求和,即可得到某個單詞的總次數(shù)菜职。
*/
public class IntSumReducer extends
Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
以上就是這個demo的所有代碼了青抛。
3 運行WordCount.java:
運行結(jié)果:
這是job提交后在hdfs中的文件
4 查看運行結(jié)果:
在DFS Locations中可以看到我們輸出的文件,在eclipse中雙擊打開part-r-00000文件會看到類似以下內(nèi)容:
運行成功。
運行遇到的一些問題:
1 用戶權(quán)限問題
Exception in thread "main" org.apache.hadoop.security.AccessControlException:
Permission denied: user=***, access=EXECUTE, inode="/tmp/hadoop-yarn/staging/***/.staging/job_1468660403917_0003":hadoop:supergroup:drwxrwx---
--這表示user所指的用戶在inode所指定的路徑下沒有執(zhí)行文件的權(quán)限酬核,解決方式有兩種:1 要么在運行這個案例時所在環(huán)境的環(huán)境變量里添加HADOOP_USER_NAME=“有權(quán)限的用戶名”蜜另。2 要么去hdfs中把這個目錄的權(quán)限改成任何人都可以執(zhí)行。
這里我們只是在eclipse上跑demo所以我采用第一種方式嫡意,而且只是在eclipse中配置了一個環(huán)境變量:
這里hadoop這個用戶是有權(quán)限的举瑰。
2 jar包沒有上傳導(dǎo)致的Class Not found的異常。這個問題在代碼中有解釋蔬螟。
3 默認(rèn)配置ip問題此迅。在代碼中也有解釋。
結(jié)束語:由于參考的連接太多了就不一一列出來了,在文章中關(guān)鍵位置都加了連接耸序。筆記粗糙如有不適請多包涵忍些。
提示:請根據(jù)個人的環(huán)境修改上面的IP和端口。所有job的運行記錄的狀態(tài)都可以在對應(yīng)的web 界面可以看見坎怪,對于web 界面上面有描述罢坝。