Chinaunix首页 | 论坛 | 博客
  • 博客访问: 756577
  • 博文数量: 190
  • 博客积分: 2991
  • 博客等级: 少校
  • 技术积分: 2400
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-24 18:11
文章分类

全部博文(190)

文章存档

2015年(3)

2014年(1)

2013年(65)

2012年(121)

我的朋友

分类: 项目管理

2013-01-09 07:38:14

写MR程序时往往会使用到第三方包, 如果这些包在集群中不存在, 可以通过多种方式提交到集群供 MR 程序使用, 但如果集群中存在的jar与用户MR程序用到的JAR存在版本冲突时该如何解决?
下面是我碰到的问题及解决方式, 简单记录如下, 碰到同样问题的同学可以参考下:
昨天使用 commons-net-3.2.jar 包连接FTP采集日志,
调用方法片段:
 
Java代码: 
  1. FTPClient ftpClient = new FTPClient();  
  2. ftpClient.setConnectTimeout(1000);   
 
// 这个方法在commons-net-3.2.jar包中有, 而在 commons-net-1.4.1.jar 中没有
 
一般情况下,使用hadoop jar 执行mr的时候,会首先加载$HADOOP_HOME/lib下的jar包,
由于使用的hadoop中带了commons-net-1.4.1.jar,所以会优先加载1.4.1版本,而忽略用户自己指定的3.2版本,所以报异常,
 
Error: org.apache.commons.net.ftp.FTPClient.setConnectTimeout(I)V     
//异常提示调用setConnectTimeout 方法有问题。
 
查看源码TaskRunner.java
 
Java代码 : 
/** 
  */  
  1.   static List getClassPaths(JobConf conf, File workDir,  
  2.   TaskDistributedCacheManager taskDistributedCacheManager)  
  3.     throws IOException {  
  4.    // Accumulates class paths for child.  
  5.    List classPaths = new ArrayList();  
  6.    boolean userClassesTakesPrecedence = conf.userClassesTakesPrecedence();   
  7. // 这个参数项可以改变系统classpath加载的优先顺序, 默认应该是false  
  8.    if (!userClassesTakesPrecedence) {   // 默认是false, tasktrack机器的系统classpath总是优先加载  
  9.    // start with same classpath as parent process  
  10.     appendSystemClasspaths(classPaths);  
  11.  }  
  12.    // include the user specified classpath  
  13.     appendJobJarClasspaths(conf.getJar(), classPaths);  
  14.    // Distributed cache paths  
  15.     if (taskDistributedCacheManager != null)  
  16.       classPaths.addAll(taskDistributedCacheManager.getClassPaths());  
  17.     // Include the working dir too  
  18.     classPaths.add(workDir.toString());  
  19.     if (userClassesTakesPrecedence) {  
  20.       // parent process's classpath is added last  
  21.      appendSystemClasspaths(classPaths);  
  22.    }  
  23.     return classPaths;  
  24.   }  
 
 
通过上面源码可以看出 参数项 -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
 
程序执行成功。
阅读(1874) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~