2016-01-12 18 views
6

ho questo schema avroschema Avro non onora compatibilità all'indietro

{ 
"namespace": "xx.xxxx.xxxxx.xxxxx", 
"type": "record", 
"name": "MyPayLoad", 
"fields": [ 
    {"name": "filed1", "type": "string"}, 
    {"name": "filed2",  "type": "long"}, 
    {"name": "filed3", "type": "boolean"}, 
    { 
      "name" : "metrics", 
      "type": 
      { 
      "type" : "array", 
      "items": 
      { 
       "name": "MyRecord", 
       "type": "record", 
       "fields" : 
        [       
         {"name": "min", "type": "long"}, 
         {"name": "max", "type": "long"}, 
         {"name": "sum", "type": "long"}, 
         {"name": "count", "type": "long"} 
        ] 
      } 
      } 
    } 
    ] 
} 

Ecco il codice che usiamo per analizzare i dati

public static final MyPayLoad parseBinaryPayload(byte[] payload) { 
     DatumReader<MyPayLoad> payloadReader = new SpecificDatumReader<>(MyPayLoad.class); 
     Decoder decoder = DecoderFactory.get().binaryDecoder(payload, null); 
     MyPayLoad myPayLoad = null; 
     try { 
      myPayLoad = payloadReader.read(null, decoder); 
     } catch (IOException e) { 
      logger.log(Level.SEVERE, e.getMessage(), e); 
     } 

     return myPayLoad; 
    } 

ora voglio aggiungere un altro campo di int lo schema appare come sotto

{ 
"namespace": "xx.xxxx.xxxxx.xxxxx", 
"type": "record", 
"name": "MyPayLoad", 
"fields": [ 
    {"name": "filed1", "type": "string"}, 
    {"name": "filed2",  "type": "long"}, 
    {"name": "filed3", "type": "boolean"}, 
    { 
      "name" : "metrics", 
      "type": 
      { 
      "type" : "array", 
      "items": 
      { 
       "name": "MyRecord", 
       "type": "record", 
       "fields" : 
        [       
         {"name": "min", "type": "long"}, 
         {"name": "max", "type": "long"}, 
         {"name": "sum", "type": "long"}, 
         {"name": "count", "type": "long"} 
        ] 
      } 
      } 
    } 
    {"name": "agentType", "type": ["null", "string"], "default": "APP_AGENT"} 
    ] 
} 

Nota il file aggiunto e anche il valore predefinito è definito. Il problema è che se riceviamo i dati che è stato scritto utilizzando lo schema più vecchio ottengo questo errore

java.io.EOFException: null 
    at org.apache.avro.io.BinaryDecoder.ensureBounds(BinaryDecoder.java:473) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.io.BinaryDecoder.readInt(BinaryDecoder.java:128) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.io.BinaryDecoder.readIndex(BinaryDecoder.java:423) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:229) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.io.parsing.Parser.advance(Parser.java:88) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:206) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:152) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:177) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:148) ~[avro-1.7.4.jar:1.7.4] 
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:139) ~[avro-1.7.4.jar:1.7.4] 
    at com.appdynamics.blitz.shared.util.XXXXXXXXXXXXX.parseBinaryPayload(BlitzAvroSharedUtil.java:38) ~[blitz-shared.jar:na] 

quello che ho capito da this documento che questo avrebbe dovuto essere compatibile, ma in qualche modo che non sembra essere il Astuccio. Qualche idea su cosa sto facendo male?

risposta

0

Ci sono due possibili problemi che io possa vedere nello schema

  1. Il valore predefinito per me sembra sempre di avere il lavoro come nulla per specificare questo è necessario impostare

"default": null

  1. Anche nello schema si è dimenticato di aggiungere un (separatore di campo) tra l'array e il nuovo campo. Quindi provare a cambiare lo schema come

    { "namespace": "xx.xxxx.xxxxx.xxxxx", "type": "record", "name": "MyPayLoad", "fields": [ {"name": "filed1", "type": "string"}, {"name": "filed2", "type": "long"}, {"name": "filed3", "type": "boolean"}, { "name" : "metrics", "type": { "type" : "array", "items": { "name": "MyRecord", "type": "record", "fields" : [ {"name": "min", "type": "long"}, {"name": "max", "type": "long"}, {"name": "sum", "type": "long"}, {"name": "count", "type": "long"} ] } } }, {"name": "agentType", "type": ["null", "string"], "default":null} ] }

2

finalmente ho ottenuto questo lavoro. Ho bisogno di dare entrambi gli schemi nel SpecificDatumReader Così ho modificato il parsing come questo, dove ho passato sia il vecchio e il nuovo schema nel lettore e ha funzionato come un fascino

public static final MyPayLoad parseBinaryPayload(byte[] payload) { 
     DatumReader<MyPayLoad> payloadReader = new SpecificDatumReader<>(SCHEMA_V1, SCHEMA_V2); 
     Decoder decoder = DecoderFactory.get().binaryDecoder(payload, null); 
     MyPayLoad myPayLoad = null; 
     try { 
      myPayLoad = payloadReader.read(null, decoder); 
     } catch (IOException e) { 
      logger.log(Level.SEVERE, e.getMessage(), e); 
     } 

     return myPayLoad; 
    } 
0

sto affrontando questa situazione esatta. I dati scritti dallo schema precedente falliscono nel tentativo di leggerlo con lo schema più recente. Lo schema più recente ha solo un campo aggiuntivo con unione e set predefinito. "tipo": ["null", "stringa"], "doc": "", "predefinito": null

Nonostante l'impostazione predefinita, il valore null non viene compilato automaticamente durante la lettura. Entrambi gli schemi di scrittore e lettore devono essere forniti durante la lettura. La mia comprensione è avro è compatibile con le versioni precedenti e dovrebbe essere in grado di supportare le colonne più recenti senza la necessità dello schema precedente.

Problemi correlati