避坑指南)
簡介Apache Hadoop 3.3.3 官方發(fā)行包hadoop-3.3.3.tar.gz面向大數(shù)據(jù)初學(xué)者、分布式系統(tǒng)開發(fā)者與運維人員用于搭建可靠、可擴(kuò)展的分布式計算與存儲環(huán)境。該框架以簡單編程模型支持跨集群處理海量數(shù)據(jù)集可從單機(jī)平滑擴(kuò)展至數(shù)千節(jié)點并在應(yīng)用層實現(xiàn)故障檢測與高可用適合學(xué)習(xí) HDFS、MapReduce、YARN 核心組件及本地庫調(diào)用。壓縮包約 615.16MB共 22536 個文件以 18870 個 html 文檔、763 個 jpg 與 762 個 gif 圖示、488 個 css 樣式為主輔以 449 個 jar 依賴、124 個 xml 配置、75 個 sh 腳本及 22 個 gz 歸檔并包含 libhadoop、libhdfs、libnativetask 等本地庫文件覆蓋文檔、配置、腳本與原生依賴。已有 644 人學(xué)習(xí)下載適合對照官方文檔完成環(huán)境部署、組件調(diào)試與源碼結(jié)構(gòu)梳理。1. Apache Hadoop 3.3.3 單機(jī)與偽分布式落地從 tar.gz 到能跑 MapReduce 的最小閉環(huán)拿到hadoop-3.3.3.tar.gz這個包的人十有八九卡在同一個地方解壓完、配完環(huán)境變量、start-dfs.sh一敲要么 NameNode 起不來要么 Web UI 打不開要么跑個 WordCount 報一堆Connection refused。Apache Hadoop 3.3.3 是 3.3.x 線里被大量課程設(shè)計和生產(chǎn)測試環(huán)境沿用的版本它的目錄結(jié)構(gòu)、默認(rèn)端口、配置文件位置和 2.x 差異不小網(wǎng)上抄來的老教程直接套會翻車。這篇筆記只干一件事把 hadoop-3.3.3.tar.gz 從零解壓到跑通第一個 MapReduce 作業(yè)的完整路徑講清楚包括偽分布式搭建、參數(shù)怎么設(shè)、日志去哪看、報錯怎么排。適合兩類人一是要交 hadoop 課程設(shè)計、需要本地跑通集群的學(xué)生二是想在 Windows 下用 IDEA 連遠(yuǎn)程 Hadoop 做開發(fā)、但被環(huán)境折騰到懷疑人生的工程師。單機(jī)和偽分布式是后面一切集群搭建的地基地基沒打牢后面整合 ZooKeeper、Tez、上 Docker 都是空中樓閣。2. 先搞清楚 3.3.3 這個包里的東西目錄、端口與運行模式2.1 解壓后每個目錄是干什么的很多人解壓完就急著配環(huán)境變量其實先花五分鐘把目錄結(jié)構(gòu)看一遍后面排錯能省一半時間。hadoop-3.3.3.tar.gz解壓出來的根目錄下真正天天打交道的是這幾個目錄作用排錯時的用途bin/客戶端命令如hdfs、hadoop、yarn執(zhí)行命令報錯先看這里腳本sbin/集群管理腳本如start-dfs.sh、stop-yarn.sh啟停服務(wù)用普通用戶別亂改etc/hadoop/全部配置文件所在地90% 的啟動失敗都在這lib/依賴 jar 包缺 jar 報 ClassNotFound 時查logs/運行日志服務(wù)起不來第一現(xiàn)場share/hadoop/各模塊的 jar 和示例跑官方 example 用關(guān)鍵點bin和sbin是兩套東西。hadoop fs -ls /用的是bin/hadoop而start-dfs.sh在sbin里。新手最容易犯的錯是把sbin加進(jìn) PATH 后以為萬事大吉結(jié)果hadoop命令找不到因為bin沒加。2.2 三個核心配置文件和它們的最小改動Hadoop 3.3.3 的配置全部在etc/hadoop/下偽分布式只需要動三個文件。先說清楚每個文件管什么再給最小配置。core-site.xml管全局最重要的是文件系統(tǒng)入口地址。偽分布式下 NameNode 的 RPC 端口默認(rèn)是 80202.x 時代是 9000很多老教程還在寫 9000這是典型翻車點configuration property namefs.defaultFS/name valuehdfs://localhost:8020/value /property property namehadoop.tmp.dir/name value/opt/hadoop-3.3.3/tmp/value /property /configurationhadoop.tmp.dir必須顯式指定。默認(rèn)它落在/tmp下機(jī)器一重啟數(shù)據(jù)全沒NameNode 格式化過的元數(shù)據(jù)丟失再啟動就報NameNode is not formatted。這是血淚經(jīng)驗別省這一行。hdfs-site.xml管 HDFS 副本和目錄。偽分布式只有一個 DataNode副本數(shù)必須改成 1否則永遠(yuǎn)處于副本不足的告警狀態(tài)configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/opt/hadoop-3.3.3/data/namenode/value /property property namedfs.datanode.data.dir/name value/opt/hadoop-3.3.3/data/datanode/value /property /configurationmapred-site.xml和yarn-site.xml決定 MapReduce 跑在什么框架上。3.3.3 默認(rèn)用 YARN所以兩個都要配!-- mapred-site.xml -- configuration property namemapreduce.framework.name/name valueyarn/value /property /configuration !-- yarn-site.xml -- configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configurationyarn.nodemanager.aux-services的值是mapreduce_shuffle不是mapreduce.shuffle中間是下劃線。這個拼寫錯誤會讓 NodeManager 起來但作業(yè)卡在 ACCEPTED 狀態(tài)不動日志里能看到 shuffle 服務(wù)注冊失敗。2.3 環(huán)境變量和 Java 版本這道坎Hadoop 3.3.3 編譯時用的是 Java 8用 Java 11 或 17 跑會出現(xiàn)各種IllegalAccessError和模塊反射問題。最穩(wěn)的做法是裝 JDK 8然后在etc/hadoop/hadoop-env.sh里顯式指定export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export HDFS_NAMENODE_USERroot export HDFS_DATANODE_USERroot export HDFS_SECONDARYNAMENODE_USERroot export YARN_RESOURCEMANAGER_USERroot export YARN_NODEMANAGER_USERroot后面那幾行*_USER是 3.x 新增的。3.x 的啟動腳本會檢查這些變量不設(shè)的話start-dfs.sh直接報ERROR: Attempting to operate on hdfs namenode as root but there is no HDFS_NAMENODE_USER defined。這是 3.x 和 2.x 最大的啟動差異老教程里根本沒有。環(huán)境變量層面~/.bashrc里加export HADOOP_HOME/opt/hadoop-3.3.3 export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoopHADOOP_CONF_DIR在 Windows 下用 IDEA 連遠(yuǎn)程集群時是必須的本地開發(fā)環(huán)境靠它找到配置。3. 從格式化到跑通 WordCount偽分布式搭建的完整命令鏈3.1 格式化 NameNode 與啟動順序配置改完第一步是格式化。注意格式化只能做一次重復(fù)格式化會導(dǎo)致 DataNode 的 clusterID 和 NameNode 對不上DataNode 拒絕啟動。# 格式化 NameNode生成元數(shù)據(jù) hdfs namenode -format # 啟動 HDFSNameNode DataNode SecondaryNameNode start-dfs.sh # 啟動 YARNResourceManager NodeManager start-yarn.sh啟動順序有講究先 HDFS 后 YARN。YARN 的 NodeManager 啟動時會向 HDFS 寫日志聚合目錄HDFS 沒起來它就一直重試。反過來先啟 YARN 再啟 HDFS雖然最終也能起來但日志里一堆重試告警看著心慌。啟動后用jps驗證進(jìn)程。正常偽分布式應(yīng)該有 5 個進(jìn)程jps # 期望輸出 # NameNode # DataNode # SecondaryNameNode # ResourceManager # NodeManager少任何一個去logs/下找對應(yīng).log文件。比如 NameNode 沒起來看logs/hadoop-user-namenode-hostname.log最后 50 行基本能定位問題。3.2 Web UI 端口與驗證方法3.3.3 的默認(rèn) Web 端口和 2.x 不同這是另一個高頻翻車點服務(wù)3.3.3 默認(rèn)端口2.x 舊端口NameNode UI987050070ResourceManager UI80888088DataNode UI986450075SecondaryNameNode UI986850090訪問http://localhost:9870能看到 HDFS 的 Overview 頁面說明 NameNode 正常。如果瀏覽器打不開但jps有進(jìn)程先檢查防火墻再確認(rèn)core-site.xml里fs.defaultFS的端口和實際監(jiān)聽端口一致。用netstat -tlnp | grep 9870看端口有沒有真的在聽。3.3 跑通第一個 MapReduceWordCount 全流程驗證集群能不能干活最直接的就是跑官方自帶的 WordCount。整個過程分四步造數(shù)據(jù)、傳 HDFS、跑作業(yè)、看結(jié)果。# 1. 本地造一個測試文件 echo hello hadoop hello mapreduce hello yarn /tmp/word.txt echo hadoop hdfs namenode datanode /tmp/word.txt # 2. 在 HDFS 建輸入目錄并上傳 hdfs dfs -mkdir -p /input hdfs dfs -put /tmp/word.txt /input/ # 3. 確認(rèn)上傳成功 hdfs dfs -ls /input hdfs dfs -cat /input/word.txt # 4. 跑 WordCount輸出到 /output hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.3.jar \ wordcount /input /output # 5. 查看結(jié)果 hdfs dfs -cat /output/part-r-00000第 4 步的 jar 包路徑是固定的hadoop-mapreduce-examples-3.3.3.jar里的版本號必須和你的包一致。跑的時候終端會刷一堆INFO日志那是正常的真正要看的是最后有沒有Job ... completed successfully。如果卡在map 0% reduce 0%超過兩分鐘八成是 YARN 的容器分配有問題去 ResourceManager UI 的 Applications 頁面看作業(yè)狀態(tài)或者翻logs/hadoop-user-nodemanager-hostname.log。結(jié)果里每個單詞后面跟一個數(shù)字hello 3、hadoop 3這種。能跑出這個說明 HDFS 讀寫、YARN 調(diào)度、MapReduce 執(zhí)行整條鏈路都通了偽分布式搭建就算成功。4. Windows 下用 IDEA 連遠(yuǎn)程 Hadoop 開發(fā)環(huán)境配置與第一個作業(yè)4.1 Windows 端必須補(bǔ)的 winutils 和依賴Windows 下用 IDEA 寫 MapReduce 有個繞不開的坑Hadoop 的本地庫是 Linux 的.soWindows 上跑會報Could not locate executable null\bin\winutils.exe。解決辦法是下載對應(yīng)版本的winutils.exe和hadoop.dll放到一個目錄里比如D:\hadoop\bin然后設(shè)環(huán)境變量# Windows 系統(tǒng)環(huán)境變量里加 HADOOP_HOMED:\hadoop PATH%PATH%;%HADOOP_HOME%\bin同時在 IDEA 的 Run Configuration 里加 VM 參數(shù)-Dhadoop.home.dirD:\hadoopwinutils.exe的版本要和 Hadoop 3.3.3 對應(yīng)用 2.x 的 winutils 配 3.3.3 會出現(xiàn)權(quán)限相關(guān)的詭異報錯。這個文件本身不參與計算只是讓 Hadoop 在 Windows 上能調(diào)用本地文件系統(tǒng)權(quán)限接口屬于典型的黑匣子依賴。4.2 Maven 依賴與連接遠(yuǎn)程集群的配置IDEA 里建 Maven 項目pom.xml加這幾個依賴版本統(tǒng)一用 3.3.3dependencies dependency groupIdorg.apache.hadoop/groupId artifactIdhadoop-client/artifactId version3.3.3/version /dependency dependency groupIdorg.apache.hadoop/groupId artifactIdhadoop-common/artifactId version3.3.3/version /dependency dependency groupIdorg.apache.hadoop/groupId artifactIdhadoop-hdfs/artifactId version3.3.3/version /dependency /dependencieshadoop-client是個聚合包會把 mapreduce、yarn、common 都拉進(jìn)來一般夠用。如果只做 HDFS 操作可以只引hadoop-common和hadoop-hdfs減少依賴沖突。連接遠(yuǎn)程集群時把集群的core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml拷到項目的src/main/resources下代碼里不用再new Configuration()手動設(shè)它會自動讀。但要注意fs.defaultFS里的localhost要改成集群的真實 IP 或主機(jī)名否則本地代碼會去連本地的 8020連不上。4.3 一個能直接跑的 HDFS 操作示例下面這段代碼演示從本地讀文件、上傳到 HDFS、再讀回來是 Windows 下驗證環(huán)境是否通的最小閉環(huán)import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; public class HdfsDemo { public static void main(String[] args) throws Exception { // 自動加載 resources 下的配置文件 Configuration conf new Configuration(); // 顯式指定避免讀到本地默認(rèn)值 conf.set(fs.defaultFS, hdfs://192.168.1.100:8020); FileSystem fs FileSystem.get(conf); // 上傳本地文件到 HDFS Path local new Path(D:/data/test.txt); Path remote new Path(/user/test/test.txt); fs.copyFromLocalFile(local, remote); System.out.println(上傳完成); // 讀取 HDFS 文件內(nèi)容 FSDataInputStream in fs.open(remote); byte[] buf new byte[1024]; int len; while ((len in.read(buf)) ! -1) { System.out.print(new String(buf, 0, len)); } in.close(); fs.close(); } }conf.set(fs.defaultFS, ...)這行是關(guān)鍵。即使 resources 下有配置文件顯式設(shè)一遍能避免被本地core-site.xml覆蓋。FileSystem.get(conf)會根據(jù) scheme 返回對應(yīng)的實現(xiàn)hdfs://返回DistributedFileSystem。跑之前確認(rèn)遠(yuǎn)程集群的 8020 端口從 Windows 能通用telnet 192.168.1.100 8020測一下不通就是網(wǎng)絡(luò)或防火墻問題跟代碼無關(guān)。5. 避坑與排查偽分布式搭建里最容易翻車的五件事5.1 NameNode 反復(fù)格式化導(dǎo)致 DataNode 起不來現(xiàn)象start-dfs.sh后jps只有 NameNode沒有 DataNodeDataNode 日志報java.io.IOException: Incompatible clusterIDs。原因每次hdfs namenode -format都會生成新的 clusterID而 DataNode 目錄里存的是舊 clusterID兩者對不上DataNode 拒絕加入。解決停掉所有進(jìn)程刪掉dfs.namenode.name.dir和dfs.datanode.data.dir指向的目錄重新格式化一次再啟動。記住格式化只做一次改配置不用重新格式化。5.2 端口 8020 和 9000 混用現(xiàn)象hdfs dfs -ls /報Connection refused但jps里 NameNode 明明在。原因core-site.xml里寫的是hdfs://localhost:9000但 3.3.3 的 NameNode 實際監(jiān)聽 8020客戶端連 9000 自然被拒。解決確認(rèn)fs.defaultFS的端口和 NameNode 實際監(jiān)聽端口一致。用netstat -tlnp | grep java看 NameNode 進(jìn)程監(jiān)聽哪個端口以實際為準(zhǔn)。3.x 默認(rèn) 8020別抄 2.x 的 9000。5.3 YARN 作業(yè)卡在 ACCEPTED 不動現(xiàn)象WordCount 提交后一直停在map 0% reduce 0%ResourceManager UI 里作業(yè)狀態(tài)是 ACCEPTED。原因常見有兩種。一是yarn.nodemanager.aux-services值寫錯shuffle 服務(wù)沒注冊二是 NodeManager 的內(nèi)存資源不夠容器申請不下來。解決先檢查yarn-site.xml里 aux-services 是不是mapreduce_shuffle。再看 NodeManager 日志有沒有Container ... is running beyond physical memory limits。偽分布式下可以在yarn-site.xml里調(diào)大yarn.nodemanager.resource.memory-mb比如設(shè)成 4096。5.4 Java 版本不匹配引發(fā)的反射錯誤現(xiàn)象啟動時報java.lang.IllegalAccessError: class ... cannot access class ...或InaccessibleObjectException。原因Hadoop 3.3.3 編譯針對 Java 8用 Java 11/17 跑時模塊系統(tǒng)限制了反射訪問。解決換 JDK 8。如果非要用高版本得加一堆--add-opens參數(shù)不劃算。生產(chǎn)環(huán)境里 Hadoop 3.3.3 配 JDK 8 是經(jīng)過驗證的組合別給自己找麻煩。5.5 Windows 下路徑和權(quán)限的坑現(xiàn)象IDEA 里跑作業(yè)報Permission denied: userxxx, accessWRITE, inode/output。原因Windows 用戶名和 HDFS 上的用戶對不上HDFS 默認(rèn)用當(dāng)前系統(tǒng)用戶名做鑒權(quán)。解決兩個辦法。一是在代碼里設(shè)System.setProperty(HADOOP_USER_NAME, root)用集群上有權(quán)限的用戶二是關(guān)掉 HDFS 權(quán)限檢查在hdfs-site.xml里加dfs.permissions.enabled設(shè)為false但生產(chǎn)環(huán)境別這么干。開發(fā)環(huán)境用第一種更干凈。6. 讓這套環(huán)境真正好用日志定位技巧與配置調(diào)優(yōu)的取舍偽分布式跑通只是起點真正拉開效率差距的是排錯速度和配置調(diào)優(yōu)的判斷力。分享幾個我踩過坑之后固定下來的習(xí)慣。先說日志定位。Hadoop 的日志文件命名是hadoop-用戶名-服務(wù)名-主機(jī)名.log比如hadoop-root-namenode-node1.log。服務(wù)起不來時別從頭翻直接tail -100看最后一百行錯誤堆棧基本都在末尾。如果日志里全是INFO沒有ERROR但服務(wù)就是沒起來去看對應(yīng)的.out文件start-dfs.sh的啟動腳本輸出重定向在那里能看到更底層的失敗原因。我一般會開兩個終端一個跑啟動命令一個tail -f盯著 NameNode 日志啟動過程中哪一步卡住一目了然。再說配置調(diào)優(yōu)的取舍。偽分布式下最值得調(diào)的是yarn.nodemanager.resource.memory-mb和yarn.scheduler.maximum-allocation-mb。默認(rèn)值偏保守跑大一點的作業(yè)容易卡在容器分配。我的習(xí)慣是把 NodeManager 可用內(nèi)存設(shè)成機(jī)器物理內(nèi)存的 70% 左右比如 8G 內(nèi)存的機(jī)器設(shè) 5632單位 MBmaximum-allocation-mb設(shè)成 2048 或 4096。但別設(shè)太大超過物理內(nèi)存會導(dǎo)致 NodeManager 被系統(tǒng) OOM Killer 干掉日志里能看到進(jìn)程突然消失。還有一個容易被忽略的點dfs.datanode.du.reserved。偽分布式下 DataNode 所在磁盤如果還存著別的東西磁盤寫滿會導(dǎo)致 DataNode 掛掉。這個參數(shù)預(yù)留一部分磁盤空間給非 HDFS 使用默認(rèn)是 0我一般設(shè)成 10G 左右避免 DataNode 把盤寫爆。最后說一個驗證配置是否生效的通用方法改完配置后用hdfs getconf -confKey 參數(shù)名查實際生效的值。比如hdfs getconf -confKey dfs.replication返回 1說明副本數(shù)配置生效了。這比翻配置文件確認(rèn)靠譜因為 Hadoop 會合并多個來源的配置最終生效值才是真的。這套環(huán)境搭好之后往上的路就寬了可以接著整合 ZooKeeper 做 HA可以換 Tez 引擎加速可以打成 Docker 鏡像方便分發(fā)。但那些都是后話眼下把 3.3.3 的偽分布式跑穩(wěn)把日志看熟把每個參數(shù)改動的后果摸清楚后面不管搭什么集群都不會慌。我自己到現(xiàn)在還保留著一個干凈的 3.3.3 偽分布式快照每次試新東西之前先回滾到這個狀態(tài)省了無數(shù)重裝的時間。希望幫到你。本文還有配套的精品資源點擊獲取