2015-09-30 39 views
0

我有一个C++服务,它公开了2个接口:运行Hadoop作业时发生类加载问题

a。提交():用于向YARNRM提交DistCp作业

b。 Query():用于查询应用程序的状态。

此服务在内部调用Java客户端(通过JNI),其中有2个静态函数:

  1. 提交()

  2. 查询()

提交()做:

DistCp distCp = new DistCp(configuration, distCpOptions); 
Job job = distCp.execute(); 
Parses the "application ID" from the tracking URL and returns it. 

查询()的作用:

Takes "application ID" returned in Submit() 
YarnClient yarnClient = YarnClient.createYarnClient(); 
yarnClient.init(new YarnConfiguration()); 
yarnClient.start(); 
yarnClient.getApplicationReport(applicationID); 
yarnClient.stop(); 

我现在面临的问题是,

  1. 如果该服务的第一个电话被提交(),那么所有的后续调用(均提交()和查询())成功
  2. 但是,如果第一次调用服务是Query(),则所有Submit()调用FAIL。

Query()调用在所有条件下都成功。

的提交()调用失败,错误(第一个呼叫,第二个呼叫和下面第三个呼叫,用不同的例外):

  1. java.util.ServiceConfigurationError: org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider: Provider org.apache.hadoop.mapred.LocalClientProtocolProvider not found
  2. java.util.ServiceConfigurationError: org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider: Provider org.apache.hadoop.mapred.YarnClientProtocolProvider not found
  3. java.io.IOException: Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.

我调试了这个问题并发现,当首先调用Query()API时,则不会加载类LocalClientProtocolProviderYarnClientProtocolProvider 。当调用Submit()时,类加载器应该加载这些类。但是,这并没有发生。

我还观察到,当首先调用Query()API时,Hadoop配置发生变化,并且包含许多与“mapreduce。*”配置相关的默认设置。

一旦调用了Submit()方法,我尝试使用Class.forName()进行显式加载。但是,这也没有帮助。

当调用Submit()时,为什么类加载器不加载所需的类?这是Hadoop配置还是Java类加载器的问题?还是这是问题,因为我混合了MapReduce和Yarn API?

“mapreduce.framework.name”配置设置为“纱线”。

我的环境是Hadoop 2.6.0。

我的类路径中包含所有Hadoop的罐子存在于以下路径:

a. hadoop/common/  
b. hadoop/common/lib  
c. hadoop/hdfs/  
d. hadoop/hdfs/lib  
e. hadoop/mapreduce/  
f. hadoop/mapreduce/lib  
g. hadoop/yarn/ 
h. hadoop/yarn/lib 

回答

1

我想通了,我是混合YarnMapReduce API和导致类装入问题。

当首先调用Query()时,它会加载所有与YARN相关的类。 对于例如为:

org.apache.hadoop.yarn.client.api.YarnClient from file:/D:/data/hadoop-2 
.6.0-SNAPSHOT/share/hadoop/yarn/hadoop-yarn-client-2.6.0-SNAPSHOT.jar 

但是,不加载MapReduce的相关类。对于例如,下面的类没有加载:

org.apache.hadoop.mapred.YarnClientProtocolProvider from 
file:/D:/data/hdoop-2.6.0-SNAPSHOT/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.6.0-SNAPSHOT.jar 

所以,当Submit()被调用时,类加载器假设,它加载的所有必需类。但是,类YarnClientProtocolProviderLocalClientProtocolProvider尚未加载。因此,Submit()调用失败。

要强制类加载器加载所有MapReduce相关类,我在构造函数YarnClientWrapper(这是一个单例类并包装YarnClient)中添加了以下语句。

Cluster cluster = new Cluster(configuration); 
cluster.getFileSystem(); 
cluster.close(); 

这解决了这个问题。

但是,更清洁的实施将使用Query()中的MapReduce客户端而不是YarnClient。这将确保我们不会遇到类加载问题。

相关问题