)
1. 先說清楚Windows 上跑 Hadoop 偽分布式到底在解決什么問題我最早接觸 Hadoop 是在一臺只有 Windows 筆記本的環(huán)境下當時手里沒有任何服務(wù)器可用虛擬機跑兩三個節(jié)點又卡得厲害于是只能退而求其次在 Windows 本機搭一套 Hadoop 偽分布式。所謂偽分布式就是把 NameNode、DataNode、ResourceManager、NodeManager 這些角色全部塞在同一臺機器上各自以獨立的 Java 進程運行用本地磁盤模擬出“分布式”的存儲與計算結(jié)構(gòu)。它不算真正的集群但足夠把 HDFS 的讀寫流程、YARN 的資源調(diào)度、MapReduce 的作業(yè)提交鏈路完整走一遍。對于想搞明白 HDFS 副本機制、塊存儲原理、作業(yè)提交流程的人來說偽分布式的性價比極高——一臺電腦、一個 JDK、一個解壓即用的 Hadoop 發(fā)行包就能把整個生態(tài)的骨架跑通。這篇文章記錄的是我基于 Windows 系統(tǒng)從零部署 Hadoop 偽分布式的完整過程包括版本怎么選、目錄怎么規(guī)劃、四個配置文件怎么寫、格式化啟動時踩了哪些坑、YARN 上跑第一個 WordCount 作業(yè)時又卡在哪里。適合的人群很明確剛接觸大數(shù)據(jù)組件但又不想一上來就折騰虛擬機的同學、需要在本地快速復(fù)現(xiàn)某個 HDFS 或 MapReduce 行為的開發(fā)者、以及被 Linux 環(huán)境慣壞想看看 Windows 下到底多難纏的老手。我把每一步的判斷依據(jù)和失敗現(xiàn)場都寫下來了你照著做大概率能少走兩三個晚上的彎路。2. 方案選型Windows 原生、子系統(tǒng)還是容器2.1 偽分布式在 Windows 上的三種落地方式對比在動手之前我先把三條路都試了一遍結(jié)論是它們各有適用場景不存在誰絕對優(yōu)于誰。第一種是 Windows 原生部署直接下載 Hadoop 的二進制壓縮包解壓補上 Windows 平臺缺失的原生庫文件然后跑起來。第二種是裝一個 Linux 子系統(tǒng)在子系統(tǒng)里按標準 Linux 流程部署Windows 只作為宿主。第三種是用容器拉一個現(xiàn)成的 Hadoop 鏡像映射幾個端口就能訪問 Web UI。我當時的判斷依據(jù)是“學習目標”而不是“省事程度”。如果只是想看看 HDFS 的 Web 界面長什么樣、跑一個現(xiàn)成的示例作業(yè)容器方案十分鐘就能搞定。但如果目標是理解 Hadoop 啟動時到底讀了哪些配置、進程之間的通信端口是哪些、日志里的報錯分別指向哪個組件原生部署帶來的“痛感”反而是有價值的——每一個報錯都對應(yīng)一個真實存在的機制。我最終選了原生方案主要原因是它最貼近真實的生產(chǎn)環(huán)境配置方式四個 XML 文件怎么寫、環(huán)境變量怎么傳這些經(jīng)驗換到 Linux 集群上是通用的。方案上手耗時學習價值主要痛點適合人群Windows 原生2 到 4 小時高配置項全部親手寫缺原生庫、路徑空格、權(quán)限問題想吃透配置細節(jié)的人Linux 子系統(tǒng)1 到 2 小時中高接近標準流程文件系統(tǒng)互通、內(nèi)存占用有一定 Linux 基礎(chǔ)的人容器鏡像10 到 30 分鐘低黑盒程度高配置改動需重建鏡像只想驗證功能的人需要說明的是原生方案有一個繞不開的前提Hadoop 的很多腳本和原生庫是按類 Unix 環(huán)境編寫的Windows 上沒有對應(yīng)實現(xiàn)。所以社區(qū)里一直有人維護一套 Windows 平臺的補充二進制文件主要包含winutils.exe和hadoop.dll兩個文件。前者負責模擬文件權(quán)限、創(chuàng)建目錄等操作后者是本地庫的 Windows 編譯版本。缺少它們程序不一定立刻報錯但會在某些節(jié)點突然拋出本地庫加載失敗這個后面會專門講。2.2 為什么偽分布式不需要配置免密登錄很多教程一上來就讓你裝 SSH、配免密那是針對完全分布式多機環(huán)境的。偽分布式下所有進程都在本機Windows 原生部署時啟動腳本本身就不走 SSH 通道Windows 自帶的啟動腳本是.cmd后綴的批處理文件直接start拉起各個 Java 進程。所以如果你看到某篇教程讓你在 Windows 上裝 OpenSSH、生成密鑰對、把公鑰追加到授權(quán)文件里可以直接跳過——那套流程解決的是跨機器啟動的問題偽分布式用不上。我一開始也照做了結(jié)果白白花了一個多小時最后發(fā)現(xiàn)啟動腳本壓根不讀這些。真正需要搞清楚的是啟動腳本的調(diào)用鏈start-dfs.cmd會依次拉起 NameNode 和 DataNodestart-yarn.cmd會拉起 ResourceManager 和 NodeManager每個進程背后都是一個java命令參數(shù)里的內(nèi)存大小、類路徑都由hadoop-env.cmd和四個 XML 配置文件決定。理解了這條鏈路后面排查啟動失敗就有方向了——先看窗口有沒有一閃而過再看日志目錄里對應(yīng)組件的.log文件末尾幾十行。2.3 版本搭配這件事容錯率比想象中低Hadoop 和 JDK 的版本搭配是這套環(huán)境里最容易埋雷的地方。Hadoop 3.x 系列官方明確支持的 JDK 版本是 8 和 11用 JDK 17 及以上會直接撞上模塊訪問限制啟動時報IllegalAccessError或者反射相關(guān)的異常改配置也救不回來。我自己用的是 JDK 8 的一個較新小版本穩(wěn)定跑通。Hadoop 本身選的是 3.3 系列的一個穩(wěn)定小版本這個系列對 Windows 的兼容性資料最多遇到問題容易搜到同類案例。還有一個容易被忽略的點JDK 的安裝路徑。默認安裝到C:\Program Files\Java\...這種帶空格的目錄下Hadoop 的批處理腳本在拼接類路徑時對空格處理得很粗糙容易出現(xiàn)“找不到主類”或者路徑被截斷的情況。我的做法是把 JDK 單獨裝到一個沒有空格、沒有中文的短路徑下比如C:\Java\jdk8后面所有配置都指向這個路徑。同理Hadoop 的解壓目錄我也放在了根目錄下的短路徑里比如D:\hadoop\hadoop-3.3.x。這一步多花兩分鐘后面能省掉一堆莫名其妙的報錯。3. 環(huán)境準備目錄規(guī)劃、環(huán)境變量與 Windows 補充庫3.1 目錄結(jié)構(gòu)怎么規(guī)劃才不給自己挖坑我見過不少人把 Hadoop 解壓到桌面或者下載文件夾里然后一路報錯到最后放棄。問題的根源在于 Hadoop 運行時會往自己所在的目錄寫日志、寫臨時文件如果路徑里有中文、空格或者權(quán)限受限比如系統(tǒng)盤的某些目錄進程就會在某個不起眼的環(huán)節(jié)掛掉。我習慣的目錄規(guī)劃是這樣的D:\hadoop\ ├── hadoop-3.3.x\ 解壓出來的發(fā)行包本體 │ ├── bin\ │ ├── etc\hadoop\ 四個配置文件都在這里 │ ├── logs\ 運行日志排錯第一現(xiàn)場 │ └── sbin\ 啟動停止腳本 └── data\ 所有運行時數(shù)據(jù)獨立于程序目錄 ├── tmp\ 臨時目錄 ├── namenode\ NameNode 元數(shù)據(jù) └── datanode\ DataNode 數(shù)據(jù)塊把數(shù)據(jù)和程序分開是我堅持的一個習慣。原因很實際想升級 Hadoop 版本時直接解壓新版本、改一下環(huán)境變量就行數(shù)據(jù)目錄原封不動想徹底重來一遍時只需要刪掉data目錄重新格式化程序本體不用動。data目錄一定要放在非系統(tǒng)盤因為 HDFS 寫入數(shù)據(jù)塊時會產(chǎn)生大量小文件系統(tǒng)盤容易被塞滿而且 Windows 對系統(tǒng)盤某些位置的寫入有額外限制。目錄建好之后還需要手工把data下的三個子目錄創(chuàng)建出來。雖然 Hadoop 在格式化時會自動創(chuàng)建但提前建好可以避免“父目錄不存在導致創(chuàng)建失敗”這類邊界問題尤其是當磁盤權(quán)限設(shè)置比較嚴格的時候。3.2 環(huán)境變量的三個關(guān)鍵項與實際作用Windows 上需要配置三組環(huán)境變量每一項都有明確用途不是隨便加的。第一項是JAVA_HOME指向 JDK 的根目錄不帶bin。這個變量的作用范圍比想象中大不只是 Hadoop 讀它很多 Java 生態(tài)的工具鏈都依賴它。配置成C:\Java\jdk8這種形式結(jié)尾不要帶反斜杠。第二項是HADOOP_HOME指向 Hadoop 解壓后的根目錄也就是包含bin、etc、sbin的那一層。這個變量是 Windows 批處理腳本定位自身的關(guān)鍵start-dfs.cmd內(nèi)部會用它拼接類路徑。如果沒配雙擊腳本會一閃而過什么提示都沒有。第三項是在Path里追加%HADOOP_HOME%\bin和%HADOOP_HOME%\sbin。加bin是為了能在任意目錄下敲hadoop、hdfs這些命令加sbin是為了能直接敲start-dfs、stop-yarn這類管理腳本。提示環(huán)境變量改完一定要關(guān)掉所有已打開的命令行窗口重新開一個舊的窗口讀的是舊環(huán)境。我吃過這個虧改完變量在當前窗口里敲hadoop version一直提示“不是內(nèi)部或外部命令”折騰半天才發(fā)現(xiàn)是窗口沒刷新。驗證方式很簡單新開一個命令行窗口敲hadoop version能打印出版本號、編譯信息、構(gòu)建時間就說明環(huán)境變量通了。如果這一步就失敗后面的所有操作都不用往下做先把這里解決掉。3.3 winutils.exe 和 hadoop.dllWindows 上繞不開的兩個文件這是 Windows 原生部署 Hadoop 最核心的一道坎。Hadoop 的部分功能依賴本地庫實現(xiàn)比如文件權(quán)限模擬、磁盤空間查詢、符號鏈接處理這些在 Linux 上有系統(tǒng)調(diào)用可以直接用Windows 上需要專門的編譯產(chǎn)物。社區(qū)長期有人維護針對各個 Hadoop 版本的 Windows 二進制包主要就是winutils.exe和hadoop.dll兩個文件。放置位置有講究winutils.exe放到%HADOOP_HOME%\bin目錄下和hadoop.cmd、hdfs.cmd這些批處理文件放在一起。hadoop.dll需要放到兩個地方一是%HADOOP_HOME%\bin二是C:\Windows\System32。放系統(tǒng)目錄這一步看起來粗暴但確實是最省事的做法因為 Java 通過系統(tǒng)路徑加載本地庫放在System32下能被穩(wěn)定找到。版本匹配這件事要特別注意。這些二進制文件需要和 Hadoop 主版本對應(yīng)跨大版本混用可能出現(xiàn)符號解析失敗。我用的 Hadoop 是 3.3 系列配套的 Windows 二進制包也選 3.3 系列的版本。如果你手頭只有 3.2 或 3.1 的包先試試能不能跑如果啟動時拋出UnsatisfiedLinkError或者NativeIO相關(guān)的異常那就說明不匹配得去找對應(yīng)版本。配完這兩個文件還要在hadoop-env.cmd里顯式指定HADOOP_HOME因為 Windows 上批處理腳本有時讀不到系統(tǒng)環(huán)境變量尤其是從快捷方式啟動的時候。我一般會在文件開頭補一行set HADOOP_HOMED:\hadoop\hadoop-3.3.x這一步看起來冗余但它能避免“明明配了環(huán)境變量卻提示找不到 winutils”的詭異情況。4. 四個配置文件逐行拆解每一項都在控制什么4.1 core-site.xml整個集群的入口地址core-site.xml是所有配置里最基礎(chǔ)的一個它定義的是整個 Hadoop 運行時的通用參數(shù)其中最關(guān)鍵的只有兩三項。configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name valuefile:///D:/hadoop/data/tmp/value /property property nameio.file.buffer.size/name value131072/value /property /configurationfs.defaultFS決定了所有 HDFS 客戶端默認連接的地址格式是hdfs://主機名:端口。端口我用了 9000這是傳統(tǒng)習慣值也可以改成別的空閑端口但改了之后所有引用這個地址的地方都要同步改。主機名寫localhost是最簡單的做法因為偽分布式只在本機通信不需要解析真實主機名。hadoop.tmp.dir這一項特別重要它是所有臨時文件的根目錄NameNode 的元數(shù)據(jù)、DataNode 的中間數(shù)據(jù)、YARN 容器的工作目錄都可能落在它下面。如果不顯式配置Hadoop 會默認寫到系統(tǒng)的臨時目錄里這個位置在 Windows 上經(jīng)常被清理而且重啟后可能被系統(tǒng)清空導致元數(shù)據(jù)和數(shù)據(jù)不一致下次啟動直接報錯。所以我強烈建議把它指向自己規(guī)劃的數(shù)據(jù)目錄。路徑的寫法需要注意Windows 路徑要用正斜杠并且前面加file:///寫成file:///D:/hadoop/data/tmp這種形式。寫成反斜杠或者漏掉file:///前綴解析時會出錯。這個細節(jié)我在第一次配置時就寫錯了報錯信息非常隱晦只是提示某個路徑不存在看不出是格式問題。io.file.buffer.size是讀寫緩沖區(qū)大小默認值偏小調(diào)到 128KB 能提升一點大文件讀寫效率。這個參數(shù)不是必填項屬于順手優(yōu)化配置不配置都不影響啟動。4.2 hdfs-site.xml副本、目錄與權(quán)限hdfs-site.xml管的是 HDFS 自身的行為偽分布式下最重要的幾項是副本數(shù)、元數(shù)據(jù)和數(shù)據(jù)目錄、權(quán)限開關(guān)。configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name valuefile:///D:/hadoop/data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///D:/hadoop/data/datanode/value /property property namedfs.permissions.enabled/name valuefalse/value /property property namedfs.namenode.http-address/name valuelocalhost:9870/value /property /configurationdfs.replication默認是 3意味著每份數(shù)據(jù)要存三個副本。偽分布式只有一臺機器、一個 DataNode根本湊不出三個副本HDFS 會一直處于“副本不足”狀態(tài)頁面上永遠掛著紅色的警告。改成 1 是必然選擇既符合單節(jié)點的物理現(xiàn)實也避免了后臺反復(fù)做副本復(fù)制帶來的資源浪費。dfs.namenode.name.dir和dfs.datanode.data.dir分別指定元數(shù)據(jù)目錄和數(shù)據(jù)塊目錄。這兩個目錄必須分開絕對不能指向同一個路徑否則格式化時會產(chǎn)生混亂。我把它們放在data下的不同子目錄里互不干擾。這兩個路徑同樣要用file:///前綴加正斜杠的寫法。dfs.permissions.enabled設(shè)為false是 Windows 下的實用妥協(xié)。HDFS 有一套類似 POSIX 的權(quán)限模型但 Windows 的文件系統(tǒng)沒有對應(yīng)的權(quán)限位winutils.exe只是做了模擬很多情況下模擬出來的結(jié)果和預(yù)期不一致容易導致“明明有權(quán)限卻提示拒絕訪問”。學習環(huán)境下關(guān)掉權(quán)限檢查能省掉大量無謂的排查時間。真要做權(quán)限相關(guān)實驗時再打開那時你對機制已經(jīng)有概念了知道該從哪個方向查。dfs.namenode.http-address指定 Web 管理界面的監(jiān)聽地址Hadoop 3.x 的默認端口是 98702.x 時代是 50070。配置成localhost:9870之后啟動成功就能在瀏覽器里打開http://localhost:9870看到 HDFS 的概覽頁、文件瀏覽、DataNode 列表等信息。這個頁面是驗證部署是否成功最直觀的方式。4.3 mapred-site.xml 與 yarn-site.xml計算框架的接線這兩個文件是一對前者告訴 MapReduce 作業(yè)往哪兒提交后者告訴 YARN 怎么接收和運行這些作業(yè)。configuration property namemapreduce.framework.name/name valueyarn/value /property /configurationmapreduce.framework.name設(shè)成yarn表示 MapReduce 作業(yè)跑在 YARN 上。另一個可選值是local本地模式不需要 YARN但那樣就失去了練習資源調(diào)度的意義。偽分布式下選yarn才有完整的作業(yè)提交鏈路客戶端連 ResourceManager、申請容器、NodeManager 拉起任務(wù)進程、任務(wù)跟 HDFS 交換數(shù)據(jù)。yarn-site.xml稍微復(fù)雜一點configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuelocalhost/value /property property nameyarn.nodemanager.vmem-check-enabled/name valuefalse/value /property property nameyarn.nodemanager.pmem-check-enabled/name valuefalse/value /property /configurationyarn.nodemanager.aux-services這一項是必須的它注冊了 MapReduce 的 Shuffle 服務(wù)。Map 階段的輸出要經(jīng)過 Shuffle 傳給 Reduce 階段這個輔助服務(wù)負責那部分數(shù)據(jù)傳輸。不配這一項作業(yè)提交上去會一直卡在 map 或者 reduce 階段日志里提示 Shuffle 服務(wù)不可用。yarn.resourcemanager.hostname指定 ResourceManager 所在的主機。偽分布式寫localhost就行。有些教程會寫具體的主機名那樣一旦計算機名變了就要改配置不如直接用localhost省心。后面兩個內(nèi)存檢查開關(guān)我建議一并關(guān)掉。YARN 默認會對每個容器的虛擬內(nèi)存和物理內(nèi)存做檢查超出限制就殺掉容器。Windows 下這個檢查的精度很差經(jīng)常在內(nèi)存完全夠用的情況下誤判把任務(wù)容器直接干掉表現(xiàn)為作業(yè)莫名其妙失敗、日志里寫著“Container killed”。關(guān)掉之后內(nèi)存分配由 Java 堆參數(shù)控制行為更可控。這不是生產(chǎn)環(huán)境該有的做法但在本機學習環(huán)境里能省掉很多干擾。4.4 hadoop-env.cmdJava 路徑與內(nèi)存閾值hadoop-env.cmd在etc\hadoop目錄下它的作用是給所有啟動腳本注入環(huán)境變量。最關(guān)鍵的只有一行set JAVA_HOMEC:\Java\jdk8注意這里用的是set而不是setx作用范圍僅限當前腳本及其子進程不會污染系統(tǒng)環(huán)境變量。這行配置寫錯啟動時會直接報“JAVA_HOME 未正確設(shè)置”。還有幾個可選的內(nèi)存參數(shù)值得順手調(diào)一下。Windows 機器內(nèi)存普遍不小但 Hadoop 默認給 NameNode 分配的內(nèi)存偏保守處理大量小文件時容易觸發(fā)頻繁 GC??梢栽谕晃募锛觭et HADOOP_HEAPSIZE_MAX1024 set HADOOP_NAMENODE_OPTS-Xmx1024m -Xms1024m set HADOOP_DATANODE_OPTS-Xmx512m -Xms512mHADOOP_HEAPSIZE_MAX是全局上限單位和 Linux 上一樣用 MB。NameNode 因為要維護整個文件系統(tǒng)的元數(shù)據(jù)內(nèi)存給大一點DataNode 相對輕量512MB 夠用ResourceManager 和 NodeManager 也用默認值即可。這些值不用給太夸張本機學習環(huán)境把總內(nèi)存控制在 3GB 以內(nèi)比較穩(wěn)妥剩下的留給系統(tǒng)和其他軟件。5. 格式化與啟動第一次跑通的完整過程5.1 格式化 NameNode 的正確姿勢配置寫完第一件事是格式化 NameNode。這一步會在dfs.namenode.name.dir指定的目錄里初始化元數(shù)據(jù)生成current目錄和fsimage文件。命令是hdfs namenode -format執(zhí)行后會輸出一大段日志最后幾行如果有Storage directory ... has been successfully formatted就說明成功了。如果看到Cannot lock storage說明該目錄已經(jīng)被占用可能是之前的進程沒退干凈或者已經(jīng)格式化過。這種情況下不要硬來先把所有 Hadoop 進程確認停止再檢查目錄里有沒有殘留文件。注意格式化只能做一次。重復(fù)格式化會把 NameNode 的集群 ID 重新生成而 DataNode 目錄里存的還是舊的集群 ID兩者對不上DataNode 就起不來日志里會提示ClusterId mismatch。真遇到了解決辦法是刪掉data目錄下的namenode和datanode兩個子目錄重新格式化代價是之前存進 HDFS 的數(shù)據(jù)全部丟失。學習環(huán)境下這不算事但一定要知道這個因果關(guān)系否則會對著報錯猜很久。格式化完成之后namenode目錄下應(yīng)該出現(xiàn)current子目錄里面有VERSION、fsimage_0000000000000000000這類文件。可以去確認一下這也是判斷格式化是否真的生效的依據(jù)。5.2 啟動腳本與進程驗證啟動分兩步。第一步起 HDFSstart-dfs.cmd這個批處理會打開兩個新的命令行窗口一個跑 NameNode一個跑 DataNode。窗口里會滾動大量日志正常情況下最后會停在某個狀態(tài)。這兩個窗口不能關(guān)關(guān)了進程就終止了。我習慣把它們最小化放著。第二步起 YARNstart-yarn.cmd同樣會打開兩個窗口分別是 ResourceManager 和 NodeManager。四個窗口都正常滾動日志、沒有立刻退出說明進程都起來了。如果某個窗口一閃就沒了說明對應(yīng)的進程啟動失敗去logs目錄找對應(yīng)組件的日志文件看末尾的異常堆棧。驗證進程是否真的活著可以用jps命令。這個命令在 JDK 的bin目錄下輸出類似12345 NameNode 12678 DataNode 13021 ResourceManager 13345 NodeManager 14567 Jps五個進程對應(yīng)上HDFS 和 YARN 的關(guān)鍵角色就齊了。如果少了哪個對應(yīng)的窗口一定已經(jīng)關(guān)閉了。這一步是我每次重裝環(huán)境時必做的確認比看窗口滾動日志更直觀。5.3 Web 界面與命令行雙重驗證進程起來之后打開瀏覽器訪問http://localhost:9870能看到 HDFS 的管理界面。重點看兩個地方一是首頁的Summary部分Live Nodes應(yīng)該是 1表示有一個 DataNode 在線二是Utilities菜單下的Browse the file system能列出 HDFS 根目錄的內(nèi)容說明元數(shù)據(jù)服務(wù)正常。YARN 的界面在http://localhost:8088首頁能看到集群的資源總量、已用資源、正在運行的作業(yè)數(shù)量。剛啟動時作業(yè)數(shù)是 0資源占用接近 0這是正常的。命令行這邊先建一個目錄、傳一個文件上去hdfs dfs -mkdir -p /user/test/input hdfs dfs -ls / hdfs dfs -put D:\local\somefile.txt /user/test/input/ hdfs dfs -cat /user/test/input/somefile.txt這幾條命令能跑通說明 HDFS 的讀寫鏈路完全正常。-ls能列出目錄-put能把本地文件寫到 HDFS-cat能把內(nèi)容讀回來三個方向都驗證到了。5.4 跑通第一個 WordCountWordCount 是驗證 MapReduce 鏈路的標準動作。Hadoop 發(fā)行包里自帶示例 JAR路徑一般在share\hadoop\mapreduce\hadoop-mapreduce-examples-版本.jar。先準備輸入數(shù)據(jù)隨便造兩個文本文件里面放一些重復(fù)的單詞傳到 HDFS 的一個目錄里hdfs dfs -mkdir -p /user/test/wc/input hdfs dfs -put D:\local\a.txt /user/test/wc/input/ hdfs dfs -put D:\local\b.txt /user/test/wc/input/然后提交作業(yè)。注意輸出目錄必須是 HDFS 上不存在的路徑否則作業(yè)會直接失敗提示輸出目錄已存在。這是 MapReduce 的設(shè)計約定為的是防止覆蓋已有結(jié)果。hadoop jar %HADOOP_HOME%\share\hadoop\mapreduce\hadoop-mapreduce-examples-3.3.x.jar wordcount /user/test/wc/input /user/test/wc/output提交之后控制臺會不斷打印進度百分比。同時打開 YARN 的 8088 頁面能看到一個應(yīng)用從ACCEPTED變成RUNNING再變成FINISHED。整個過程走完用下面的命令看結(jié)果hdfs dfs -cat /user/test/wc/output/part-r-00000輸出的每行是“單詞 出現(xiàn)次數(shù)”按字母序排列??吹竭@個結(jié)果說明 HDFS、YARN、MapReduce 三層已經(jīng)全部打通。6. 常見問題速查與排查思路實錄6.1 啟動階段的高頻報錯與定位方法啟動階段的問題占了全部問題的一大半我把遇到過的整理成一張表方便對照排查?,F(xiàn)象大概率原因處理方式窗口一閃而過無任何輸出HADOOP_HOME沒配或路徑帶空格在命令行里手動執(zhí)行腳本看報錯提示 JAVA_HOME 未正確設(shè)置hadoop-env.cmd里的路徑寫錯確認路徑存在且不帶引號NameNode 啟動后立刻退出元數(shù)據(jù)目錄被舊數(shù)據(jù)占用清空data目錄重新格式化DataNode 起來但 Live Nodes 為 0ClusterId 不一致清空數(shù)據(jù)目錄重新格式化提示找不到 winutils補充二進制未放到bin目錄補文件并檢查HADOOP_HOMEUnsatisfiedLinkErrorhadoop.dll未放系統(tǒng)目錄復(fù)制到System32后重啟命令行端口被占用9000 或 9870 被其他程序占用換端口或結(jié)束占用進程計算機名含中文導致注冊失敗主機名解析異常改用localhost或修改主機名“窗口一閃而過”這個現(xiàn)象最讓人抓狂因為看不到任何錯誤信息。我的應(yīng)對辦法是不雙擊運行而是先開一個命令行窗口cd到sbin目錄直接敲腳本名回車。這樣報錯信息會留在窗口里一眼就能看到是哪一行出的問題。這個技巧適用于所有.cmd批處理腳本。端口占用也值得一提。9000 是 HDFS 的 RPC 端口如果本機裝了其他用 9000 端口的服務(wù)NameNode 就綁不上。查占用用netstat -ano | findstr :9000能拿到進程號再用任務(wù)管理器找到對應(yīng)程序。9870 是 Web 端口沖突概率低一些但也不是沒有。真沖突了改hdfs-site.xml里的端口配置就行只影響 Web 訪問不影響數(shù)據(jù)讀寫。6.2 運行作業(yè)時才暴露的問題有些問題在啟動階段完全看不出來直到提交作業(yè)才炸出來而且報錯信息往往指向不明顯的地方。最常見的是Container exited with a non-zero exit code 1。這個報錯本身幾乎不提供任何信息只說容器退出碼非零。真正的線索在 NodeManager 的日志里搜這個容器 ID能找到它拉起的具體命令和標準錯誤輸出。我遇到過的原因有三種一是類路徑拼接在 Windows 下用了錯誤的路徑分隔符需要檢查mapreduce.application.classpath配置二是工作目錄權(quán)限不足NodeManager 無法在臨時目錄下創(chuàng)建容器目錄三是hadoop.dll沒被容器進程找到因為容器是新的進程環(huán)境變量繼承可能不完整。另一個是作業(yè)長時間卡在ACCEPTED狀態(tài)一直不進入RUNNING。這說明 ResourceManager 收到了作業(yè)但沒有分配到容器。原因通常是 NodeManager 沒注冊上或者可用資源不足。去 8088 頁面看Cluster Nodes列表如果為空說明 NodeManager 根本沒連上 ResourceManager回去檢查yarn-site.xml里的主機名配置和 NodeManager 窗口的日志。如果列表有節(jié)點但資源顯示為 0那是內(nèi)存參數(shù)配得太極端把這個節(jié)點的可分配內(nèi)存擠沒了。還有一種比較隱蔽作業(yè)能跑完但結(jié)果不對比如輸出文件是空的。這種情況先看 Map 階段的輸入記錄數(shù)是不是 0。如果是 0說明輸入路徑?jīng)]讀到文件可能是路徑寫錯也可能是文件權(quán)限問題。我在關(guān)掉權(quán)限檢查之前遇到過一次本地傳上去的文件所有者是當前 Windows 用戶名但作業(yè)運行時的用戶名解析出了偏差導致讀不到文件。關(guān)掉dfs.permissions.enabled之后就沒再出現(xiàn)過。6.3 停止、重啟與二次啟動的注意事項停止的順序有講究一般是先停 YARN 再停 HDFSstop-yarn.cmd stop-dfs.cmd反過來停也不是不行但 YARN 上如果還有運行中的作業(yè)直接停 HDFS 會讓作業(yè)以很奇怪的方式失敗日志里一堆連接異??雌饋硐袷桥渲脝栴}實際上只是停止順序?qū)е碌?。二次啟動時最容易踩的坑是“沒等上一個進程完全退出就重新啟動”。Windows 上進程退出有時會有延遲端口還沒釋放新進程綁不上報Address already in use。我的做法是停完之后用jps確認四個進程都不在了再執(zhí)行啟動。如果jps顯示還有殘留去任務(wù)管理器里結(jié)束對應(yīng)的java.exe進程。還有一個細節(jié)如果某次啟動失敗data目錄里可能會留下鎖文件或者不完整的臨時文件導致下一次啟動也失敗。判斷方法是看 NameNode 日志里有沒有Cannot lock storage或者Directory is already locked這類關(guān)鍵詞。遇到了把data目錄下的tmp子目錄清空通常就能恢復(fù)不需要動namenode和datanode目錄也就不會丟數(shù)據(jù)。提示養(yǎng)成一個習慣每次改動配置文件之前先備份一份。Windows 上排查問題時經(jīng)常要改配置試錯改來改去就忘了最初是什么樣。我一般在etc\hadoop下建一個bak目錄把改之前的四個 XML 文件復(fù)制進去出問題了一鍵還原比憑記憶回滾靠譜得多。7. 一些只有實際搭過才會有的體會整套環(huán)境搭下來我最深的感受是Windows 上跑 Hadoop 的難點不在 Hadoop 本身而在兩個系統(tǒng)的“接口層”。配置文件怎么寫、參數(shù)是什么意思這些看文檔就能明白真正耗時間的是路徑格式、權(quán)限模擬、本地庫加載這些邊界地帶它們不在任何一份官方文檔里只能靠一次次報錯去試。所以我的建議是第一次搭的時候把每個報錯都記下來包括完整的報錯文本和你最終的解決方式形成自己的排查清單。下次換機器或者換版本時這份清單能讓你在半小時內(nèi)定位問題而不是重新經(jīng)歷一遍摸索。另一個體會是關(guān)于“夠用就好”這個判斷。偽分布式下很多人會照搬生產(chǎn)環(huán)境的參數(shù)副本數(shù)設(shè) 3、內(nèi)存給 8G、各種超時時間拉到很長結(jié)果本機資源被吃光反而跑不動。學習環(huán)境的配置應(yīng)該反過來做減法副本數(shù)降到 1、內(nèi)存控制在小幾百兆、能關(guān)的檢查都關(guān)掉目標是讓鏈路跑通、讓機制看得見而不是追求性能指標。等你把流程走順了再逐項加回去觀察每項參數(shù)帶來的變化這個過程本身就是很好的學習。最后分享一個我在排查時常用的小技巧不確定某個配置項有沒有真正生效時用hdfs getconf -confKey 配置項名稱直接查運行時的實際值。比如hdfs getconf -confKey dfs.replication返回的就是當前生效的副本數(shù)。這個命令比翻配置文件可靠因為它讀的是進程實際加載后的結(jié)果能排除“改了文件但沒重啟”“改錯了文件”這類低級失誤。搭環(huán)境的過程中大部分所謂的“疑難問題”其實都是配置沒生效先用這個命令確認一遍能排除掉一半的可能性。