Panduan untuk Apache Avro

1. Gambaran keseluruhan

Serialisasi data adalah teknik menukar data menjadi format binari atau teks. Terdapat banyak sistem yang tersedia untuk tujuan ini. Apache Avro adalah salah satu sistem penyirian data tersebut.

Avro adalah perpustakaan bersiri data berasaskan bahasa yang bebas skema . Ia menggunakan skema untuk melakukan serialisasi dan deserialisasi. Lebih-lebih lagi, Avro menggunakan format JSON untuk menentukan struktur data yang menjadikannya lebih kuat.

Dalam tutorial ini, kita akan meneroka lebih lanjut mengenai penyediaan Avro, Java API untuk melakukan serialisasi dan perbandingan Avro dengan sistem serialisasi data lain.

Kami akan memberi tumpuan terutamanya pada penciptaan skema yang menjadi asas keseluruhan sistem.

2. Apache Avro

Avro adalah perpustakaan bersiri bebas bahasa. Untuk melakukan ini Avro menggunakan skema yang merupakan salah satu komponen teras. Ia menyimpan skema dalam fail untuk pemprosesan data lebih lanjut .

Avro paling sesuai untuk pemprosesan Big Data. Ia cukup popular di dunia Hadoop dan Kafka kerana pemprosesannya lebih pantas.

Avro membuat fail data di mana ia menyimpan data bersama dengan skema di bahagian metadata-nya. Di atas segalanya, ia menyediakan struktur data yang kaya yang menjadikannya lebih popular daripada penyelesaian lain yang serupa.

Untuk menggunakan Avro untuk bersiri, kita perlu mengikuti langkah-langkah yang disebutkan di bawah.

3. Penyataan Masalah

Mari kita mulakan dengan menentukan kelas yang dipanggil AvroHttRequest yang akan kita gunakan untuk contoh kita. Kelas mengandungi atribut jenis primitif dan kompleks:

class AvroHttpRequest { private long requestTime; private ClientIdentifier clientIdentifier; private List employeeNames; private Active active; } 

Di sini, requestTime adalah nilai primitif. ClientIdentifier adalah kelas lain yang mewakili jenis kompleks. Kami juga mempunyai nama pekerja yang lagi kompleks. Aktif adalah enum untuk menerangkan sama ada senarai pekerja yang diberikan aktif atau tidak.

Objektif kami adalah untuk membuat siri dan membatalkan siri AvroHttRequest menggunakan Apache Avro.

4. Jenis Data Avro

Sebelum melangkah lebih jauh, mari kita bincangkan jenis data yang disokong oleh Avro.

Avro menyokong dua jenis data:

  • Jenis primitif: Avro menyokong semua jenis primitif. Kami menggunakan nama jenis primitif untuk menentukan jenis bidang tertentu. Sebagai contoh, nilai yang memegang String harus dinyatakan sebagai {"type": "string"} dalam Skema
  • Jenis kompleks: Avro menyokong enam jenis jenis kompleks: rekod, enum, tatasusunan, peta, kesatuan dan tetap

Sebagai contoh, dalam pernyataan masalah kami, ClientIdentifier adalah rekod.

Sekiranya skema untuk ClientIdentifier kelihatan seperti:

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

5. Menggunakan Avro

Sebagai permulaan, mari kita tambahkan kebergantungan Maven yang kita perlukan ke fail pom.xml kami .

Kita harus memasukkan kebergantungan berikut:

  • Apache Avro - komponen teras
  • Compiler - Apache Avro Compiler untuk Avro IDL dan Avro Specific Java APIT
  • Alat - yang merangkumi alat dan utiliti baris perintah Apache Avro
  • Plugin Apache Avro Maven untuk projek Maven

Kami menggunakan versi 1.8.2 untuk tutorial ini.

Walau bagaimanapun, selalu dinasihatkan untuk mencari versi terbaru di Maven Central:

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

Setelah menambahkan kebergantungan maven, langkah seterusnya adalah:

  • Pembentukan skema
  • Membaca skema dalam program kami
  • Serial data kami menggunakan Avro
  • Akhir sekali, nyahsenaraikan data

6. Penciptaan Skema

Avro menerangkan Skema menggunakan format JSON. Terdapat terutamanya empat atribut untuk Skema Avro tertentu:

  • Jenis- yang menerangkan jenis Skema sama ada jenis kompleksnya atau nilai primitif
  • Namespace- yang menerangkan ruang nama tempat Skema diberikan
  • Nama - nama Skema
  • Fields- yang memberitahu tentang bidang yang berkaitan dengan skema yang diberikan. Padang boleh terdiri daripada jenis primitif dan juga kompleks .

Salah satu cara membuat skema adalah dengan menulis representasi JSON, seperti yang kita lihat di bahagian sebelumnya.

Kita juga boleh membuat skema menggunakan SchemaBuilder yang tidak dapat dinafikan cara yang lebih baik dan cekap untuk membuatnya.

6.1. Utiliti SchemaBuilder

Kelas org.apache.avro.SchemaBuilder berguna untuk membuat Skema.

Pertama sekali, mari buat skema untuk ClientIdentifier:

Schema clientIdentifier = SchemaBuilder.record("ClientIdentifier") .namespace("com.baeldung.avro") .fields().requiredString("hostName").requiredString("ipAddress") .endRecord();

Sekarang, mari kita gunakan ini untuk membuat skema avroHttpRequest :

Schema avroHttpRequest = SchemaBuilder.record("AvroHttpRequest") .namespace("com.baeldung.avro") .fields().requiredLong("requestTime") .name("clientIdentifier") .type(clientIdentifier) .noDefault() .name("employeeNames") .type() .array() .items() .stringType() .arrayDefault(null) .name("active") .type() .enumeration("Active") .symbols("YES","NO") .noDefault() .endRecord();

Penting untuk diperhatikan di sini bahawa kami telah menetapkan clientIdentifier sebagai jenis untuk bidang clientIdentifier . Dalam kes ini, clientIdentifier yang digunakan untuk menentukan jenis adalah skema yang sama yang kita buat sebelumnya.

Nanti kita dapat menerapkan kaedah toString untuk mendapatkan struktur JSON Skema .

Fail skema disimpan menggunakan peluasan .avsc . Mari simpan skema yang dihasilkan kita ke fail "src / main / resources / avroHttpRequest-schema.avsc" .

7. Membaca Skema

Membaca skema lebih kurang membuat kelas Avro untuk skema yang diberikan . Sebaik sahaja kelas Avro dibuat, kita dapat menggunakannya untuk membuat siri dan mendeserisasi objek.

Terdapat dua cara untuk membuat kelas Avro:

  • Membuat kelas Avro secara terprogram : Kelas boleh dihasilkan menggunakan SchemaCompiler . Ada beberapa API yang dapat kita gunakan untuk menghasilkan kelas Java. Kita dapat mencari kod untuk kelas generasi di GitHub.
  • Menggunakan Maven untuk menghasilkan kelas

Kami mempunyai satu plugin maven yang berfungsi dengan baik. Kita perlu memasukkan plugin dan menjalankan pemasangan bersih mvn .

Mari tambahkan pemalam ke fail pom.xml kami :

 org.apache.avro avro-maven-plugin ${avro.version}   schemas generate-sources  schema protocol idl-protocol   ${project.basedir}/src/main/resources/ ${project.basedir}/src/main/java/     

8. Serialisasi dan Deserialisasi dengan Avro

Setelah selesai membuat skema, mari terus meneroka bahagian siri.

Terdapat dua format serialisasi data yang disokong oleh Avro: format JSON dan format Binari.

Pertama, kita akan memfokus pada format JSON dan kemudian kita membincangkan format Binari.

Sebelum melangkah lebih jauh, kita harus melalui beberapa antara muka utama. Kita boleh menggunakan antara muka dan kelas di bawah untuk siriisasi:

DatumWriter: We should use this to write data on a given Schema. We'll be using the SpecificDatumWriter implementation in our example, however, DatumWriter has other implementations as well. Other implementations are GenericDatumWriter, Json.Writer, ProtobufDatumWriter, ReflectDatumWriter, ThriftDatumWriter.

Encoder: Encoder is used or defining the format as previously mentioned. EncoderFactory provides two types of encoders, binary encoder, and JSON encoder.

DatumReader: Single interface for de-serialization. Again, it got multiple implementations, but we'll be using SpecificDatumReader in our example. Other implementations are- GenericDatumReader, Json.ObjectReader, Json.Reader, ProtobufDatumReader, ReflectDatumReader, ThriftDatumReader.

Decoder: Decoder is used while de-serializing the data. Decoderfactory provides two types of decoders: binary decoder and JSON decoder.

Next, let's see how serialization and de-serialization happen in Avro.

8.1. Serialization

We'll take the example of AvroHttpRequest class and try to serialize it using Avro.

First of all, let's serialize it in JSON format:

public byte[] serealizeAvroHttpRequestJSON( AvroHttpRequest request) { DatumWriter writer = new SpecificDatumWriter( AvroHttpRequest.class); byte[] data = new byte[0]; ByteArrayOutputStream stream = new ByteArrayOutputStream(); Encoder jsonEncoder = null; try { jsonEncoder = EncoderFactory.get().jsonEncoder( AvroHttpRequest.getClassSchema(), stream); writer.write(request, jsonEncoder); jsonEncoder.flush(); data = stream.toByteArray(); } catch (IOException e) { logger.error("Serialization error:" + e.getMessage()); } return data; } 

Let's have a look at a test case for this method:

@Test public void whenSerialized_UsingJSONEncoder_ObjectGetsSerialized(){ byte[] data = serealizer.serealizeAvroHttpRequestJSON(request); assertTrue(Objects.nonNull(data)); assertTrue(data.length > 0); }

Here we've used the jsonEncoder method and passing the schema to it.

If we wanted to use a binary encoder, we need to replace the jsonEncoder() method with binaryEncoder():

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

8.2. Deserialization

To do this, we'll be using the above-mentioned DatumReader and Decoder interfaces.

As we used EncoderFactory to get an Encoder, similarly we'll use DecoderFactory to get a Decoder object.

Let's de-serialize the data using JSON format:

public AvroHttpRequest deSerealizeAvroHttpRequestJSON(byte[] data) { DatumReader reader = new SpecificDatumReader(AvroHttpRequest.class); Decoder decoder = null; try { decoder = DecoderFactory.get().jsonDecoder( AvroHttpRequest.getClassSchema(), new String(data)); return reader.read(null, decoder); } catch (IOException e) { logger.error("Deserialization error:" + e.getMessage()); } } 

And let's see the test case:

@Test public void whenDeserializeUsingJSONDecoder_thenActualAndExpectedObjectsAreEqual(){ byte[] data = serealizer.serealizeAvroHttpRequestJSON(request); AvroHttpRequest actualRequest = deSerealizer .deSerealizeAvroHttpRequestJSON(data); assertEquals(actualRequest,request); assertTrue(actualRequest.getRequestTime() .equals(request.getRequestTime())); }

Similarly, we can use a binary decoder:

Decoder decoder = DecoderFactory.get().binaryDecoder(data, null);

9. Conclusion

Apache Avro sangat berguna semasa menangani data besar. Ia menawarkan siri data dalam bentuk binari dan juga JSON yang dapat digunakan mengikut kes penggunaan.

Proses serialisasi Avro lebih pantas, dan ruangnya juga cekap. Avro tidak menyimpan maklumat jenis bidang dengan setiap bidang; sebaliknya, ia membuat metadata dalam skema.

Akhir sekali, Avro mempunyai pengikatan yang hebat dengan pelbagai bahasa pengaturcaraan, yang memberikan kelebihan.

Seperti biasa, kodnya boleh didapati di GitHub.