我有一个C ++服务,它公开了2个接口:
一个。提交():用于向YARNRM提交DistCp作业
湾Query():用于查询应用程序的状态。
此服务在内部调用Java客户端(通过JNI),它具有2个静态函数:
提交()
查询()
提交()确实:
DistCp distCp = new DistCp(configuration, distCpOptions);
Job job = distCp.execute();
Parses the "application ID" from the tracking URL and returns it.
Query()确实:
Takes "application ID" returned in Submit()
YarnClient yarnClient = YarnClient.createYarnClient();
yarnClient.init(new YarnConfiguration());
yarnClient.start();
yarnClient.getApplicationReport(applicationID);
yarnClient.stop();
我面临的问题是,
Query()调用在所有条件下都成功。
Submit()调用失败并显示错误(第一次调用,第二次调用和第三次调用,但有不同的例外):
java.util.ServiceConfigurationError: org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider: Provider org.apache.hadoop.mapred.LocalClientProtocolProvider not found
java.util.ServiceConfigurationError: org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider: Provider org.apache.hadoop.mapred.YarnClientProtocolProvider not found
java.io.IOException: Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.
我调试了这个问题并发现,当首先调用Query()API时,不会加载类LocalClientProtocolProvider
和YarnClientProtocolProvider
。当调用Submit()时,类加载器应该加载这些类。但是,这种情况并没有发生。
我还观察到,当首先调用Query()API时,Hadoop配置会发生变化,并且包含许多与“mapreduce。*”配置相关的默认设置。
一旦调用Submit()方法,我就尝试使用Class.forName()进行显式加载。但是,这也没有帮助。
调用Submit()时,为什么类加载器不加载所需的类?这是Hadoop配置或Java类加载器的问题吗?或者是问题,因为我正在混合使用MapReduce和Yarn API?
“mapreduce.framework.name”配置设置为“yarn”。
我的环境是Hadoop 2.6.0。
我的类路径包含以下路径中存在的所有Hadoop jar:
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
答案 0 :(得分:1)
我发现,我正在混合使用Yarn
和MapReduce
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()
时,类加载器会假定它已加载了所有必需的类。但是,类YarnClientProtocolProvider
和LocalClientProtocolProvider
尚未加载。因此,Submit()
调用失败。
为了强制类加载器加载所有MapReduce
相关类,我在YarnClientWrapper
的构造函数中添加了以下语句(这是一个单例类并包装YarnClient
)。
Cluster cluster = new Cluster(configuration);
cluster.getFileSystem();
cluster.close();
这解决了这个问题。
但是,更清晰的实施方法是在MapReduce
而不是Query()
中使用YarnClient
客户端。这将确保我们不会进入类加载问题。