之前將eclipse下編好的mapreduce代碼放到集群上面跑,發現速度很慢,namenode節點的cpu和內存使用率很低,datanode節點基本上處於沒有運行的狀態,然后通過查看hadoop-etc-hadoop下面的配置文件,發現mapreduce-site.xml文件下面的mapreduce.framework.name名字中framework少了一個字母e,導致集群一直運行在偽分布模式下面,同時也導致web控制網頁沒有datanode的信息,打開master:8088網站顯示no available datanode in the table,曾經這個問題困擾了我很久很久,因為如果網站打不開的話就沒有辦法查看運行的日志,沒有辦法通過日志來查看運行出錯信息。在hadoop2.1以后就通過mapreduce-site.xml配置文件里面的mapreduce.jobhistory.webapp.address下面的value值master:19888網站來查看各個節點的運行狀態了,開啟jobhistory的命令是mr-jobhistory-sh start historyserver。
運行jar包的時候提示空指針異常 java.lang.NullPointerException分析說明
這個問題也困擾了我相當長的時間,直到后來通過日志log發現原來是程序沒有讀我的文件(文件格式是xml格式),后來把文件復制到各個節點下面相同的路徑里面,然后在代碼中輸入路徑(不可以只放在namenode節點上,不然datanonde讀不到文件便會報空指針異常)。
mapreduce框架中全局變量的設置
在我的工程中需要在map函數里面調用一個類的方法,如果在每個map函數里面都新建類的話會導致運行時間很長,內存溢出。這里我想在代碼運行之前新建這個類,在map方法里面直接調用這個類的方法,這個過程也困擾了我很長的時間,直到另一個需求的出現,在處理很多文件的時候我希望輸出為多個文件,而不是只有一個輸出文件。
對於輸出多個文件的分析
在程序中加入以下代碼
private MultipleOutputs mos;
protected void setup(Context context) throws IOException, InterruptedException {
mos=new MultipleOutputs(context);//初始化mos
}
protected void cleanup( Context context) throws IOException, InterruptedException {
mos.close();//釋放資源
}
public void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException,NullPointerException{
mos.write(new Text(key),new Text(value),filename);
}
實現以filename文件作為輸入文件輸出map的結果。
這里我就發現了一個地方,在setup方法中新建了一個對象mos,然后在map函數中直接調用mos的方法,而網上說setup方法只運行一次,可以重載自己的功能,然后回到上一個問題,我把需要初始化的對象直接放到setup方法里面,然后在map函數里面執行對象的方法,結果空指針異常消失了,而且不會再每執行一次map函數就新建一個對象,這樣減少了內存的消耗。
運行時候出現Error: GC overhead limit exceeded
在hadoop2.x中默認Container的yarn child jvm堆大小為200M,通過參數mapred.child.java.opts指定,可以在job提交的時候給定,是一個客戶端生效的參數,配置在mapred-site.xml文件中,通過將該參數修改為-Xms200m -Xmx4096000m來更改jvm堆大小,異常解決。
然后我繼續運行jar包工程,運行時出現4.2 GB of 2.1 GB virtual memory used. Killing container.
這個錯誤和物理內存無關,是虛擬內存超了。
解決方法:
在etc/hadoop/yarn-site.xml文件中,修改檢查虛擬內存的屬性為false,如下:
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
參考資料:http://blog.csdn.net/ma0903/article/details/48289731

