有时我的MR工作抱怨MyMapper类没有找到。我必须给job.setJarByClass(MyMapper.class);告诉它从我的jar文件中加载。
cloudera@cloudera-vm:/tmp/translator$ hadoop jar MapReduceJobs.jar translator/input/Portuguese.txt translator/output13/06/13 03:36:57警告映射。JobClient:没有设置作业jar文件。可能找不到用户类。参见JobConf(Class)或JobConf#setJar(String)。13/06/13 03:36:57信息输入。FileInputFormat:要处理的输入路径总数:113/06/13 03:36:57信息映射。JobClient:正在运行的作业:job_201305100422_004313/06/13 03:36:58信息映射。JobClient: map 0% reduce 0%13/06/13 03:37:03信息映射。JobClient:任务Id: attempt_201305100422_0043_m_000000_0,状态:FAILEDjava.lang.RuntimeException: java.lang.ClassNotFoundException: com.mapreduce.variousformats.keyvaluetextinputformat.MyMapperorg.apache.hadoop.conf.Configuration.getClass (Configuration.java: 996)org.apache.hadoop.mapreduce.JobContext.getMapperClass (JobContext.java: 212)org.apache.hadoop.mapred.MapTask.runNewMapper (MapTask.java: 601)
问题:为什么会这样?为什么它不总是告诉我从我的jar文件加载它。有没有解决这类问题的最佳实践?另外,如果我正在使用一些第三方库,我也必须为他们做这个吗?
确保在提交作业时向HADOOP_CLASSPATH
和-libjars
添加任何依赖项,如下面的示例所示:
使用以下命令从(例如)current和lib
目录中添加所有jar依赖项:
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:`echo *.jar`:`echo lib/*.jar | sed 's/ /:/g'`
请记住,当通过hadoop jar
启动作业时,您还需要通过使用-libjars
将任何依赖项的jar传递给它。我喜欢使用:
hadoop jar <jar> <class> -libjars `echo ./lib/*.jar | sed 's/ /,/g'` [args...]
注意: sed
命令需要一个不同的分隔符;HADOOP_CLASSPATH
用:
分隔,-libjars
用,
分隔。
是的,job.setJarByClass
是必要的。这样hadoop就会把你的jar复制到任务跟踪器中。如果你没有调用job.setJarByClass
, hadoop会认为你的jar在任务跟踪器的类路径中,所以它不会复制你的jar。