Pergunta

Estou tentando executar o exemplo de caminhos mais curtos da incubadora de girafas (https://cwiki.apache.org/confluence/display/GIRAPH/Shortest+Paths+Example).No entanto, em vez de executar o exemplo do giraph-*-dependencies.jar, criei meu próprio jar de trabalho.Quando criei um único arquivo Job conforme apresentado no exemplo, estava recebendo

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

Em seguida, movi as classes internas (SimpleShortestPathsVertexInputFormat e SimpleShortestPathsVertexOutputFormat) para arquivos separados e os renomeei apenas por precaução (SimpleShortestPathsVertexInputFormat_v2, SimpleShortestPathsVertexOutputFormat_v2);as classes não são estáticos não mais.Isso resolveu os problemas de classe não encontrada para SimpleShortestPathsVertexInputFormat_v2, porém ainda estou recebendo o mesmo erro para SimpleShortestPathsVertexOutputFormat_v2.Abaixo está meu rastreamento de pilha.

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

Eu inspecionei meu frasco de trabalho e todas as classes estão lá.Além disso, estou usando o hadoop 0.20.203 em modo pseudo-distribuído.A forma como inicio meu trabalho é apresentada a seguir.

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

Também defini HADOOP_CLASSPATH para giraph-*-dependencies.jar.Posso executar o exemplo do PageRankBenchmark sem problemas (diretamente do giraph-*-dependencies.jar), e o exemplo do caminho shortes também funciona (também diretamente do giraph-*-dependencies.jar).Outros trabalhos de hadoop funcionam sem problemas (li em algum lugar para testar se meu "cluster" funciona corretamente).Alguém se deparou com problema semelhante?Qualquer ajuda será apreciada.


Solução (desculpe postar assim, mas não posso responder minha própria pergunta por mais algumas horas)

Para resolver esse problema, tive que adicionar meu Job jar ao -libjars (nenhuma alteração em HADOOP_CLASSPATH foi feita).O comando para iniciar o trabalho agora se parece com isto.

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

A lista de jars deve ser separada por vírgulas.Embora isso tenha resolvido meu problema.Ainda estou curioso para saber por que preciso passar meu jar de trabalho como um parâmetro "classpath"?Alguém pode me explicar qual é o racional por trás disso?Como achei estranho (para dizer o mínimo) invocar meu jar de trabalho e depois passá-lo novamente como um jar de "caminho de classe".Estou muito curioso com a explicação.

Foi útil?

Solução

Encontrei uma solução programática alternativa para o problema.Precisamos modificar o método run() da seguinte maneira -

...
@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á com que o hadoop procure as classes ausentes no mesmo jar que contém a classe retornada por getClass(), e não precisaremos adicionar o nome do jar do trabalho separadamente à opção -libjars.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top