ali*_*n01 5 hadoop shortest-path classnotfoundexception giraph
我试图运行从孵化giraph(最短路径例如https://cwiki.apache.org/confluence/display/GIRAPH/Shortest+Paths+Example).但是,我没有从giraph - * - dependencies.jar执行示例,而是创建了自己的作业jar.当我创建一个如示例中所示的Job文件时,我得到了
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.Test$SimpleShortestPathsVertexInputFormat
Run Code Online (Sandbox Code Playgroud)
然后我移动了内部类(SimpleShortestPathsVertexInputFormat和SimpleShortestPathsVertexOutputFormat)来分离文件并重命名它们以防万一(SimpleShortestPathsVertexInputFormat_v2,SimpleShortestPathsVertexOutputFormat_v2); 这些类不再是静态的.这解决了SimpleShortestPathsVertexInputFormat_v2找不到类的问题,但是我仍然得到SimpleShortestPathsVertexOutputFormat_v2的相同错误.下面是我的堆栈跟踪.
INFO mapred.JobClient: Running job: job_201205221101_0003
INFO mapred.JobClient: map 0% reduce 0%
INFO mapred.JobClient: Task Id : attempt_201205221101_0003_m_000005_0, Status : FAILED
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.utils.SimpleShortestPathsVertexOutputFormat_v2
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:898)
at org.apache.giraph.graph.BspUtils.getVertexOutputFormatClass(BspUtils.java:134)
at org.apache.giraph.bsp.BspOutputFormat.getOutputCommitter(BspOutputFormat.java:56)
at org.apache.hadoop.mapred.Task.initialize(Task.java:490)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:352)
at org.apache.hadoop.mapred.Child$4.run(Child.java:259)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1059)
at org.apache.hadoop.mapred.Child.main(Child.java:253)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.utils.SimpleShortestPathsVertexOutputFormat_v2
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:866)
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:890)
... 9 more
Run Code Online (Sandbox Code Playgroud)
我检查了我的工作罐,所有课程都在那里.此外,我在伪分布模式下使用hadoop 0.20.203.我的工作方式如下所示.
hadoop jar giraphJobs.jar org.test.giraph.Test -libjars /path/to/giraph-0.2-SNAPSHOT-jar-with-dependencies.jar /path/to/input /path/to/output 0 3
Run Code Online (Sandbox Code Playgroud)
我还为giraph - * - dependencies.jar定义了HADOOP_CLASSPATH.我可以毫无问题地运行PageRankBenchmark示例(直接来自giraph - * - dependencies.jar),并且shortes路径示例也可以工作(也可以直接来自giraph - * - dependencies.jar).其他hadoop工作没有问题(在某些地方我已经阅读过以测试我的"集群"是否正常工作).有没有人遇到类似的问题?任何帮助将不胜感激.
解决方案(抱歉发布这样的但是我再也无法回答我自己的问题了几个小时)
为了解决这个问题,我不得不将我的Job jar添加到-libjars(没有对HADOOP_CLASSPATH进行更改).现在启动作业的命令看起来像这样.
hadoop jar giraphJobs.jar org.test.giraph.Test -libjars /path/to/giraph-0.2-SNAPSHOT-jar-with-dependencies.jar,/path/to/job.jar /path/to/input /path/to/output 0 3
Run Code Online (Sandbox Code Playgroud)
罐子列表必须以逗号分隔.虽然这解决了我的问题.我仍然好奇为什么我必须将我的工作jar作为"classpath"参数传递?谁能解释一下这背后的理性是什么?因为我发现调用我的工作jar然后再次作为"classpath"jar传递它很奇怪(至少可以说).我对这个解释很好奇.
我找到了解决该问题的替代方案。我们需要按以下方式修改 run() 方法 -
...
@Override
public int run(String[] argArray) throws Exception {
Preconditions.checkArgument(argArray.length == 4,
"run: Must have 4 arguments <input path> <output path> " +
"<source vertex id> <# of workers>");
GiraphJob job = new GiraphJob(getConf(), getClass().getName());
// This is the addition - it will make hadoop look for other classes in the same jar that contains this class
job.getInternalJob().setJarByClass(getClass());
job.setVertexClass(getClass());
...
}
Run Code Online (Sandbox Code Playgroud)
setJarByClass() 将使 hadoop 在包含 getClass() 返回的类的同一个 jar 中查找丢失的类,并且我们不需要将作业 jar 名称单独添加到 -libjars 选项中。