mahout(或者hadoop)优先使用用户指定的classpath加载jar包

mahout(或者hadoop)优先使用用户指定的classpath加载jar包



问题:使用mahout0.8时,出现java.lang.NoSuchMethodError: org.apache.lucene.util.PriorityQueue
类似http://www.warski.org/blog/2013/10/using-amazons-elastic-map-reduce-to-compute-recommendations-with-apache-mahout-0-8/
原因:
$HADOOP_HOME/lib下面有个旧版本的lucene-core-3.6.0.jar的jar包,mahout的lib也有自己的lucene-core的jar包。
hadoop会优先考虑$HADOOP_HOME/lib的jar包,
所以mahout的lib的那个lucene-core-4.3.0.jar就没有加载,而是加载了$HADOOP_HOME/lib那个旧版本的。
由于旧版本的lucene-core-3.6.0.jar跟mahout0.8不兼容,所以出错了。


google搜索overwrite hadoop classpath看到
http://stackoverflow.com/questions/11685949/overriding-default-hadoop-jars-in-class-path
For other versions of hadoop, you‘re best to check the TaskRunner.java class to 
confirm the name of the config property after all this is a "semi hidden config":
static final String MAPREDUCE_USER_CLASSPATH_FIRST =
        "mapreduce.user.classpath.first"; //a semi-hidden config

hadoop1.1.2中TaskRunner.java的源码
https://github.com/hobinyoon/hadoop-1.1.2/blob/8d91a5453c23ea9f643952a3961f78d31ca5f22c/src/mapred/org/apache/hadoop/mapred/TaskRunner.java

因此调用mahout时加上-Dmapreduce.user.classpath.first=true选项
$MAHOUT recommendfactorized -Dmapreduce.user.classpath.first=true --numThreads 88 --input $hdfs_user_ratings_path --userFeatures $hdfs_user_features_path --itemFeatures $hdfs_item_features_path --numRecommendations 10 --output $hdfs_result_path --maxRating 1
-D选项对于hadoop也是有效的。

其实开始是我参考以下链接的做法:
hadoop mapreduce程序jar包版本冲突解决方法
http://f.dataguru.cn/thread-58160-1-1.html
一般情况下,使用hadoop jar 执行mr的时候,会首先加载$HADOOP_HOME/lib下的jar包,
由于使用的hadoop中带了commons-net-1.4.1.jar,所以会优先加载1.4.1版本,而忽略用户自己指定的3.2版本,所以报异常
参数项 -Dmapreduce.task.classpath.user.precedence 可以改变系统classpath加载的优先顺序
验证:
hadoop jar collect_log.jar com.collect.LogCollectJob -Dmapreduce.task.classpath.user.precedence=true -libjars commons-net-3.2.jar /new_log_collect/input /new_log_collect/output

我发现在mahout里-libjars选项压根没用,还会报错。虽然mahout提示有-libjars选项,但是压根貌似不认识-libjars似的。所以我放弃了这种做法。
对于参数项 -Dmapreduce.task.classpath.user.precedence,也许是其他hadoop版本的选项。

但是对于我这个场景,hadoop1.1.2,是使用-Dmapreduce.user.classpath.first=true选项来优先加载用户自定义的jar包的。
那么为啥我不需要再指定mahout里lib下面的lucene-core-4.3.0.jar呢?
因为mahout自己会尝试加载自己lib下面的jar包,
如果设置了-Dmapreduce.user.classpath.first=true选项,
lucene-core-4.3.0.jar就不会被系统默认的覆盖掉了。


收获:
hadoop1.1.2使用-Dmapreduce.user.classpath.first=true选项来优先加载用户自定义的jar包的
每个版本hadoop的这个选项不同,在hadoop源码的TaskRunner.java可以找到。


本文链接:http://blog.csdn.net/lingerlanlan/article/details/42504479

本文作者:linger






郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。