2012-05-22 7 views
5

Sto provando a eseguire l'esempio di percorso più breve dall'incubatrice giraph (https://cwiki.apache.org/confluence/display/GIRAPH/Shortest+Paths+Example). Tuttavia, invece di eseguire l'esempio da giraph - * - dependencies.jar, ho creato il mio jar di lavoro. Quando ho creato un unico file di lavoro, come presentato nel esempio, mi è stato sempreEsempio di percorso più breve di Giraph ClassNotFoundException

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

Poi mi hanno spostato le classi interne (SimpleShortestPathsVertexInputFormat e SimpleShortestPathsVertexOutputFormat) per separa file e rinominato solo nel caso (SimpleShortestPathsVertexInputFormat_v2, SimpleShortestPathsVertexOutputFormat_v2); le classi non sono più statiche. Questo ha risolto i problemi di classe non trovati per SimpleShortestPathsVertexInputFormat_v2, tuttavia sto ancora ottenendo lo stesso errore per SimpleShortestPathsVertexOutputFormat_v2. Di seguito è la mia traccia di stack.

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 

Ho ispezionato il mio vaso di lavoro e tutte le lezioni ci sono. Inoltre sto usando hadoop 0.20.203 in una modalità pseudo distribuita. Il modo in cui lancio il mio lavoro è presentato di seguito.

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 

Inoltre ho definito HADOOP_CLASSPATH per il giraph - * - dependencies.jar. Posso eseguire l'esempio PageRankBenchmark senza problemi (direttamente da giraph - * - dependencies.jar), e l'esempio di percorso breve funziona pure (anche direttamente da giraph - * - dependencies.jar). Altri lavori hadoop funzionano senza problemi (da qualche parte ho letto per verificare se il mio "cluster" funziona correttamente). Qualcuno ha incontrato un problema simile? Qualsiasi aiuto sarà apprezzato.


Solution (mi dispiace di inviare in questo modo, ma non posso rispondere alla mia domanda per un paio d'ore in più)

Per risolvere questo problema ho dovuto aggiungere il mio vaso di lavoro al -libjars (nessuna modifica apportata a HADOOP_CLASSPATH). Il comando per avviare il lavoro ora si presenta così.

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 

L'elenco dei vasi deve essere separato da virgola. Anche se questo ha risolto il mio problema. Sono ancora curioso di sapere perché devo passare il mio job jar come parametro "classpath"? Qualcuno può spiegarmi qual è la ragione dietro a questo? Come ho trovato strano (per non dire altro) invocare il mio lavoro jar e poi passarlo di nuovo come un jar "classpath". Sono davvero curioso della spiegazione.

risposta

3

Ho trovato una soluzione programmatica alternativa al problema. abbiamo bisogno di modificare il metodo run() nel seguente modo -

... 
@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() farà aspetto Hadoop per le classi mancanti nella stessa vaso che contiene la classe restituito da getClass(), e lo faremo non è necessario aggiungere il nome del jar del lavoro separatamente all'opzione -libjars.