如何分佈式運行mapreduce程序java
1、 首先要知道此前提linux
若在windows的Eclipse工程中直接啓動mapreduc程序,須要先把hadoop集羣的配置目錄下的xml都拷貝到src目錄下,讓程序 自動讀取集羣的地址後去進行分佈式運行(您也能夠本身寫java代碼去設置job的configuration屬性)。apache
若不拷貝,工程中bin目錄沒有完整的xml配置文件,則windows執行的mapreduce程序所有經過本機的jvm執行,做業名也是帶有 「local"字眼的做業,如 job_local2062122004_0001。 這不是真正的分佈式運行mapreduce程序。 編程
估計得研究org.apache.hadoop.conf.Configuration的源碼,反正xml配置文件會影響執行mapreduce使用的 文件系統是本機的windows文件系統仍是遠程的hdfs系統; 還有影響執行mapreduce的mapper和reducer的是本機的jvm仍是集羣裏面機器的jvmwindows
2、 本文的結論app
第一點就是: windows上執行mapreduce,必須打jar包到全部slave節點才能正確分佈式運行mapreduce程序。(我有個需求是要windows上觸發一個mapreduce分佈式運行)eclipse
第二點就是: Linux上,只需拷貝jar文件到集羣master上,執行命令hadoop jarPackage.jar MainClassName便可分佈式運行mapreduce程序。 jvm
第三點就是: 推薦使用附一,實現了自動打jar包並上傳,分佈式執行的mapreduce程序。分佈式
附1、 推薦使用此方法:實現了自動打jar包並上傳,分佈式執行的mapreduce程序:oop
請先參考博文五篇:
Hadoop做業提交分析(一)~~(五)
http://www.cnblogs.com/spork/archive/2010/04/07/1706162.htm
引用博文的附件中EJob.java到你的工程中,而後main中添加以下方法和代碼。
public static File createPack() throws IOException {
File jarFile = EJob.createTempJar("bin");
ClassLoader classLoader = EJob.getClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
return jarFile;
}
在做業啓動代碼中使用打包:
Job job = Job.getInstance(conf, "testAnaAction");
添加:
String jarPath = createPack().getPath();
job.setJar(jarPath);
便可實現直接run as java application 在windows跑分佈式的mapreduce程序,不用手工上傳jar文件。
附2、得出結論的測試過程
(未有空看書,只能經過愚笨的測試方法得出結論了)
一. 直接經過windows上Eclipse右擊main程序的java文件,而後"run as application"或選擇hadoop插件"run on hadoop"來觸發執行MapReduce程序的測試。
1,若是不打jar包到進集羣任意linux機器上,它報錯以下:
[work] 2012-06-25 15:42:47,360 - org.apache.hadoop.mapreduce.Job -10244 [main] INFO org.apache.hadoop.mapreduce.Job - map 0% reduce 0%
[work] 2012-06-25 15:42:52,223 - org.apache.hadoop.mapreduce.Job -15107 [main] INFO org.apache.hadoop.mapreduce.Job - Task Id : attempt_1403517983686_0056_m_000000_0, Status : FAILED
Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class bookCount.BookCount$BookCountMapper not found
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1720)
at org.apache.hadoop.mapreduce.task.JobContextImpl.getMapperClass(JobContextImpl.java:186)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:721)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:339)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:162)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1491)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:157)
Caused by: java.lang.ClassNotFoundException: Class bookCount.BookCount$BookCountMapper not found
at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1626)
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1718)
... 8 more
# Error:後重復三次
2012-06-25 15:44:53,234 - org.apache.hadoop.mapreduce.Job -37813 [main] INFO org.apache.hadoop.mapreduce.Job - map 100% reduce 100%
現象就是:報錯,無進度,無運行結果。
2, 拷貝jar包到「只是」集羣master的$HADOOP_HOME/share/hadoop/mapreduce/目錄上,直接經過windows的 eclipse "run as application"和經過hadoop插件"run on hadoop"來觸發執行,它報錯同上。
現象就是:報錯,無進度,無運行結果。
3, 拷貝jar包到集羣某些slave的$HADOOP_HOME/share/hadoop/mapreduce/目錄上,直接經過windows的 eclipse "run as application"和經過hadoop插件"run on hadoop"來觸發執行
和報錯:
Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class bookCount.BookCount$BookCountMapper not found
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1720)
at org.apache.hadoop.mapreduce.task.JobContextImpl.getMapperClass(JobContextImpl.java:186)
和報錯:
Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class bookCount.BookCount$BookCountReducer not found
現象就是:有報錯,但仍然有進度,有運行結果。
4, 拷貝jar包到集羣全部slave的$HADOOP_HOME/share/hadoop/mapreduce/目錄上,直接經過windows的 eclipse "run as application"和經過hadoop插件"run on hadoop"來觸發執行:
現象就是:無報錯,有進度,有運行結果。
第一點結論就是: windows上執行mapreduce,必須打jar包到全部slave節點才能正確分佈式運行mapreduce程序。
二 在Linux上的經過如下命令觸發MapReduce程序的測試。
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/bookCount.jar bookCount.BookCount
1,只拷貝到master,在master上執行。
現象就是:無報錯,有進度,有運行結果。
2,拷貝隨便一個slave節點,在slave上執行。
現象就是:無報錯,有進度,有運行結果。
但某些節點上運行會報錯以下,且運行結果。:
14/06/25 16:44:02 INFO mapreduce.JobSubmitter: Cleaning up the staging area /tmp/hadoop-yarn/staging/hduser/.staging/job_1403517983686_0071
Exception in thread "main" java.lang.NoSuchFieldError: DEFAULT_MAPREDUCE_APPLICATION_CLASSPATH
at org.apache.hadoop.mapreduce.v2.util.MRApps.setMRFrameworkClasspath(MRApps.java:157)
at org.apache.hadoop.mapreduce.v2.util.MRApps.setClasspath(MRApps.java:198)
at org.apache.hadoop.mapred.YARNRunner.createApplicationSubmissionContext(YARNRunner.java:443)
at org.apache.hadoop.mapred.YARNRunner.submitJob(YARNRunner.java:283)
at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:415)
at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1268)
at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1265)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1491)
at org.apache.hadoop.mapreduce.Job.submit(Job.java:1265)
at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:1286)
at com.etrans.anaSpeed.AnaActionMr.run(AnaActionMr.java:207)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at com.etrans.anaSpeed.AnaActionMr.main(AnaActionMr.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.main(RunJar.java:212)
第二點結論就是: Linux上,只需拷貝jar文件到集羣master上,執行命令hadoop jarPackage.jar MainClassName便可分佈式運行mapreduce程序。
附3、本附程序的主要代碼:
請參考我另外的博文
Hadoop的mapreduce編程新舊API的簡單例子
http://keyknight.blog.163.com/blog/static/36637840201452651146607/