מסרים אמינים עם קבוצות JG

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

JGroups הוא API של Java להחלפת הודעות אמינה. הוא כולל ממשק פשוט המספק:

  • מחסנית פרוטוקולים גמישה, הכוללת TCP ו- UDP
  • פיצול והרכבה מחדש של מסרים גדולים
  • חד אמצעי שידור ורב-שידור אמינים
  • איתור כשלים
  • בקרת זרימה

כמו גם תכונות רבות אחרות.

במדריך זה ניצור יישום פשוט להחלפה חוּט הודעות בין יישומים ומספקים מצב משותף ליישומים חדשים כשהם מצטרפים לרשת.

2. התקנה

2.1. תלות של Maven

עלינו להוסיף תלות אחת שלנו pom.xml:

 org.jgroups jgroups 4.0.10. גמר 

ניתן לבדוק את הגרסה האחרונה של הספרייה ב- Maven Central.

2.2. נטוורקינג

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

כדי למנוע זאת, נגדיר את java.net.preferIPv4Stack ל נָכוֹן מאפיין בעת ​​הפעלת היישומים שלנו כאן:

java -Djava.net.preferIPv4Stack = com.baeldung.jgroups. true 

3. ערוצי J

החיבור שלנו לרשת JGroups הוא JChannel. הערוץ מצטרף לאשכול ושולח ומקבל הודעות, כמו גם מידע על מצב הרשת.

3.1. יצירת ערוץ

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

ניצור ערוץ עם קובץ תצורה בשם מפורש:

ערוץ JChannel = JChannel חדש ("src / main / resources / udp.xml"); 

תצורת JGroups יכולה להיות מאוד מסובכת, אך תצורות ה- UDP וה- TCP המוגדרות כברירת מחדל מספיקות עבור רוב היישומים. הכנסנו את הקובץ ל- UDP לקוד שלנו ונשתמש בו לצורך הדרכה זו.

למידע נוסף על הגדרת התעבורה עיין במדריך JGroups כאן.

3.2. חיבור ערוץ

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

הצטרפות לאשכול מחייבת שם אשכול:

channel.connect ("באלדונג"); 

הצומת הראשון שמנסה להצטרף לאשכול ייצור אותו אם הוא לא קיים. נראה את התהליך הזה בפעולה בהמשך.

3.3. מתן שמות לערוץ

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

channel.name ("user1");

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

3.4. סוגרים ערוץ

ניקוי ערוצים חיוני אם אנו רוצים שהעמיתים יקבלו התראה בזמן שעזבנו.

אנחנו סוגרים א JChannel בשיטה הקרובה שלה:

channel.close ()

4. שינויים בתצוגת אשכול

עם JChannel שנוצר אנו מוכנים כעת לראות את מצב העמיתים באשכול ולהחליף איתם הודעות.

JGroups שומר על מצב האשכול בתוך ה- נוף מעמד. לכל ערוץ יש יחיד נוף של הרשת. כאשר התצוגה משתנה, היא מועברת דרך viewAccepted () התקשר חזרה.

להדרכה זו, נרחיב את ReceiverAdaptor מחלקת API המיישמת את כל שיטות הממשק הנדרשות ליישום.

זו הדרך המומלצת ליישם התקשרות חוזרות.

בואו נוסיף viewAccepted ליישום שלנו:

view void public accepted (הצג newView) {private View lastView; אם (lastView == null) {System.out.println ("התצוגה הראשונית שהתקבלה:"); newView.forEach (System.out :: println); } אחר {System.out.println ("קיבלה תצוגה חדשה."); רשימת newMembers = View.newMembers (lastView, newView); System.out.println ("חברים חדשים:"); newMembers.forEach (System.out :: println); רשימה exMembers = View.leftMembers (lastView, newView); System.out.println ("חברים שיצאו:"); exMembers.forEach (System.out :: println); } lastView = newView; } 

כל אחד נוף מכיל א רשימה שֶׁל כתובת אובייקטים, המייצגים כל חבר באשכול. JGroups מציעה שיטות נוחות להשוואת תצוגה אחת לאחרת, בה אנו משתמשים כדי לאתר חברים חדשים או עזיבה מהאשכול.

5. שליחת הודעות

הטיפול בהודעות ב- JGroups הוא פשוט. א הוֹדָעָה מכיל א בתים מערך ו כתובת אובייקטים המתאימים לשולח ולמקלט.

לצורך הדרכה זו אנו משתמשים מיתרים לקרוא משורת הפקודה, אך קל לראות כיצד יישום יכול להחליף סוגי נתונים אחרים.

5.1. הודעות שידור

א הוֹדָעָה נוצר עם יעד ומערך בתים; JChannel מגדיר לנו את השולח. אם היעד הוא ריק, כל האשכול יקבל את ההודעה.

אנו נקבל טקסט משורת הפקודה ונשלח אותו לאשכול:

System.out.print ("הזן הודעה:"); קו מחרוזת = in.readLine (). ToLowerCase (); הודעת הודעה = הודעה חדשה (null, line.getBytes ()); channel.send (הודעה); 

אם אנו מריצים מספר מופעים של התוכנית ושולחים הודעה זו (לאחר יישום ה- לְקַבֵּל() בשיטה למטה), כולם יקבלו את זה, כולל השולח.

5.2. חסימת המסרים שלנו

אם איננו רוצים לראות את ההודעות שלנו, אנו יכולים להגדיר מאפיין לכך:

channel.setDiscardOwnMessages (נכון); 

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

5.3. הודעות ישירות

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

הנוכחי נוף זמין תמיד מה- JChannel:

פרטי getAddress (שם מחרוזת) אופציונלי {View view = channel.view (); להחזיר view.getMembers (). stream () .filter (address -> name.equals (address.toString ())) .findAny (); } 

כתובת שמות זמינים דרך הכיתה toString () שיטה, לכן אנו רק מחפשים את רשימה של חברי אשכול לשם שאנחנו רוצים.

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

יעד כתובת = null; System.out.print ("הזן יעד:"); מחרוזת destinationName = in.readLine (). ToLowerCase (); destination = getAddress (destinationName) .orElseThrow (() -> חריג חדש ("יעד לא נמצא"); הודעת הודעה = הודעה חדשה (יעד, "שלום!"); channel.send (הודעה); 

6. קבלת הודעות

אנחנו יכולים לשלוח הודעות, עכשיו בואו נוסיף נסה לקבל אותן עכשיו.

בואו נעקוף מקלט Adaptor שיטת קבלה ריקה:

קבלת חלל ציבורי (הודעת הודעה) {String line = הודעה שהתקבלה מ: "+ message.getSrc () +" אל: "+ message.getDest () +" -> "+ message.getObject (); System.out.println (קו);} 

מכיוון שאנחנו יודעים שההודעה מכילה חוּטאנחנו יכולים לעבור בבטחה getObject () ל System.out.

7. בורסת המדינה

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

כאשר צומת מצטרף לאשכול, הוא פשוט מתקשר getState (). האשכול בדרך כלל שולף את המדינה מהחבר הוותיק ביותר בקבוצה - הרכז.

בואו להוסיף ספירת הודעות משודרת ליישום שלנו. נוסיף משתנה חבר חדש ונגדיל אותו בתוכו לְקַבֵּל():

פרטי מספר שלם פרטיCount = 0; קבלת חלל פומבי (הודעת הודעה) {String line = "הודעה שהתקבלה מ:" + message.getSrc () + "אל:" + message.getDest () + "->" + message.getObject (); System.out.println (קו); אם (message.getDest () == null) {messageCount ++; System.out.println ("ספירת הודעות:" + MessageCount); }} 

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

לאחר מכן, אנו עוקפים שתי שיטות נוספות ב- ReceiverAdaptor:

חלל ציבורי setState (קלט InputStream) {נסה {messageCount = Util.objectFromStream (DataInputStream חדש (קלט)); } לתפוס (חריג e) {System.out.println ("מצב עריקת שגיאה!"); } System.out.println (messageCount + "הוא מספר המסרים הנוכחי."); } בטל פומבי getState (פלט OutputStream) זורק Exception {Util.objectToStream (messageCount, DataOutputStream חדש (פלט)); } 

בדומה להודעות, מצב העברות של JGroups הוא מערך של בתים.

JGroups מספקת InputStream לרכז לכתוב את המדינה אליה, ו OutputStream לקריאת הצומת החדש. ממשק ה- API מספק שיעורי נוחות לסידור וניתוק עריכת הנתונים.

שים לב שבקוד ייצור הגישה למידע המדינה חייבת להיות בטוחה בשרשור.

לבסוף, אנו מוסיפים את השיחה אל getState () לסטארט-אפ שלנו, אחרי שאנחנו מתחברים לאשכול:

channel.connect (clusterName); channel.getState (null, 0); 

getState () מקבל יעד שממנו לבקש את המדינה ואת פסק הזמן באלפיות השנייה. א ריק יעד מציין את הרכז ו -0 פירושו אינו פסק זמן.

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

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

8. מסקנה

במדריך זה השתמשנו ב- JGroups כדי ליצור יישום להחלפת הודעות. השתמשנו בממשק ה- API לניטור אילו צמתים התחברו לאשכול ועזבו אותו וגם כדי להעביר את מצב האשכול לצומת חדש כשהוא הצטרף.

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