Panduan untuk Apache Avro

1. Ikhtisar

Serialisasi data adalah teknik mengubah data menjadi format biner atau teks. Ada beberapa sistem yang tersedia untuk tujuan ini. Apache Avro adalah salah satu sistem serialisasi data tersebut.

Avro adalah pustaka serialisasi data berbasis skema yang independen bahasa . Ini menggunakan skema untuk melakukan serialisasi dan deserialisasi. Selain itu, Avro menggunakan format JSON untuk menentukan struktur data yang membuatnya lebih kuat.

Dalam tutorial ini, kita akan mempelajari lebih lanjut tentang penyiapan Avro, Java API untuk melakukan serialisasi, dan perbandingan Avro dengan sistem serialisasi data lainnya.

Kami akan fokus terutama pada pembuatan skema yang merupakan dasar dari keseluruhan sistem.

2. Apache Avro

Avro adalah pustaka serialisasi bahasa-independen. Untuk melakukan ini, Avro menggunakan skema yang merupakan salah satu komponen inti. Ini menyimpan skema dalam file untuk pemrosesan data lebih lanjut .

Avro paling cocok untuk pemrosesan Big Data. Ini cukup populer di dunia Hadoop dan Kafka karena pemrosesannya yang lebih cepat.

Avro membuat file data tempat menyimpan data bersama dengan skema di bagian metadatanya. Di atas segalanya, ini menyediakan struktur data yang kaya yang membuatnya lebih populer daripada solusi serupa lainnya.

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

3. Pernyataan Masalah

Mari kita mulai dengan mendefinisikan kelas yang disebut AvroHttRequest yang akan kita gunakan untuk contoh kita. Kelas berisi atribut tipe 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 tipe kompleks. Kami juga memiliki employeeName yang sekali lagi merupakan tipe yang kompleks. Aktif adalah enum untuk mendeskripsikan apakah daftar karyawan yang diberikan aktif atau tidak.

Tujuan kami adalah untuk membuat serial dan membatalkan serialisasi kelas AvroHttRequest menggunakan Apache Avro.

4. Tipe Data Avro

Sebelum melangkah lebih jauh, mari kita bahas tipe data yang didukung oleh Avro.

Avro mendukung dua jenis data:

  • Tipe primitif: Avro mendukung semua tipe primitif. Kami menggunakan nama tipe primitif untuk mendefinisikan tipe bidang tertentu. Misalnya, nilai yang menyimpan String harus dideklarasikan sebagai {"type": "string"} di Schema
  • Jenis kompleks: Avro mendukung enam jenis jenis kompleks: catatan, enum, array, peta, unions, dan tetap

Misalnya, dalam pernyataan masalah kami, ClientIdentifier adalah sebuah record.

Dalam hal ini, skema untuk ClientIdentifier akan terlihat seperti:

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

5. Menggunakan Avro

Untuk memulai, mari tambahkan dependensi Maven yang kita perlukan ke file pom.xml kita .

Kami harus menyertakan dependensi berikut:

  • Apache Avro - komponen inti
  • Compiler - Kompiler Apache Avro untuk Avro IDL dan Avro Specific Java APIT
  • Alat - yang mencakup alat dan utilitas baris perintah Apache Avro
  • Plugin Apache Avro Maven untuk proyek Maven

Kami menggunakan versi 1.8.2 untuk tutorial ini.

Namun, selalu disarankan untuk menemukan versi terbaru di Maven Central:

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

Setelah menambahkan dependensi maven, langkah selanjutnya adalah:

  • Pembuatan skema
  • Membaca skema dalam program kami
  • Membuat serial data kami menggunakan Avro
  • Terakhir, lakukan de-serialisasi data

6. Pembuatan Skema

Avro menjelaskan Skemanya menggunakan format JSON. Ada empat atribut utama untuk Skema Avro yang diberikan:

  • Type- yang mendeskripsikan tipe Schema apakah tipe kompleks atau nilai primitifnya
  • Namespace- yang mendeskripsikan namespace tempat Skema tertentu berada
  • Nama - nama Skema
  • Bidang- yang menceritakan tentang bidang yang terkait dengan skema tertentu. Bidang dapat berupa tipe primitif maupun kompleks .

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

Kita juga dapat membuat skema menggunakan SchemaBuilder yang merupakan cara yang lebih baik dan efisien untuk membuatnya.

6.1. SchemaBuilder Utility

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

Pertama-tama, mari buat skema untuk ClientIdentifier:

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

Sekarang, mari 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 bahwa kami telah menetapkan clientIdentifier sebagai tipe untuk bidang clientIdentifier . Dalam kasus ini, clientIdentifier yang digunakan untuk mendefinisikan tipe adalah skema yang sama yang kita buat sebelumnya.

Nanti kita bisa menerapkan metode toString untuk mendapatkan struktur JSON dari Schema .

File skema disimpan menggunakan ekstensi .avsc . Mari simpan skema yang kita buat ke file “src / main / resources / avroHttpRequest-schema.avsc” .

7. Membaca Skema

Membaca skema kurang lebih tentang membuat kelas Avro untuk skema yang diberikan . Setelah kelas Avro dibuat, kita dapat menggunakannya untuk membuat serial dan deserialisasi objek.

Ada dua cara untuk membuat kelas Avro:

  • Kelas Avro yang dibuat secara terprogram: Kelas dapat dibuat menggunakan SchemaCompiler . Ada beberapa API yang bisa kita gunakan untuk membuat kelas Java. Kita dapat menemukan kode untuk kelas pembuatan di GitHub.
  • Menggunakan Maven untuk menghasilkan kelas

Kami memiliki satu plugin maven yang melakukan pekerjaan dengan baik. Kita perlu memasukkan plugin dan menjalankan mvn clean install .

Mari tambahkan plugin ke file pom.xml kita :

 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 kita selesai membuat skema, mari lanjutkan menjelajahi bagian serialisasi.

Ada dua format serialisasi data yang didukung Avro: format JSON dan format Biner.

Pertama, kita akan fokus pada format JSON dan kemudian kita akan membahas format Biner.

Sebelum melangkah lebih jauh, kita harus melalui beberapa antarmuka utama. Kita dapat menggunakan antarmuka dan kelas di bawah ini untuk serialisasi:

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 saat menangani data besar. Ini menawarkan serialisasi data dalam format biner serta JSON yang dapat digunakan sesuai kasus penggunaan.

Proses serialisasi Avro lebih cepat, dan juga hemat ruang. Avro tidak menyimpan informasi jenis bidang dengan setiap bidang; sebagai gantinya, ini membuat metadata dalam skema.

Terakhir namun tidak kalah pentingnya, Avro memiliki ikatan yang bagus dengan berbagai bahasa pemrograman, yang memberikan keunggulan.

Seperti biasa, kode dapat ditemukan di GitHub.