מדריך לאפאצ'י אברו

1. סקירה כללית

סדרת נתונים היא טכניקה של המרת נתונים לפורמט בינארי או טקסט. ישנן מספר מערכות זמינות למטרה זו. Apache Avro היא אחת מאותן מערכות סידור נתונים.

Avro היא ספריית סידור נתונים מבוססת-סכמה על-פי שפה. היא משתמשת בסכמה לביצוע סדרת סדר וסילוק מחדש. יתר על כן, Avro משתמש בפורמט JSON כדי לציין את מבנה הנתונים שהופך אותו לחזק יותר.

במדריך זה נחקור עוד על התקנת Avro, ה- API של Java לביצוע סידור והשוואה בין Avro למערכות סידור נתונים אחרות.

אנו נתמקד בעיקר ביצירת סכמות שהיא הבסיס של המערכת כולה.

2. אפאצ'י אברו

Avro היא ספריית סדרות ללא תלות בשפה. לשם כך Avro משתמש בסכמה שהיא אחד ממרכיבי הליבה. זה מאחסן את הסכימה בקובץ לעיבוד נתונים נוסף.

Avro הוא המתאים ביותר לעיבוד Big Data. זה די פופולרי בעולם Hadoop ו- Kafka בגלל העיבוד המהיר יותר שלו.

Avro יוצר קובץ נתונים שבו הוא שומר נתונים יחד עם סכימה בקטע המטא נתונים שלה. מעל לכל, הוא מספק מבנה נתונים עשיר שהופך אותו לפופולרי יותר מפתרונות דומים אחרים.

כדי להשתמש ב- Avro לסידור, עלינו לבצע את השלבים המוזכרים להלן.

3. הצהרת בעיות

נתחיל בהגדרת כיתה שנקראת AvroHttRequest שנשתמש בדוגמאות שלנו. הכיתה מכילה תכונות סוג פרימיטיביות כמו גם מורכבות:

מחלקה AvroHttpRequest {private long requestTime; פרטי ClientIdentifier clientIdentifier; שמות עובדים ברשימה פרטית; פעיל פעיל פעיל; } 

פה, זמן הבקשה הוא ערך פרימיטיבי. ClientIdentifier הוא מחלקה אחרת המייצגת סוג מורכב. יש לנו גם שם העובד שזה שוב סוג מורכב. פָּעִיל הוא אנומט המתאר האם רשימת העובדים הנתונה פעילה או לא.

המטרה שלנו היא לבצע סדרת סדרות של דה-סדרת AvroHttRequest בכיתה באמצעות Apache Avro.

4. סוגי נתונים של Avro

לפני שנמשיך הלאה, בואו נדון בסוגי הנתונים הנתמכים על ידי Avro.

Avro תומך בשני סוגים של נתונים:

  • סוג פרימיטיבי: Avro תומך בכל הסוגים הפרימיטיביים. אנו משתמשים בשם סוג פרימיטיבי כדי להגדיר סוג של שדה נתון. לדוגמא, ערך שמחזיק a חוּט יש להכריז כ- "סוג": "מחרוזת"} בסכמה
  • סוג מורכב: Avro תומך בשישה סוגים מורכבים: רשומות, enums, מערכים, מפות, איגודים ותיקים

לדוגמא, בהצהרת הבעיות שלנו, ClientIdentifier הוא שיא.

במקרה זה סכמה עבור ClientIdentifier צריך להיראות כמו:

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

5. שימוש ב- Avro

ראשית, בואו נוסיף את התלות של Maven שאנחנו צריכים pom.xml קוֹבֶץ.

עלינו לכלול את התלות הבאה:

  • Apache Avro - מרכיבי ליבה
  • מהדר - קומפיילרים של Apache Avro עבור Avro IDL ו- Java APIT ספציפי ל- Avro
  • כלים - הכוללים כלים ושירותי פקודה של Apache Avro
  • תוסף Apache Avro Maven עבור פרויקטים של Maven

אנו משתמשים בגירסה 1.8.2 לצורך הדרכה זו.

עם זאת, תמיד מומלץ למצוא את הגרסה האחרונה ב- Maven Central:

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

לאחר הוספת תלות של maven, השלבים הבאים יהיו:

  • יצירת סכמה
  • קריאת הסכימה בתכנית שלנו
  • סדרת הנתונים שלנו באמצעות Avro
  • לבסוף, בטל את סדרת הנתונים

6. יצירת סכמה

Avro מתאר את הסכימה שלה באמצעות פורמט JSON. ישנן בעיקר ארבע תכונות לסכימת אברו נתונה:

  • סוּג- המתאר את סוג הסכימה בין אם סוג המורכב שלה או הערך הפרימיטיבי שלה
  • מרחב שמות- המתאר את מרחב השמות אליו שייכת הסכימה הנתונה
  • שֵׁם - שם הסכימה
  • שדות- המספר על השדות המשויכים לסכמה נתונה. שדות יכולים להיות מסוג פרימיטיבי וגם מורכב.

אחת הדרכים ליצור את הסכימה היא לכתוב את ייצוג JSON, כפי שראינו בסעיפים הקודמים.

אנו יכולים גם ליצור סכמה באמצעות SchemaBuilder שהיא ללא ספק דרך טובה ויעילה ליצור אותה.

6.1. SchemaBuilder תוֹעֶלֶת

הכיתה org.apache.avro.SchemaBuilder שימושי ליצירת הסכימה.

קודם כל, בואו ליצור את הסכימה עבור ClientIdentifier:

סכימה clientIdentifier = SchemaBuilder.record ("ClientIdentifier"). מרחב שמות ("com.baeldung.avro") .fields (). RequiredString ("hostName"). RequiredString ("ipAddress"). EndRecord ();

עכשיו, בואו נשתמש בזה ליצירת avroHttpRequest סכֵימָה:

Schema avroHttpRequest = SchemaBuilder.record ("AvroHttpRequest"). Namespace ("com.baeldung.avro") .fields (). RequiredLong ("requestTime") .name ("clientIdentifier") .type (clientIdentifier) ​​.noDefault (). שם ("עובדNames") .type () .array () .items () .stringType () .arrayDefault (null) .name ("פעיל") .type () .ציון ("פעיל") .סימבולים ("YES "," NO ") .noDefault (). EndRecord ();

חשוב לציין כאן שהקצבנו clientIdentifier כסוג עבור clientIdentifier שדה. במקרה הזה, clientIdentifier המשמש להגדרת סוג הוא אותה סכמה שיצרנו קודם.

בהמשך נוכל להחיל את toString שיטה להשיג את ג'סון מבנה של סכֵימָה.

קבצי סכימה נשמרים באמצעות הסיומת .avsc. בואו נשמור את הסכימה שנוצרה ל "Src / main / resources / avroHttpRequest-schema.avsc" קוֹבֶץ.

7. קריאת הסכימה

קריאת סכמה היא פחות או יותר בערך יצירת שיעורי אברו לסכמה הנתונה. לאחר שנוצרו שיעורי אברו נוכל להשתמש בהם לסידור וסיווג מחדש של אובייקטים.

ישנן שתי דרכים ליצור שיעורי Avro:

  • ייצור תכנותי שיעורי Avro: ניתן ליצור שיעורים באמצעות SchemaCompiler. ישנם כמה ממשקי API בהם אנו יכולים להשתמש ליצירת שיעורי Java. אנו יכולים למצוא את הקוד לשיעורי דור ב- GitHub.
  • באמצעות Maven להפקת שיעורים

יש לנו תוסף אחד של maven שעושה את העבודה היטב. עלינו לכלול את התוסף ולהפעיל mvn נקי להתקין.

בואו נוסיף את התוסף שלנו pom.xml קוֹבֶץ:

 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. סדרת ועריקול עם Avro

לאחר שסיימנו לייצר את הסכימה, נמשיך לחקור את החלק הסידורי.

ישנם שני פורמטים של סידורי נתונים אשר Avro תומך בהם: פורמט JSON ופורמט בינארי.

ראשית נתמקד בפורמט JSON ואז נדון בפורמט הבינארי.

לפני שנמשיך הלאה, עלינו לעבור על כמה ממשקי מפתח. אנו יכולים להשתמש בממשקים והשיעורים הבאים לסידור:

DatumWriter: עלינו להשתמש בזה כדי לכתוב נתונים על סכמה נתונה. נשתמש ב- SpecificDatumWriter עם זאת, DatumWriter יש יישומים אחרים גם כן. יישומים אחרים הם GenericDatumWriter, Json.Writer, ProtobufDatumWriter, ReflectDatumWriter, ThriftDatumWriter.

קוֹדַאִי: מקודד משמש או מגדיר את הפורמט כאמור לעיל. EncoderFactory מספק שני סוגים של מקודדים, מקודד בינארי ומקודד JSON.

DatumReader: ממשק יחיד להסרת סדרה. שוב, יש לו מספר יישומים, אבל נשתמש SpecificDatumReader בדוגמה שלנו. יישומים אחרים הם- GenericDatumReader, Json.ObjectReader, Json.Reader, ProtobufDatumReader, ReflectDatumReader, ThriftDatumReader.

מפענח: נעשה שימוש במפענח בעת ביטול סדרת הנתונים. מפענח מפענח מספק שני סוגים של מפענחים: מפענח בינארי ומפענח JSON.

לאחר מכן, בואו נראה כיצד סדרות והסרת סדרות מתרחשות באברו.

8.1. סידור

ניקח את הדוגמה של AvroHttpRequest בכיתה ונסה לסדר אותה באמצעות Avro.

קודם כל, בואו לסדר אותו בפורמט JSON:

בתים ציבוריים [] serealizeAvroHttpRequestJSON (בקשת AvroHttpRequest) {כותב DatumWriter = SpecificDatumWriter חדש (AvroHttpRequest.class); בתים [] נתונים = בתים חדשים [0]; זרם ByteArrayOutputStream = ByteArrayOutputStream חדש (); מקודד jsonEncoder = null; נסה את {jsonEncoder = EncoderFactory.get (). jsonEncoder (AvroHttpRequest.getClassSchema (), stream); writer.write (בקשה, jsonEncoder); jsonEncoder.flush (); נתונים = stream.toByteArray (); } לתפוס (IOException e) {logger.error ("שגיאת סידור:" + e.getMessage ()); } להחזיר נתונים; } 

בואו נסתכל על מקרה מבחן לשיטה זו:

@ מבחן ציבורי בטל כאשר Serialized_UsingJSONEncoder_ObjectGetsSerialized () {byte [] data = serealizer.serealizeAvroHttpRequestJSON (בקשה); assertTrue (Objects.nonNull (נתונים)); assertTrue (data.length> 0); }

הנה השתמשנו ב- jsonEncoder שיטה והעברת הסכימה אליה.

אם היינו רוצים להשתמש במקודד בינארי, עלינו להחליף את ה- jsonEncoder () שיטה עם binaryEncoder ():

מקודד jsonEncoder = EncoderFactory.get (). BinaryEncoder (זרם, null);

8.2. התפטרות

לשם כך נשתמש באמור לעיל DatumReader ו מפענח ממשקים.

כמו שהשתמשנו EncoderFactory להשיג קוֹדַאִי, באופן דומה נשתמש מפענח מפעל לקבל מפענח לְהִתְנַגֵד.

בואו לבטל את סדרת הנתונים באמצעות פורמט JSON:

AvroHttpRequest ציבורי deSerealizeAvroHttpRequestJSON (נתונים בתים []) {קורא DatumReader = SpecificDatumReader חדש (AvroHttpRequest.class); מפענח מפענח = null; נסה {decoder = DecoderFactory.get (). jsonDecoder (AvroHttpRequest.getClassSchema (), מחרוזת חדשה (נתונים)); להחזיר reader.read (null, מפענח); } לתפוס (IOException e) {logger.error ("שגיאת עריקה:" + e.getMessage ()); }} 

ובואו נראה את מקרה הבדיקה:

@ מבחן פומבי בטל כאשר DeserializeUsingJSONDecoder_thenActualAndExpectedObjectsAreEqual () {byte [] data = serealizer.serealizeAvroHttpRequestJSON (בקשה); AvroHttpRequest actualRequest = deSerealizer. DeSerealizeAvroHttpRequestJSON (נתונים); assertEquals (בקשה בפועל, בקשה); assertTrue (actualRequest.getRequestTime () .equals (request.getRequestTime ())); }

באופן דומה, אנו יכולים להשתמש במפענח בינארי:

מפענח מפענח = DecoderFactory.get (). BinaryDecoder (נתונים, null);

9. מסקנה

Apache Avro שימושי במיוחד בעת התמודדות עם נתונים גדולים. הוא מציע סידור נתונים בפורמט בינארי כמו גם בפורמט JSON בו ניתן להשתמש בהתאם למקרה השימוש.

תהליך הסידור של Avro מהיר יותר, וגם יעיל במקום. Avro לא שומר את המידע על סוג השדה בכל שדה; במקום זאת, הוא יוצר מטא נתונים בסכימה.

אחרון חביב לאברו יש כריכה נהדרת עם מגוון רחב של שפות תכנות, מה שמעניק לה יתרון.

כמו תמיד, ניתן למצוא את הקוד ב- GitHub.