Hadoop初次體驗:各種坑以及解決辦法
- 本文使用的Hadoop版本是2.7.4;
- 作業系統是:Linux下的Ubuntu16.04以及其定製版Linux mint 18.1
一、背景
因為工作和以後課題方向的原因,開始涉及大資料的方向,在大資料的領域,Hadoop無論如何是繞不過去的話題,於是進入這個方向也是著手從Hadoop開始,但是從Hadoop開始,並不代表我們一定要採用它的解決方案,因為現在Hadoop自身各個元件的解耦做得已經才能夠當好了,所以說我們可以把某一個元件單獨拿出來使用,或者和別的框架相結合,比如單單使用HDFS,但是因為採用的計算模型可能和我們實際的業務並不相同,所以說HDFS之上,我們可以採用Spark,Storm等計算框架。
這篇文章只是一篇“入坑文”,在我看來,因為對於這樣一個龐大的生態系統,早點遇到一些問題還是好的,因為如果在生產環境中遇到,那真是一件想死的事情。
對於下邊的體驗和實踐,我都在兩種環境下進行了測試,其結果並不完全相同。其中最開始我是在阿里雲的伺服器上搭建的,開始買的是學生優惠的伺服器,但是整體伺服器的效能並不是很強(由於窘迫的經濟),但是對於折騰一下還是足夠的,但是一在執行Hadoop的時候就出現問題了,後面會詳說;同時我還在自己的筆記本上運行了一下,對於整個過程來說,相對於阿里雲上的測試還是比較順利的。
下面是我的伺服器的配置對比,可以給大家做參考。
指標/配置 | 阿里雲伺服器 | 本地伺服器 |
---|---|---|
CPU | 單處理器*單核 Intel Xeon E5-2682 v4 | 4處理器*雙核 Intel Core i5-3210M |
記憶體 | 2G | 8G |
作業系統 | Ubuntu 16.04.2 LTS | Linux Mint 18.1 Serena |
磁碟 | 40G | 512G |
網路 | 1M頻寬 | 6M頻寬 |
對於Hadoop執行環境的選擇,個人更偏向Linux,雖然目前Hadoop是使用Java
開發的,天然支援跨平臺,而且也開始支援windows,但是由於是部署在伺服器上的,而Linux是伺服器領域無愧的王者,所以最好還是在Linux平臺上。
本文主要是在單機和偽分散式模式下執行,參考的是Hadoop的官方文件。對於一些簡單的配置和執行在文件中已經寫的很清楚了,在上述兩臺伺服器上執行的都沒有問題,但是對於YARN on a Single Node部分(我們假設執行之前的HDFS的程式和配置是沒有問題的),在兩臺伺服器的執行就開始有差別了,這是因為作為Hadoop 2.x最明顯的改變就是講JobTracker分開了,成為兩部分:
- 資源管理器;
- 任務排程器;
所以在這部分涉及了資源管理的內容,導致在兩臺伺服器上的執行效果不同。下面是測試的結果、問題和解決辦法。
二、測試過程
2.1 相關引數的配置
這一步的目的在於提供Hadoop執行MapReduce任務、資源管理和節點管理等的配置資訊,預設情況下,Hadoop給我們提供了關於這些程式執行的所有引數配置,這裡涉及到的是:
- etc/Hadoop/mapred-site.xml:用於配置MapReduce應用的配置資訊,這是隻有你在選擇了MapReduce計算模型後才會來配置該檔案,如果你選擇的是Spark的話,則需要考慮另外的配置檔案,預設的配置在mapred-default.xml;
- etc/Hadoop/yarn-site.xml:這個配置檔案裡提供的是Yarn相關的配置引數,預設的配置引數在yarn-default.xml;
在官方的文件中,上述兩個檔案的配置如下:
mapred-site.xml
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>
yarn-site.xml
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration>
從上述的配置中也可以看出來,Hadoop已經將計算框架從Hadoop本身剝離出來了,連配置檔案都是獨立的。
2.2 啟動yarn
配置完畢之後就要啟動yarn指令碼了,這個指令碼中包括ResourceManager和NodeManager兩個守護程序,是獨立執行的。開啟之後你可以通過jps檢視執行情況,這個命令可以檢視執行的JVM例項,如果正常的話,結果如下:
10356 NameNode
10661 SecondaryNameNode
26840 ResourceManager
26953 NodeManager
10492 DataNode
9340 Jps
對於上述結果:
- 前提是你的HDFS已經執行起來了;
- 這裡雖然所有程式都已經顯示了,但是根據我執行時的經驗,jps這個命令有時候不太靈,有些程式原本執行失敗,但是它仍然顯示出來了,在手冊上也顯示這個命令處於實驗階段,所以穩定性還有待提高;此時我們應該去檢視對應的日誌看看時候有異常出現,但是對於這一點,對於Hadoop有不滿的一點,所有的異常都是寫到檔案中的,在控制檯沒有絲毫的提示資訊,導致出現異常不能及時發現,對應的日誌在logs目錄下;
在我執行的時候,出現的問題如下:
NodeManager 啟動失敗,檢視日誌發現異常如下:
org.apache.Hadoop.yarn.exceptions.YarnRuntimeException: org.apache.Hadoop.yarn.exceptions.YarnRuntimeException: Recieved SHUTDOWN signal from Resourcemanager ,Registration of NodeManager failed, Message from ResourceManager: NodeManager from localhost doesn't satisfy minimum allocations, Sending SHUTDOWN signal to the NodeManager.
從日誌中來看,明顯是伺服器的資源不能滿足程式執行的需要,此時只能去查詢預設NodeManager的資源配置,所謂的資源,這裡涉及到的由記憶體和CPU,預設情況下,這兩種資源的配置如下:
yarn.nodemanager.resource.memory-mb
:用於配置可以分給執行的containers的實體記憶體的數量,預設是8192MB,也就是8G;yarn.nodemanager.resource.cpu-vcores
:用於containers執行的虛擬核心的數量,這裡指的是虛擬核心,而不是物理核心,指的是使用牙膏廠的超執行緒技術虛擬出來的核心,預設是8;
情況很明顯,對於這兩個要求,我的伺服器都不滿足,所以只能更改配置,在如下:
對於阿里雲伺服器:
<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>1600</value> </property> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>1</value> </property>
對於本地伺服器:
<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>3000</value> </property> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>3</value> </property>
對於這個配置過程真是一波三折,期間和各種其他的預設配置相沖突,導致不斷推到重來,而且在加上使用的伺服器那點資源,真是捉急呀!對於整個配置的過程,需要對Yarn的構建元件和彼此之間的關係十分清楚,才能找出各個配置之間的關係,這裡主要關注記憶體分配之間的關係:
yarn.scheduler.minimum-allocation-mb
&yarn.scheduler.maximum-allocation-mb
該引數的作用階段在:應用(以Container的形式)向ResourceManager請求記憶體分配的時候,如果應用請求的記憶體,記為Mem(Container Request),出現以下情況則會丟擲
InvalidResourceRequestException
異常:- Mem(Container Request) < Mem(
yarn.scheduler.minimum-allocation-mb
) - Mem(Container Request) > Mem(
yarn.scheduler.maximum-allocation-mb
)
對於這兩個引數和
yarn.nodemanager.resource.memory-mb
的關係,這兩個引數決定的是一個Container執行所需資源的波動範圍,而應用都是要在各個Node上執行的,yarn.nodemanager.resource.memory-mb
決定的是一個Node能夠提供給containers多少記憶體資源,所以這三個引數決定了一個Node同時能夠執行的最多的Container有多少,記為Num(Max Running Container):
Num(MaxRunningContainer)=Mem(′yarn.nodemanager.resource.memory−mb′)Mem(′yarn.scheduler.minimum−allocation−mb′) - Mem(Container Request) < Mem(
mapreduce.map.memory.mb
&mapreduce.reduce.memory.mb
這兩個引數的作用階段在:Container已經在各個Node上執行起來了,NodeManager起到監控和預警的作用,相當於設定的閾值,如果實際情況下的Map或者Reduce任務使用的資源超過這兩個設定值的話,會被killed掉,具體滿足何種條件才會監控,包括對於虛擬記憶體的監控相關的引數參考相關文章的第2篇,作為一篇入坑文,本文不詳細闡述。所以這兩個引數的值滿足:
- Mem(
yarn.nodemanager.resource.memory-mb
) > Mem(mapreduce.map.memory.mb
) - Mem(
yarn.nodemanager.resource.memory-mb
) > Mem(mapreduce.reduce.memory.mb
)
- Mem(
yarn.app.mapreduce.am.resource.mb
該引數決定了執行在特定Node的Application Master使用的記憶體的總數,由於Application Master是和NodeManager一起用來執行和監控執行在Node上的所有Application的,包括它們的執行狀態和執行過程,由於Application Master也是在Node上執行的,所以它要使用的記憶體也是由NodeManager提供的,所以也要滿足一下條件,在提交客戶端的時候會檢查如下:
- Mem(
yarn.nodemanager.resource.memory-mb
) > Mem(yarn.app.mapreduce.am.resource.mb
)
- Mem(
2.3 提交MapReduce應用
當啟動Yarn成功後,我們可以提交MapReduce任務,當提交MapReduce任務時候可能會出現奇怪的異常,比如任務:
bin/Hadoop jar share/Hadoop/mapreduce/Hadoop-mapreduce-examples-2.7.4.jar grep input output 'dfs[a-z.]+'
異常如下:
WARN hdfs.DataStreamer:
Caught exceptionjava.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1245) at java.lang.Thread.join(Thread.java:1319) at org.apache.Hadoop.hdfs.DataStreamer.closeResponder(DataStreamer.java:871) at org.apache.Hadoop.hdfs.DataStreamer.endBlock(DataStreamer.java:519) at org.apache.Hadoop.hdfs.DataStreamer.run(DataStreamer.java:696)
這個對於初學者來說有點恐慌,其實這是Hadoop本身的一個bug,而且還沒有修復。
到此為止,所有的流程全部完成,對於兩個伺服器來說,結果是不同的:
- 本地伺服器:成功執行,雖然執行的時間很長,但是結果完全正確;
- 阿里雲伺服器:執行的Application一致卡在Running狀態,搜尋了很多,都將矛頭指向了記憶體分配,但是無奈,巧婦難為無米之炊;
關於初次體驗Hadoop,最直接的感受和印象就是對資源管理要很熟悉才行,才能瞭解各種引數之間的關係,但是想要達到這個目的,首先要了解Hadoop整體的架構組成,以及各個元件詳細的功能、彼此之間的關係。
相關文章: