原文同步至 http://waylau.com/about-hadoop/html
Apache Hadoop 是一個由 Apache 基金會所開發的分佈式系統基礎架構。可讓用戶在不瞭解分佈式底層細節的狀況下,開發出可靠、可擴展的分佈式計算應用。java
Apache Hadoop 框架,容許用戶使用簡單的編程模型來實現計算機集羣的大型數據集的分佈式處理。它的目的是支持從單一服務器到上千臺機器的擴展,充分利用了每臺機器所提供本地計算和存儲,而不是依靠硬件來提供高可用性。其自己被設計成在應用層檢測和處理故障的庫,對於計算機集羣來講,其中每臺機器的頂層都被設計成能夠容錯的,以便提供一個高度可用的服務。node
Apache Hadoop 的框架最核心的設計就是:HDFS 和 MapReduce。HDFS 爲海量的數據提供了存儲,而 MapReduce 則爲海量的數據提供了計算。web
<!-- more -->正則表達式
正如上一節 MapReduce 所提到的那樣,Apache Hadoop 受到了 Google 的 GFS 和 MapReduce 的啓發,而前者產生了 Apache Hadoop 的分佈式文件系統 NDFS (Nutch Distributed File System) ,然後者也被歸入到 Apache Hadoop 做爲核心組件之一。算法
Apache Hadoop 的雛形開始於2002年的 Apache 的 Nutch。Nutch 是一個開源 Java 實現的搜索引擎。它提供了咱們運行本身的搜索引擎所需的所有工具,包括全文搜索和 Web 爬蟲。shell
隨後在 2003 年 Google 發表了一篇技術學術論文關於 Google 文件系統(GFS)。GFS 也就是 Google File System,是 Google 公司爲了存儲海量搜索數據而設計的專用文件系統。數據庫
2004年 Nutch 創始人 Doug Cutting(同時也是 Apache Lucene 的創始人) 基於 Google 的 GFS 論文實現了分佈式文件存儲系統名爲 NDFS。apache
2004年 Google 又發表了一篇技術學術論文,向全世界介紹了 MapReduce。2005年 Doug Cutting 又基於 MapReduce,在 Nutch 搜索引擎實現了該功能。編程
2006年,Yahoo! 僱用了 Doug Cutting,Doug Cutting 將 NDFS 和MapReduce 升級命名爲 Hadoop。Yahoo! 開建了一個獨立的團隊給 Goug Cutting 專門研究發展 Hadoop。
2008年1月,Hadoop 成爲了 Apache 頂級項目。以後 Hadoop 被成功的應用在了其餘公司,其中包括 Last.fm、Facebook、《紐約時報》等。
2008年2月,Yahoo! 宣佈其搜索引擎產品部署在一個擁有1萬個內核的 Hadoop 集羣上。
2008年4月,Hadoop 打破世界記錄,稱爲最快排序1TB數據的系統。有關該報道的記錄,能夠參閱《Apache Hadoop Wins Terabyte Sort Benchmark》(見 https://developer.yahoo.com/blogs/hadoop/apache-hadoop-wins-terabyte-sort-benchmark-408.html)。
截止目前,Apache Hadoop 的最新版本爲 2.7.3。
Apache Hadoop 它主要有如下幾個優勢:
Apache Hadoop 包含如下模塊:
其餘與 Apache Hadoop 的相關項目包括:
下面將演示快速完成在單節點上的 Hadoop 安裝與配置,以便你對 Hadoop HDFS 和 MapReduce 框架有所體會。
支持平臺:
所需軟件:
$ sudo apt-get install ssh $ sudo apt-get install rsync
下載地址在 http://www.apache.org/dyn/closer.cgi/hadoop/common/。
解壓所下載的 Hadoop 發行版。編輯 etc/hadoop/hadoop-env.sh
文件,定義以下參數:
# 設置 Java 的安裝目錄 export JAVA_HOME=/usr/java/latest
嘗試以下命令:
$ bin/hadoop
將會顯示 hadoop 腳本的使用文檔。
如今你能夠用如下三種支持的模式中的一種啓動 Hadoop 集羣:
默認狀況下,Hadoop 被配置成以非分佈式模式運行的一個獨立 Java 進程。這對調試很是有幫助。
下面的實例將已解壓的 conf 目錄拷貝做爲輸入,查找並顯示匹配給定正則表達式的條目。輸出寫入到指定的 output 目錄。
$ mkdir input $ cp etc/hadoop/*.xml input $ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+' $ cat output/*
Hadoop 能夠在單節點上以所謂的僞分佈式模式運行,此時每個 Hadoop 守護進程都做爲一個獨立的 Java 進程運行。
使用以下的:
etc/hadoop/core-site.xml
:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration>
etc/hadoop/hdfs-site.xml
:
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>
如今確認可否不輸入口令就用 ssh 登陸 localhost:
$ ssh localhost
若是不輸入口令就沒法用 ssh 登錄 localhost,執行下面的命令:
$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa $ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys $ chmod 0600 ~/.ssh/authorized_keys
下面演示本地運行一個 MapReduce 的 job,如下是運行步驟。
(1)格式化一個新的分佈式文件系統:
$ bin/hdfs namenode -format
(2)啓動 NameNode 守護進程和 DataNode 守護進程:
$ sbin/start-dfs.sh
Hadoop 守護進程的日誌寫入到 $HADOOP_LOG_DIR
目錄(默認是 $HADOOP_HOME/logs
)
(3)瀏覽 NameNode 的網絡接口,它們的地址默認爲:
NameNode - http://localhost:50070/
(4)建立 HDFS 目錄來執行 MapReduce 的 job:
$ bin/hdfs dfs -mkdir /user $ bin/hdfs dfs -mkdir /user/<username>
(5)將輸入文件拷貝到分佈式文件系統:
$ bin/hdfs dfs -put etc/hadoop input
(6)運行發行版提供的示例程序:
$ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+'
(7)查看輸出文件
將輸出文件從分佈式文件系統拷貝到本地文件系統查看:
$ bin/hdfs dfs -get output output $ cat output/*
或者,在分佈式文件系統上查看輸出文件:
$ bin/hdfs dfs -cat output/*
(8)完成所有操做後,中止守護進程:
$ sbin/stop-dfs.sh
您能夠經過設置幾個參數,另外運行 ResourceManager 的守護進程和 NodeManager 守護進程以僞分佈式模式在 YARN 上運行 MapReduce job。
如下是運行步驟。
(1)配置
etc/hadoop/mapred-site.xml
:
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>
etc/hadoop/yarn-site.xml
:
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration>
(2)啓動 ResourceManager 守護進程和 NodeManager 守護進程
$ sbin/start-yarn.sh
(3)瀏覽 ResourceManager 的網絡接口,它們的地址默認爲:
ResourceManager - http://localhost:8088/
(4)運行 MapReduce job
(5)完成所有操做後,中止守護進程:
$ sbin/stop-yarn.sh
關於搭建徹底分佈式模式的,請參閱下文《Apache Hadoop 集羣上的安裝配置》小節內容。
本節將描述如何安裝、配置和管理 Hadoop 集羣,其規模可從幾個節點的小集羣到幾千個節點的超大集羣。
確保在你集羣中的每一個節點上都安裝了全部必需軟件,安裝 Hadoop 集羣一般要將安裝軟件解壓到集羣內的全部機器上,參考上節內容《Apache Hadoop 單節點上的安裝配置》。
一般狀況下,集羣中的一臺機器被指定爲 NameNode 和另外一臺機器做爲 ResourceManager。這些都是 master。其餘服務(例如,Web 應用程序代理服務器和 MapReduce Job History 服務器)是在專用的硬件仍是共享基礎設施上運行,這取決於負載。
在羣集裏剩餘的機器充當 DataNode 和 NodeManager。這些都是 slave。
Hadoop 配置有兩種類型的重要配置文件:
core-default.xml
、hdfs-default.xml
、yarn-default.xml
和 mapred-default.xml
;etc/hadoop/core-site.xml
、etc/hadoop/hdfs-site.xml
、etc/hadoop/yarn-site.xml
和 etc/hadoop/mapred-site.xml
。另外,你可以配置 bin 目錄下的 etc/hadoop/hadoop-env.sh
和 etc/hadoop/yarn-env.sh
腳本文件的值來控制 Hadoop 的腳本。
爲了配置 Hadoop 集羣,你須要配置 Hadoop 守護進程的執行環境和Hadoop 守護進程的配置參數。
HDFS 的守護進程有 NameNode、econdaryNameNode 和 DataNode。YARN 的守護進程有 ResourceManager、NodeManager 和 WebAppProxy。若 MapReduce 在使用,那麼 MapReduce Job History Server 也是在運行的。在大型的集羣中,這些通常都是在不一樣的主機上運行。
管理員應該利用etc/hadoop/hadoop-env.sh
、etc/hadoop/mapred-env.sh
和 etc/hadoop/yarn-env.sh
腳原本對 Hadoop 守護進程的環境作一些自定義的配置。
至少你應該在每一個遠程節點上正確配置 JAVA_HOME。
管理員可以使用下面的表格當中的配置選項來配置獨立的守護進程:
守護進程 | 環境變量 |
---|---|
NameNode | HADOOP_NAMENODE_OPTS |
DataNode | HADOOP_DATANODE_OPTS |
SecondaryNamenode | HADOOP_SECONDARYNAMENODE_OPTS |
ResourceManager | YARN_RESOURCEMANAGER_OPTS |
NodeManager | YARN_NODEMANAGER_OPTS |
WebAppProxy | YARN_PROXYSERVER_OPTS |
Map Reduce Job History Server | HADOOP_JOB_HISTORYSERVER_OPTS |
例如,配置 Namenode 時,爲了使其可以 parallelGC(並行回收垃圾), 要把下面的代碼加入到 etc/hadoop/hadoop-env.sh
:
export HADOOP_NAMENODE_OPTS="-XX:+UseParallelGC"
其它可定製的經常使用參數還包括:
在大多數狀況下,你應該指定 HADOOP_PID_DIR 和 HADOOP_LOG_DIR 目錄,這樣它們只能由要運行 hadoop 守護進程的用戶寫入。不然會受到符號連接攻擊的可能。
這也是在 shell 環境配置裏配置 HADOOP_PREFIX 的傳統方式。例如,在/etc/profile.d
中一個簡單的腳本的配置以下:
HADOOP_PREFIX=/path/to/hadoop export HADOOP_PREFIX
守護進程 | 環境變量 |
---|---|
ResourceManager | YARN_RESOURCEMANAGER_HEAPSIZE |
NodeManager | YARN_NODEMANAGER_HEAPSIZE |
WebAppProxy | YARN_PROXYSERVER_HEAPSIZE |
Map Reduce Job History Server | HADOOP_JOB_HISTORYSERVER_HEAPSIZE |
這部分涉及 Hadoop 集羣的重要參數的配置
etc/hadoop/core-site.xml
參數 | 取值 | 備註 |
---|---|---|
fs.defaultFS | NameNode URI | hdfs://host:port/ |
io.file.buffer.size | 131072 | SequenceFiles 中讀寫緩衝的大小 |
etc/hadoop/hdfs-site.xml
用於配置 NameNode:
參數 | 取值 | 備註 |
---|---|---|
dfs.namenode.name.dir | NameNode 持久存儲命名空間及事務日誌的本地文件系統路徑。 | 當這個值是一個逗號分割的目錄列表時,name table 數據將會被複制到全部目錄中作冗餘備份。 |
dfs.hosts / dfs.hosts.exclude | 容許/排除的 DataNodes 列表。 | 若是有必要,使用這些文件,以控制容許的 datanodes 的列表。 |
dfs.blocksize | 268435456 | 在大型文件系統裏面設置 HDFS 塊大小爲 256MB |
dfs.namenode.handler.count | 100 | 在大數量的 DataNodes 裏面用更多的 NameNode 服務器線程來控制 RPC |
用於配置 DataNode:
參數 | 取值 | 備註 |
---|---|---|
dfs.datanode.data.dir | DataNode存放塊數據的本地文件系統路徑,逗號分割的列表。 | 當這個值是逗號分割的目錄列表時,數據將被存儲在全部目錄下,一般分佈在不一樣設備上。 |
etc/hadoop/yarn-site.xml
用於配置 ResourceManager 和 NodeManager:
參數 | 取值 | 備註 |
---|---|---|
yarn.acl.enable | true / false | 是否啓用 ACLs。默認是 false |
yarn.admin.acl | Admin ACL | ACL 集羣上設置管理員。 ACLs 是用逗號分隔的。默認爲 * 意味着任何人。特殊值空格,意味着沒有人能夠進入。 |
yarn.log-aggregation-enable | false | 配置算法啓用日誌聚合 |
用於配置 ResourceManager :
參數 | 取值 | 備註 |
---|---|---|
yarn.resourcemanager.address | ResourceManager host:port ,用於給客戶端提交 jobs | 若 host:port 設置,則覆蓋 yarn.resourcemanager.hostname 中的 hostname |
yarn.resourcemanager.scheduler.address | ResourceManager host:port,用於 ApplicationMasters (主節點)和 Scheduler(調度器)通訊來取得資源 | 若 host:port 設置,則覆蓋 yarn.resourcemanager.hostname 中的 hostname |
yarn.resourcemanager.resource-tracker.address | ResourceManager host:port ,用於 NodeManagers | 若 host:port 設置,則覆蓋 yarn.resourcemanager.hostname 中的 hostname |
yarn.resourcemanager.admin.address | ResourceManager host:port ,用於管理命令 | 若 host:port 設置,則覆蓋 yarn.resourcemanager.hostname 中的 hostname |
yarn.resourcemanager.webapp.address | ResourceManager web-ui host:port,用於 web 管理 | 若 host:port 設置,則覆蓋 yarn.resourcemanager.hostname 中的 hostname |
yarn.resourcemanager.scheduler.class | ResourceManager Scheduler 類 | CapacityScheduler (推薦)、FairScheduler(也推薦)或 FifoScheduler |
yarn.scheduler.minimum-allocation-mb | 分配給每一個容器請求Resource Manager 的最小內存 | 單位爲 MB |
yarn.scheduler.maximum-allocation-mb | 分配給每一個容器請求Resource Manager 的最大內存 | 單位爲 MB |
yarn.resourcemanager.nodes.include-path / yarn.resourcemanager.nodes.exclude-path | 容許/拒絕的NodeManager 的列表 | 若是有必要,用這些文件來控制列出的容許的 NodeManager |
用於配置 NodeManager :
參數 | 取值 | 備註 |
---|---|---|
yarn.nodemanager.resource.memory-mb | NodeManager 可用的物理內存 | 定義在 NodeManager 上的所有資源,用來運行容器。 |
yarn.nodemanager.vmem-pmem-ratio | task 使用虛擬內存的最大比例,可能超過物理內存 | 每一個 task 使用的虛擬內存可能超過它的物理內存, 虛擬內存靠這個比率來進行限制。這個比率限制的在 NodeManager 上task 使用的虛擬內存總數,可能會超過它的物理內存。 |
yarn.nodemanager.local-dirs | 在本地文件系統裏,寫入中間數據的地方的路徑。多個路徑就用逗號進行隔開。 | 多個路徑有助於分散磁盤I/O |
yarn.nodemanager.log-dirs | 在本地文件系統裏,寫入日誌的地方的路徑。多個路徑就用逗號進行隔開。 | 多個路徑有助於分散磁盤I/O |
yarn.nodemanager.log.retain-seconds | 10800 | 日誌文件在NodeManager 上保存的默認時間(單位爲秒),僅僅適合在日誌聚合關閉的時候使用。 |
yarn.nodemanager.remote-app-log-dir | /logs | 在應用程序完成的時候,應用程序的日誌將移到這個HDFS目錄。須要設置適當的權限。 僅僅適合在日誌聚合開啓的時候使用。 |
yarn.nodemanager.remote-app-log-dir-suffix | logs | 追加到遠程日誌目錄 |
yarn.nodemanager.aux-services 、 mapreduce.shuffle | 給 Map Reduce 應用程序設置 Shuffle 服務。 |
用於配置 History Server (需搬移到其它地方):
參數 | 取值 | 備註 |
---|---|---|
yarn.log-aggregation.retain-seconds | -1 | 保留聚合日誌的時間, -1 表示不啓用。須要注意的是,該值不能設置的過小 |
yarn.log-aggregation.retain-check-interval-seconds | -1 | 檢查聚合日誌保留的時間間隔,-1 表示不啓用。須要注意的是,該值不能設置的過小 |
etc/hadoop/mapred-site.xml
用於配置 MapReduce 應用:
參數 | 取值 | 備註 |
---|---|---|
mapreduce.framework.name | yarn | 運行框架設置爲 Hadoop YARN. |
mapreduce.map.memory.mb | 1536 | maps 的最大資源. |
mapreduce.map.java.opts | -Xmx1024M | maps 子虛擬機的堆大小 |
mapreduce.reduce.memory.mb | 3072 | reduces 的最大資源. |
mapreduce.reduce.java.opts | -Xmx2560M | reduces 子虛擬機的堆大小 |
mapreduce.task.io.sort.mb | 512 | 任務內部排序緩衝區大小 |
mapreduce.task.io.sort.factor | 100 | 在整理文件時一次性合併的流數量 |
mapreduce.reduce.shuffle.parallelcopies | 50 | reduces 運行的最大並行複製的數量,用於獲取大量的 maps 的輸出 |
用於配置 MapReduce JobHistory Server:
參數 | 取值 | 備註 |
---|---|---|
mapreduce.jobhistory.address | MapReduce JobHistory Server host:port | 默認端口是 10020. |
mapreduce.jobhistory.webapp.address | MapReduce JobHistory Server Web 界面 host:port | 默認端口是 19888. |
mapreduce.jobhistory.intermediate-done-dir | /mr-history/tmp | MapReduce jobs 寫入歷史文件的目錄 |
mapreduce.jobhistory.done-dir | /mr-history/done | MR JobHistory Server 管理的歷史文件目錄 |
Hadoop 提供了一種機制,管理員能夠配置 NodeManager 來運行提供腳本按期確認一個節點是否健康。
管理員能夠經過在腳本中執行檢查來判斷該節點是否處於健康狀態。若是腳本檢查到節點不健康,能夠打印一個標準的 ERROR(錯誤)輸出。NodeManager 經過一些腳本按期檢查他的輸出,若是腳本輸出有 ERROR信息,如上所述,該節點將報告爲不健康,就將節點加入到 ResourceManager 的黑名單列表中,則任務不會分配到該節點中。而後 NodeManager 繼續跑這個腳本,因此若是 Node 節點變爲健康了,將自動的從 ResourceManager 的黑名單列表刪除,節點的健康情況隨着腳本的輸出,若是變爲不健康,在 ResourceManager web 接口上對管理員來講是可用的。這個時候節點的健康情況不會顯示在web接口上。
在etc/hadoop/yarn-site.xml
下,能夠控制節點的健康檢查腳本:
參數 | 取值 | 備註 |
---|---|---|
yarn.nodemanager.health-checker.script.path | Node health script | 這個腳本檢查節點的健康狀態。 |
yarn.nodemanager.health-checker.script.opts | Node health script options | 檢查節點的健康狀態腳本選項 |
yarn.nodemanager.health-checker.script.interval-ms | Node health script interval | 運行健康腳本的時間間隔 |
yarn.nodemanager.health-checker.script.timeout-ms | Node health script timeout interval | 健康腳本的執行超時時間 |
若是隻是本地硬盤壞了,健康檢查腳本將不會設置該節點爲 ERROR。可是NodeManager 有能力來按期檢查本地磁盤的健康(檢查 nodemanager-local-dirs 和 nodemanager-log-dirs 兩個目錄),當達到yarn.nodemanager.disk-health-checker.min-healthy-disks 設置的閥值,則整個節點將標記爲不健康。
全部 slave 的 hostname 或者 IP 都保存在etc/hadoop/slaves
文件中,每行一個。腳本能夠經過etc/hadoop/slaves
文件去運行多臺機器的命令。他不使用任何基於 Java 的 Hadoop 配置。爲了使用這個功能,ssh 必須創建好使用帳戶才能運行 Hadoop。因此在安裝 Hadoop 的時候,須要配置 ssh 登錄。
不少 Hadoop 組件得益於機架感知,給性能和安全性帶來了很大的提高,Hadoop 的守護進程調用管理配置的模塊,獲取到集羣 slave 的機架信息,更多的機架感知信息,查看這裏 http://hadoop.apache.org/docs/r2.7.3/hadoop-project-dist/hadoop-common/RackAwareness.html。
使用 HDFS 時,強烈推薦使用機架感知。
Hadoop 使用 Apache log4j 做爲日誌框架,編輯etc/hadoop/log4j.properties
文件來自定義日誌的配置。
全部必備的配置都完成了,分發 HADOOP_CONF_DIR 配置文件到全部機器,全部機器安裝 Hadoop 目錄的路徑應該是同樣的。
在通常狀況下,建議 HDFS 和 YARN 做爲單獨的用戶運行。在大多數安裝中,HDFS 執行 「hdfs」。YARN 一般使用「yarn」賬戶。
爲了啓動 Hadoop 集羣,你須要啓動 HDFS 和 YARN 集羣。
第一次使用 HDFS 須要格式化。 做爲 hdfs 格式化新分發的文件系統:
[hdfs]$ $HADOOP_PREFIX/bin/hdfs namenode -format <cluster_name>
做爲 hdfs,經過以下命令啓動 HDFS NameNode 到指定的節點 :
[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemon.sh --config $HADOOP_CONF_DIR --script hdfs start namenode
做爲 hdfs,經過以下命令啓動 HDFS DataNode 到每一個指定的節點 :
[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemons.sh --config $HADOOP_CONF_DIR --script hdfs start datanode
做爲 hdfs,若是 etc/hadoop/slaves
和 ssh 可信任訪問已經配置,那麼全部的 HDFS 進程均可以經過腳本工具來啓動:
[hdfs]$ $HADOOP_PREFIX/sbin/start-dfs.sh
做爲 yarn,經過下面的命令啓動 YARN,運行指定的 ResourceManager :
[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR start resourcemanager
做爲 yarn,運行腳原本啓動從機上的全部 NodeManager:
[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemons.sh --config $HADOOP_CONF_DIR start nodemanager
做爲 yarn,啓動本地化的 WebAppProxy 服務器。若是想使用大量的服務器來實現負載均衡,那麼它就應該運行在它們各自機器之上:
[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR start proxyserver
做爲 yarn,若是 etc/hadoop/slaves
和 ssh 可信任訪問已經配置,那麼全部的 YARN 進程均可以經過腳本工具來啓動:
[yarn]$ $HADOOP_PREFIX/sbin/start-yarn.sh
做爲 mapred,根據下面的命令啓動 MapReduce JobHistory Server :
[mapred]$ $HADOOP_PREFIX/sbin/mr-jobhistory-daemon.sh --config $HADOOP_CONF_DIR start historyserver
做爲 hdfs,經過如下命令中止 NameNode:
[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemon.sh --config $HADOOP_CONF_DIR --script hdfs stop namenode
做爲 hdfs,運行腳本中止在全部從機上的全部 DataNode:
[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemons.sh --config $HADOOP_CONF_DIR --script hdfs stop datanode
做爲 hdfs,若是 etc/hadoop/slaves
和 ssh 可信任訪問已經配置,那麼全部的 HDFS 進程均可以經過腳本工具來關閉:
[hdfs]$ $HADOOP_PREFIX/sbin/stop-dfs.sh
做爲 yarn,經過如下命令中止 ResourceManager:
[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR stop resourcemanager
做爲 yarn,運行一下腳本中止 slave 機器上的 NodeManager :
[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemons.sh --config $HADOOP_CONF_DIR stop nodemanager
做爲 yarn,若是 etc/hadoop/slaves
和 ssh 可信任訪問已經配置,那麼全部的 YARN 進程均可以經過腳本工具來關閉
[yarn]$ $HADOOP_PREFIX/sbin/stop-yarn.sh
做爲 yarn,中止 WebAppProxy 服務器。因爲負載均衡有可能設置了多個:
[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR stop proxyserver
做爲 mapred,經過如下命令中止 MapReduce JobHistory Server :
[mapred]$ $HADOOP_PREFIX/sbin/mr-jobhistory-daemon.sh --config $HADOOP_CONF_DIR stop historyserver
當 Hadoop 啓動後,能夠查看以下 Web 界面:
守護進行 | Web 界面 | 備註 |
---|---|---|
NameNode | http://nn_host:port/ | 默認 HTTP 端口爲 50070. |
ResourceManager | http://rm_host:port/ | 默認 HTTP端口爲 8088 |
MapReduce JobHistory Server | http://jhs_host:port/ | 默認 HTTP 端口爲 19888 |
下面是 Hadoop 提供的詞頻統計 WordCount 程序 示例。運行運行改程序以前,請確保 HDFS 已經啓動。
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; 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.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.output.FileOutputFormat; import org.apache.hadoop.mapreduce.Counter; import org.apache.hadoop.util.GenericOptionsParser; import org.apache.hadoop.util.StringUtils; public class WordCount2 { public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{ static enum CountersEnum { INPUT_WORDS } private final static IntWritable one = new IntWritable(1); private Text word = new Text(); private boolean caseSensitive; private Set<String> patternsToSkip = new HashSet<String>(); private Configuration conf; private BufferedReader fis; @Override public void setup(Context context) throws IOException, InterruptedException { conf = context.getConfiguration(); caseSensitive = conf.getBoolean("wordcount.case.sensitive", true); if (conf.getBoolean("wordcount.skip.patterns", true)) { URI[] patternsURIs = Job.getInstance(conf).getCacheFiles(); for (URI patternsURI : patternsURIs) { Path patternsPath = new Path(patternsURI.getPath()); String patternsFileName = patternsPath.getName().toString(); parseSkipFile(patternsFileName); } } } private void parseSkipFile(String fileName) { try { fis = new BufferedReader(new FileReader(fileName)); String pattern = null; while ((pattern = fis.readLine()) != null) { patternsToSkip.add(pattern); } } catch (IOException ioe) { System.err.println("Caught exception while parsing the cached file '" + StringUtils.stringifyException(ioe)); } } @Override public void map(Object key, Text value, Context context ) throws IOException, InterruptedException { String line = (caseSensitive) ? value.toString() : value.toString().toLowerCase(); for (String pattern : patternsToSkip) { line = line.replaceAll(pattern, ""); } StringTokenizer itr = new StringTokenizer(line); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); Counter counter = context.getCounter(CountersEnum.class.getName(), CountersEnum.INPUT_WORDS.toString()); counter.increment(1); } } } public static 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); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); GenericOptionsParser optionParser = new GenericOptionsParser(conf, args); String[] remainingArgs = optionParser.getRemainingArgs(); if (!(remainingArgs.length != 2 | | remainingArgs.length != 4)) { System.err.println("Usage: wordcount <in> <out> [-skip skipPatternFile]"); System.exit(2); } Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount2.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); List<String> otherArgs = new ArrayList<String>(); for (int i=0; i < remainingArgs.length; ++i) { if ("-skip".equals(remainingArgs[i])) { job.addCacheFile(new Path(remainingArgs[++i]).toUri()); job.getConfiguration().setBoolean("wordcount.skip.patterns", true); } else { otherArgs.add(remainingArgs[i]); } } FileInputFormat.addInputPath(job, new Path(otherArgs.get(0))); FileOutputFormat.setOutputPath(job, new Path(otherArgs.get(1))); System.exit(job.waitForCompletion(true) ? 0 : 1); } }
待輸入的樣本文件以下:
$ bin/hadoop fs -ls /user/joe/wordcount/input/ /user/joe/wordcount/input/file01 /user/joe/wordcount/input/file02 $ bin/hadoop fs -cat /user/joe/wordcount/input/file01 Hello World, Bye World! $ bin/hadoop fs -cat /user/joe/wordcount/input/file02 Hello Hadoop, Goodbye to hadoop.
運行程序:
$ bin/hadoop jar wc.jar WordCount2 /user/joe/wordcount/input /user/joe/wordcount/output
輸出以下:
$ bin/hadoop fs -cat /user/joe/wordcount/output/part-r-00000 Bye 1 Goodbye 1 Hadoop, 1 Hello 2 World! 1 World, 1 hadoop. 1 to 1
經過 DistributedCache 來設置單詞過濾的策略:
$ bin/hadoop fs -cat /user/joe/wordcount/patterns.txt \. \, \! to
再次運行,此次增長了更多的選項:
$ bin/hadoop jar wc.jar WordCount2 -Dwordcount.case.sensitive=true /user/joe/wordcount/input /user/joe/wordcount/output -skip /user/joe/wordcount/patterns.txt
輸出以下:
$ bin/hadoop fs -cat /user/joe/wordcount/output/part-r-00000 Bye 1 Goodbye 1 Hadoop 1 Hello 2 World 2 hadoop 1
再次運行,此次去掉了大小寫敏感:
$ bin/hadoop jar wc.jar WordCount2 -Dwordcount.case.sensitive=false /user/joe/wordcount/input /user/joe/wordcount/output -skip /user/joe/wordcount/patterns.txt
輸出以下:
$ bin/hadoop fs -cat /user/joe/wordcount/output/part-r-00000 bye 1 goodbye 1 hadoop 2 hello 2 horld 2