2015-04-04 14 views
5

Nie widziałem dotąd rozwiązania mojego konkretnego problemu. To nie działa co najmniej. To doprowadza mnie do szału. Ta szczególna kombinacja nie wydaje się mieć wiele w przestrzeni Google. Mój błąd występuje, gdy zadanie wykonuje się w programie odwzorowującym z tego co wiem. Dane wejściowe do tego zadania to avro schematu, który jest skompresowany za pomocą funkcji deflate, chociaż próbowałem również nieskompresowane.Znaleziono interfejs org.apache.hadoop.mapreduce.TaskAttemptContext

Avro: 1.7.7 Hadoop: 2.4.1

otrzymuję ten błąd i nie jestem pewien dlaczego. Oto moja praca, mapper i zmniejsz. Błąd dzieje się, gdy odwzorowujący przychodzi

Sample nieskompresowany plik wejściowy Avro (StockReport.SCHEMA jest zdefiniowana w ten sposób)

{"day": 3, "month": 2, "year": 1986, "stocks": [{"symbol": "AAME", "timestamp": 507833213000, "dividend": 10.59}]} 

Praca

@Override 
public int run(String[] strings) throws Exception { 
    Job job = Job.getInstance(); 
    job.setJobName("GenerateGraphsJob"); 
    job.setJarByClass(GenerateGraphsJob.class); 

    configureJob(job); 

    int resultCode = job.waitForCompletion(true) ? 0 : 1; 

    return resultCode; 
} 

private void configureJob(Job job) throws IOException { 
    try { 
     Configuration config = getConf(); 
     Path inputPath = ConfigHelper.getChartInputPath(config); 
     Path outputPath = ConfigHelper.getChartOutputPath(config); 

     job.setInputFormatClass(AvroKeyInputFormat.class); 
     AvroKeyInputFormat.addInputPath(job, inputPath); 
     AvroJob.setInputKeySchema(job, StockReport.SCHEMA$); 


     job.setMapperClass(StockAverageMapper.class); 
     job.setCombinerClass(StockAverageCombiner.class); 
     job.setReducerClass(StockAverageReducer.class); 

     FileOutputFormat.setOutputPath(job, outputPath); 

    } catch (IOException | ClassCastException e) { 
     LOG.error("An job error has occurred.", e); 
    } 
} 

Mapper.

public class StockAverageMapper extends 
     Mapper<AvroKey<StockReport>, NullWritable, StockYearSymbolKey, StockReport> { 
    private static Logger LOG = LoggerFactory.getLogger(StockAverageMapper.class); 

private final StockReport stockReport = new StockReport(); 
private final StockYearSymbolKey stockKey = new StockYearSymbolKey(); 

@Override 
protected void map(AvroKey<StockReport> inKey, NullWritable ignore, Context context) 
     throws IOException, InterruptedException { 
    try { 
     StockReport inKeyDatum = inKey.datum(); 
     for (Stock stock : inKeyDatum.getStocks()) { 
      updateKey(inKeyDatum, stock); 
      updateValue(inKeyDatum, stock); 
      context.write(stockKey, stockReport); 
     } 
    } catch (Exception ex) { 
     LOG.debug(ex.toString()); 
    } 
} 

Schemat klucza wyjścia mapy:

{ 
    "namespace": "avro.model", 
    "type": "record", 
    "name": "StockYearSymbolKey", 
    "fields": [ 
    { 
     "name": "year", 
     "type": "int" 
    }, 
    { 
     "name": "symbol", 
     "type": "string" 
    } 
    ] 
} 

Ślad stosu:

java.lang.Exception: java.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.mapreduce.TaskAttemptContext, but class was expected 
    at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462) 
    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522) 
Caused by: java.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.mapreduce.TaskAttemptContext, but class was expected 
    at org.apache.avro.mapreduce.AvroKeyInputFormat.createRecordReader(AvroKeyInputFormat.java:47) 
    at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.<init>(MapTask.java:492) 
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:735) 
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:340) 
    at org.apache.hadoop.mapred.LocalJobRunner$Job$MapTaskRunnable.run(LocalJobRunner.java:243) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:745) 

Edit: Nie, że jest to ważne, ale ja pracuję, aby zmniejszyć to do danych można utworzyć wyjść z JFreeChart. Nie przedostanie się przez program odwzorowujący, więc nie powinno być z nim powiązane.

Odpowiedz

6

Problem polega na tym, że org.apache.hadoop.mapreduce.TaskAttemptContext był class in Hadoop 1, ale stał się interface in Hadoop 2.

Jest to jeden z powodów, dla których biblioteki zależne od bibliotek Hadoop muszą oddzielnie skompilować pliki jar dla Hadoop 1 i Hadoop 2. W oparciu o twój ślad stosu, wygląda na to, że masz w jakiś sposób skompilowany plik Hroop1 Avro, pomimo uruchomienia z Hadoop 2.4.1.

download mirrors for Avro zapewnia ładne osobne pliki do pobrania dla avro-mapred-1.7.7-hadoop1.jar vs avro-mapred-1.7.7-hadoop2.jar.

+0

Dam ci szansę. Te skompilowane klasy Avro działają z moją drugą pracą. To właśnie w tej pracy, która korzysta z biblioteki współdzielonej. Mój pom ma 1.7.7 avro-mapred, avro-tools i avro. Ręcznie skompilowałem schematy avro za pomocą słoja o nazwie avro-tools-1.7.7.jar. – Rig

+0

Przybiłeś to. Dzięki. – Rig

1

Problem polega na tym, że Avro 1.7.7 obsługuje 2 wersje Hadoop, a zatem zależy od obu wersji Hadoop. I domyślnie słoiki Avro 1.7.7 zależą od starej wersji Hadoop. budować z Avro 1.7.7 z Hadoop2 prostu dodać dodatkowy classifier linię Maven zależności:

<dependency> 
     <groupId>org.apache.avro</groupId> 
     <artifactId>avro-mapred</artifactId> 
     <version>1.7.7</version> 
     <classifier>hadoop2</classifier> 
    </dependency> 

to powie Maven, aby szukać avro-mapred-1.7.7-hadoop2.jar nie avro-mapred-1.7.7.jar

samo dotyczy Avro 1.7 .4 i powyżej