5 votes

Exemple de chemins les plus courts de Giraph ClassNotFoundException

J'essaie d'exécuter l'exemple des chemins les plus courts à partir de l'incubateur giraph ( https://cwiki.apache.org/confluence/display/GIRAPH/Shortest+Paths+Exemple ). Cependant, au lieu d'exécuter l'exemple à partir de giraph-*-dependencies.jar, j'ai créé mon propre job jar. Lorsque j'ai créé un seul fichier Job comme présenté dans l'exemple, j'ai obtenu les résultats suivants

java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.Test$SimpleShortestPathsVertexInputFormat

Ensuite, j'ai déplacé les classes internes (SimpleShortestPathsVertexInputFormat et SimpleShortestPathsVertexOutputFormat) vers des fichiers séparés et je les ai renommés juste au cas où (SimpleShortestPathsVertexInputFormat_v2, SimpleShortestPathsVertexOutputFormat_v2) ; les classes ne sont pas statiques plus. Cela a résolu le problème de classe non trouvée pour le SimpleShortestPathsVertexInputFormat_v2, mais je reçois toujours la même erreur pour le SimpleShortestPathsVertexOutputFormat_v2. Voici ma trace de pile.

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

J'ai inspecté mon pot de travail et toutes les classes sont là. De plus, j'utilise hadoop 0.20.203 en mode pseudo-distribué. La façon dont je lance mon job est présentée ci-dessous.

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

J'ai également défini HADOOP_CLASSPATH pour le fichier giraph-*-dependencies.jar. Je peux exécuter l'exemple PageRankBenchmark sans problème (directement à partir de giraph-*-dependencies.jar), et l'exemple shortes path fonctionne également (également directement à partir de giraph-*-dependencies.jar). Les autres jobs hadoop fonctionnent sans problème (j'ai lu quelque part pour tester si mon "cluster" fonctionne correctement). Quelqu'un a-t-il rencontré un problème similaire ? Toute aide sera appréciée.


Solución (désolé de le poster comme ça mais je ne peux pas répondre à ma propre question avant quelques heures)

Pour résoudre ce problème, j'ai dû ajouter mon jar Job à l'option -libjars (aucune modification n'a été apportée à HADOOP_CLASSPATH). La commande pour lancer Job ressemble maintenant à ceci.

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

La liste des bocaux doit être séparée par des virgules. Bien que cela ait résolu mon problème. Je suis toujours curieux de savoir pourquoi je dois passer mon jar de travail comme paramètre "classpath" ? Quelqu'un peut-il m'expliquer ce qui se cache derrière cela ? Je trouve étrange (c'est le moins que l'on puisse dire) d'invoquer mon job jar et de le repasser en tant que jar "classpath". Je suis vraiment curieux de connaître l'explication.

4voto

user1484380 Points 158

J'ai trouvé une solution programmatique alternative au problème. Nous devons modifier la méthode run() de la manière suivante -

...
@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() fera en sorte que hadoop recherche les classes manquantes dans le même bocal qui contient la classe retournée par getClass(), et nous n'aurons pas besoin d'ajouter le nom du bocal du travail séparément à l'option -libjars.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X