Пример кратчайших путей Giraph ClassNotFoundException
Я пытаюсь запустить пример кратчайших путей из инкубатора 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
Затем я переместил внутренние классы (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
Я осмотрел свою рабочую банку и все классы там. Кроме того, я использую 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
Также я определил HADOOP_CLASSPATH для giraph-*-dependencies.jar. Я могу запустить пример PageRankBenchmark без проблем (непосредственно из giraph-*-dependencies.jar), и пример с кратчайшим путем тоже работает (также непосредственно из 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
Список баночек должен быть через запятую. Хотя это решило мою проблему. Мне все еще любопытно, почему я должен передать свою рабочую банку в качестве параметра "classpath"? Может кто-нибудь объяснить мне, что является рациональным за этим? Как мне показалось странным (если не сказать больше) вызывать мою рабочую банку, а затем снова передавать ее как банку "classpath". Мне действительно любопытно объяснить.
1 ответ
Я нашел альтернативное программное решение проблемы. Нам нужно изменить метод 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());
...
}
setJarByClass () заставит hadoop искать недостающие классы в том же jar-файле, который содержит класс, возвращаемый getClass(), и нам не нужно будет добавлять имя jar-задания отдельно к параметру -libjars.