Guide til Apache Avro

1. Oversigt

Dataserialisering er en teknik til konvertering af data til binært eller tekstformat. Der er flere systemer tilgængelige til dette formål. Apache Avro er et af disse dataserialiseringssystemer.

Avro er et sproguafhængigt, skemabaseret dataserialiseringsbibliotek. Det bruger et skema til at udføre serialisering og deserialisering. Desuden bruger Avro et JSON-format til at specificere datastrukturen, der gør den mere kraftfuld.

I denne vejledning udforsker vi mere om Avro-opsætning, Java API til at udføre serialisering og en sammenligning af Avro med andre dataserialiseringssystemer.

Vi fokuserer primært på skemaoprettelse, som er basen i hele systemet.

2. Apache Avro

Avro er et sproguafhængigt serialiseringsbibliotek. For at gøre dette bruger Avro et skema, der er en af ​​kernekomponenterne. Det gemmer skemaet i en fil til yderligere databehandling.

Avro passer bedst til Big Data-behandling. Det er ret populært i Hadoop og Kafka verden for sin hurtigere behandling.

Avro opretter en datafil, hvor den gemmer data sammen med skemaet i sin metadata sektion. Frem for alt giver den en rig datastruktur, der gør den mere populær end andre lignende løsninger.

For at bruge Avro til serialisering skal vi følge nedenstående trin.

3. Problemerklæring

Lad os starte med at definere en klasse kaldet AvroHttRequest som vi bruger til vores eksempler. Klassen indeholder både primitive og komplekse attributter:

klasse AvroHttpRequest {privat lang anmodningstid; private ClientIdentifier clientIdentifier; private medarbejdernavne på listen; privat Aktiv aktiv; } 

Her, anmodningstid er en primitiv værdi. ClientIdentifier er en anden klasse, der repræsenterer en kompleks type. Vi har også Ansattes navn hvilket igen er en kompleks type. Aktiv er et rum til beskrivelse af, om den givne liste over medarbejdere er aktiv eller ej.

Vores mål er at serialisere og de-serialisere AvroHttRequest klasse ved hjælp af Apache Avro.

4. Avro-datatyper

Lad os diskutere de datatyper, der understøttes af Avro, inden vi fortsætter videre.

Avro understøtter to typer data:

  • Primitiv type: Avro understøtter alle primitive typer. Vi bruger primitivt navn til at definere en type af et givet felt. For eksempel en værdi, der indeholder en Snor skal erklæres som {“type”: “streng”} i skemaet
  • Kompleks type: Avro understøtter seks slags komplekse typer: poster, enums, arrays, maps, fagforeninger og faste

For eksempel i vores problemangivelse ClientIdentifier er en rekord.

I så fald skema til ClientIdentifier skal se ud som:

{"type": "record", "name": "ClientIdentifier", "namespace": "com.baeldung.avro", "fields": [{"name": "hostName", "type": "string" }, {"name": "ipAddress", "type": "string"}]}

5. Brug af Avro

Til at begynde med, lad os tilføje de Maven-afhængigheder, vi har brug for, til vores pom.xml fil.

Vi bør inkludere følgende afhængigheder:

  • Apache Avro - kernekomponenter
  • Compiler - Apache Avro Compilers til Avro IDL og Avro Specific Java APIT
  • Værktøjer - som inkluderer Apache Avro kommandolinjeværktøjer og hjælpeprogrammer
  • Apache Avro Maven Plugin til Maven-projekter

Vi bruger version 1.8.2 til denne tutorial.

Det tilrådes dog altid at finde den nyeste version på Maven Central:

 org.apache.avro avro-compiler 1.8.2 org.apache.avro avro-maven-plugin 1.8.2 

Efter tilføjelse af maven-afhængigheder er de næste trin:

  • Oprettelse af skema
  • Læsning af skemaet i vores program
  • Serialisering af vores data ved hjælp af Avro
  • Til sidst afserialiserer du dataene

6. Oprettelse af skema

Avro beskriver sit skema ved hjælp af et JSON-format. Der er hovedsageligt fire attributter for et givet Avro-skema:

  • Type- der beskriver typen af ​​skema, hvad enten den er kompleks eller primitiv værdi
  • Navneområde- som beskriver navneområdet, hvor det givne skema hører til
  • Navn - navnet på skemaet
  • Felter- som fortæller om de felter, der er knyttet til et givet skema. Felter kan være af både primitiv og kompleks type.

En måde at oprette skemaet på er at skrive JSON-repræsentationen, som vi så i de foregående sektioner.

Vi kan også oprette et skema ved hjælp af SchemaBuilder hvilket utvivlsomt er en bedre og effektiv måde at skabe det på.

6.1. SchemaBuilder Hjælpeprogram

Klassen org.apache.avro.SchemaBuilder er nyttigt til oprettelse af skemaet.

Lad os først og fremmest oprette skemaet til ClientIdentifier:

Skema clientIdentifier = SchemaBuilder.record ("ClientIdentifier") .navneområde ("com.baeldung.avro") .fields (). RequiredString ("hostName"). RequiredString ("ipAddress") .endRecord ();

Lad os nu bruge dette til at oprette en avroHttpRequest skema:

Skema avroHttpRequest = SchemaBuilder.record ("AvroHttpRequest"). Navneområde ("com.baeldung.avro") .fields (). RequiredLong ("requestTime") .name ("clientIdentifier") .type (clientIdentifier) ​​.noDefault (). navn ("medarbejdernavne") .type () .array () .items () .stringType () .arrayDefault (null) .navn ("aktiv") .type () .nummer ("Aktiv") .symboler ("JA "," NO ") .noDefault () .endRecord ();

Det er vigtigt at bemærke her, at vi har tildelt clientIdentifier som typen for clientIdentifier Mark. I dette tilfælde, clientIdentifier bruges til at definere type er det samme skema, som vi oprettede før.

Senere kan vi anvende toString metode til at få JSON struktur af Skema.

Skema filer gemmes ved hjælp af .avsc udvidelse. Lad os gemme vores genererede skema til “Src / main / resources / avroHttpRequest-schema.avsc” fil.

7. Læsning af skemaet

Læsning af et skema handler mere eller mindre om oprettelse af Avro-klasser for det givne skema. Når Avro-klasser er oprettet, kan vi bruge dem til at serieisere og deserialisere objekter.

Der er to måder at oprette Avro-klasser på:

  • Programmerende generering af Avro-klasser: Klasser kan genereres ved hjælp af SchemaCompiler. Der er et par API'er, som vi kan bruge til at generere Java-klasser. Vi kan finde koden til generationsklasser på GitHub.
  • Brug af Maven til at generere klasser

Vi har et maven-plugin, der gør jobbet godt. Vi skal medtage pluginet og køre mvn ren installation.

Lad os tilføje pluginet til vores pom.xml fil:

 org.apache.avro avro-maven-plugin $ {avro.version} skemaer genererer-kilder skema protokol idl-protokol $ {project.basedir} / src / main / resources / $ {project.basedir} / src / main / java / 

8. Serialisering og deserialisering med Avro

Efterhånden som vi er færdige med at generere skemaet, lad os fortsætte med at udforske serialiseringsdelen.

Der er to dataserialiseringsformater, som Avro understøtter: JSON-format og binært format.

Først vil vi fokusere på JSON-formatet og derefter diskutere det binære format.

Før vi fortsætter, skal vi gennemgå et par nøglegrænseflader. Vi kan bruge nedenstående grænseflader og klasser til serialisering:

DatumWriter: Vi skal bruge dette til at skrive data om et givet skema. Vi bruger SpecificDatumWriter implementering i vores eksempel, dog DatumWriter har også andre implementeringer. Andre implementeringer er GenericDatumWriter, Json.Writer, ProtobufDatumWriter, ReflectDatumWriter, ThriftDatumWriter.

Koder: Encoder bruges eller definerer formatet som tidligere nævnt. EncoderFabrik giver to typer kodere, binær encoder og JSON encoder.

DatumLæser: Enkelt interface til de-serialisering. Igen fik den flere implementeringer, men vi bruger det SpecificDatumReader i vores eksempel. Andre implementeringer er- GenericDatumReader, Json.ObjectReader, Json.Reader, ProtobufDatumReader, ReflectDatumReader, ThriftDatumReader.

Dekoder: Dekoder bruges under de-serialisering af dataene. Dekoderfabrik giver to typer dekodere: binær dekoder og JSON dekoder.

Lad os derefter se, hvordan serialisering og de-serialisering sker i Avro.

8.1. Serialisering

Vi tager eksemplet med AvroHttpRequest klasse og prøv at serieisere det ved hjælp af Avro.

Lad os først og fremmest serieisere det i JSON-format:

offentlig byte [] serealizeAvroHttpRequestJSON (AvroHttpRequest anmodning) {DatumWriter forfatter = ny SpecificDatumWriter (AvroHttpRequest.class); byte [] data = ny byte [0]; ByteArrayOutputStream stream = ny ByteArrayOutputStream (); Koder jsonEncoder = null; prøv {jsonEncoder = EncoderFactory.get (). jsonEncoder (AvroHttpRequest.getClassSchema (), stream); writer.write (anmodning, jsonEncoder); jsonEncoder.flush (); data = stream.toByteArray (); } fange (IOException e) {logger.error ("Serialiseringsfejl:" + e.getMessage ()); } returnere data } 

Lad os se på en test case for denne metode:

@Test offentlig ugyldig nårSerialized_UsingJSONEncoder_ObjectGetsSerialized () {byte [] data = serealizer.serealizeAvroHttpRequestJSON (anmodning); assertTrue (Objects.nonNull (data)); assertTrue (data.length> 0); }

Her har vi brugt jsonEncoder metode og videregive skemaet til den.

Hvis vi ønskede at bruge en binær encoder, skal vi udskifte jsonEncoder () metode med binærEncoder ():

Encoder jsonEncoder = EncoderFactory.get (). BinaryEncoder (stream, null);

8.2. Deserialisering

For at gøre dette bruger vi ovennævnte Datolæser og Dekoder grænseflader.

Som vi brugte EncoderFabrik at få en Koder, på samme måde bruger vi DekoderFabrik at få en Dekoder objekt.

Lad os de-serialisere dataene ved hjælp af JSON-format:

offentlig AvroHttpRequest deSerealizeAvroHttpRequestJSON (byte [] data) {DatumReader reader = ny SpecificDatumReader (AvroHttpRequest.class); Dekoder dekoder = null; prøv {decoder = DecoderFactory.get (). jsonDecoder (AvroHttpRequest.getClassSchema (), ny streng (data)); return reader.read (null, dekoder); } fange (IOException e) {logger.error ("Deserialiseringsfejl:" + e.getMessage ()); }} 

Og lad os se testsagen:

@Test offentlig ugyldig nårDeserializeUsingJSONDecoder_thenActualAndExpectedObjectsAreEqual () {byte [] data = serealizer.serealizeAvroHttpRequestJSON (anmodning); AvroHttpRequest actualRequest = deSerealizer .deSerealizeAvroHttpRequestJSON (data); assertEquals (actualRequest, anmodning); assertTrue (actualRequest.getRequestTime () .equals (request.getRequestTime ())); }

På samme måde kan vi bruge en binær dekoder:

Dekoder dekoder = DecoderFactory.get (). BinaryDecoder (data, null);

9. Konklusion

Apache Avro er især nyttig i forbindelse med store data. Det tilbyder dataserialisering i binært såvel som JSON-format, som kan bruges i henhold til brugssagen.

Avro-serialiseringsprocessen er hurtigere, og den er også pladseffektiv. Avro opbevarer ikke felttypeoplysningerne for hvert felt; i stedet opretter det metadata i et skema.

Sidst men ikke mindst har Avro en stor binding med en bred vifte af programmeringssprog, hvilket giver den en fordel.

Som altid kan koden findes på GitHub.