דפוסי אינטגרציה עם גמל אפאצ'י

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

מאמר זה יעסוק בכמה דפוסי אינטגרציה ארגוניים חיוניים (EIP) הנתמכים על ידי Apache Camel. דפוסי שילוב עוזרים על ידי מתן פתרונות לדרכים סטנדרטיות לשילוב מערכות.

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

2. אודות EIP

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

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

2. נתב מבוסס תוכן

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

זה מתחיל ב בְּחִירָה() הצהרת DSL ואחריה אחת או יותר מתי() הצהרות DSL. כל אחד מתי() מכיל ביטוי פרדיקטי אשר, אם יתקיים, יביא לביצוע שלבי עיבוד כלולים.

בואו להמחיש את ה- EIP על ידי הגדרת מסלול הצורך קבצים מתיקיה אחת ומעביר אותם לשתי תיקיות שונות בהתאם לסיומת הקובץ. המסלול שלנו מוזכר בקובץ XML באביב באמצעות תחביר XML מותאם אישית עבור גמל:

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

לחלופין, נוכל להשתמש כאן בגישת תצורת Spring Java, בניגוד לשימוש בקובץ XML של Spring. לשם כך, עלינו להוסיף תלות נוספת לפרויקט שלנו:

 org.apache.camel camel-spring-javaconfig 2.18.1 

הגרסה האחרונה של החפץ נמצאת כאן.

אחרי זה, אנחנו צריכים להאריך תצורת גמלים מחלקה ועקיפה מסלולים () שיטה אשר תתייחס אליה ContentBasedFileRouter:

@Configuration מחלקה ציבורית ContentBasedFileRouterConfig מרחיב את CamelConfiguration {@Bean ContentBasedFileRouter getContentBasedFileRouter () {להחזיר ContentBasedFileRouter חדש (); } @ מסלול רשימת ציבורי @Override () {Return Arrays.asList (getContentBasedFileRouter ()); }}

הרחבה מוערכת באמצעות שפת ביטוי פשוטה באמצעות פָּשׁוּט() הצהרת DSL שנועדה לשמש להערכת ביטויים וחיזויים:

מחלקה ציבורית ContentBasedFileRouter מרחיב את RouteBuilder {סופי סטטי פרטי מחרוזת SOURCE_FOLDER = "src / test / source-folder"; סופי סטטי פרטי מחרוזת DESTINATION_FOLDER_TXT = "src / test / destination-folder-txt"; סופי סטטי פרטי מחרוזת DESTINATION_FOLDER_OTHER = "src / test / destination-folder-other"; @ קביעת תצורה ריקה בטלפון @ (עקירה) זורקת חריג {מ ("file: //" + SOURCE_FOLDER + "? Delete = true"). בחירה (). מתי (פשוט ("$ {file: ext} == 'txt'") )) .to ("file: //" + DESTINATION_FOLDER_TXT). אחרת () .to ("file: //" + DESTINATION_FOLDER_OTHER); }}

כאן אנו משתמשים בנוסף אחרת() הצהרת DSL על מנת לנתב את כל ההודעות שאינן מספקות את הפרדיקטים שניתנו עם מתי() הצהרות.

3. מתרגם הודעות

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

תומך בגמל MessageTranslator נתב המאפשר לנו להמיר הודעות באמצעות מעבד מותאם אישית בלוגיקת הניתוב, באמצעות שעועית ספציפית לביצוע השינוי או באמצעות שינוי צורה() הצהרת DSL.

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

בואו נדגים כיצד להשתמש במתרגם הודעות באמצעות שינוי צורה() הַצהָרָה:

class class MessageTranslatorFileRouter מרחיב את RouteBuilder {פרטית סטטית סופית מחרוזת SOURCE_FOLDER = "src / test / source-folder"; סופי סטטי פרטי מחרוזת DESTINATION_FOLDER = "src / מבחן / תיקיית יעד"; @ קביעת תצורה ריקה בטלפון של @ (לזרוק) זורק חריג {מ ("file: //" + SOURCE_FOLDER + "? Delete = true") .transform (body (). Append (header (Exchange.FILE_NAME))) .to ("file : // "+ DESTINATION_FOLDER); }}

בדוגמה זו אנו מצרפים את שם הקובץ לתוכן הקובץ באמצעות שינוי צורה() הצהרה עבור כל קובץ מתיקיית המקור והעברת קבצים שהוסבו לתיקיית יעד.

4. Multicast

Multicast מאפשר לנו לנתב את אותה הודעה למערכת של נקודות קצה שונות ולעבד אותן בצורה שונה.

זה אפשרי באמצעות שידור רב () הצהרת DSL ואז על ידי רישום נקודות הקצה ושלבי העיבוד בתוכם.

כברירת מחדל, עיבוד בנקודות קצה שונות אינו מתבצע במקביל, אך ניתן לשנות זאת באמצעות parallelProcessing () הצהרת DSL.

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

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

מחלקה ציבורית MulticastFileRouter מרחיב את RouteBuilder {מחרוזת סופי סטטי פרטי SOURCE_FOLDER = "src / test / source-folder"; סופי סטטי פרטי מחרוזת DESTINATION_FOLDER_WORLD = "src / test / destination-folder-world"; סופי סטטי פרטי מחרוזת DESTINATION_FOLDER_HELLO = "src / test / destination-folder-hello"; @ קביעת תצורה בטלנית ברירה ציבורית () מעיפה חריג {מ ("file: //" + SOURCE_FOLDER + "? Delete = true") .multicast () .to ("direct: append", "direct: prepend"). End ( ); מ ("ישיר: נספח") .transform (גוף (). נספח ("עולם")). אל ("קובץ: //" + DESTINATION_FOLDER_WORLD); מ ("ישיר: prepend") .transform (body (). prepend ("שלום")). אל ("file: //" + DESTINATION_FOLDER_HELLO); }}

5. ספליטר

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

בניגוד ל- Multicast, ספליטר ישנה את ההודעה הנכנסת, בעוד ש- Multicast ישאיר אותה כמו שהיא.

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

מחלקה ציבורית SplitterFileRouter מרחיב את RouteBuilder {סופי סטטי פרטי מחרוזת SOURCE_FOLDER = "src / test / source-folder"; סופי סטטי פרטי מחרוזת DESTINATION_FOLDER = "src / מבחן / תיקיית יעד"; @ קביעת חלל ציבורי בטל ציבורי () זורק חריג {מ ("file: //" + SOURCE_FOLDER + "? Delete = true"). Split (body (). ConvertToString (). Tokenize ("\ n")). SetHeader ( Exchange.FILE_NAME, body ()) .to ("file: //" + DESTINATION_FOLDER); }}

6. ערוץ אותיות מתות

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

ערוץ אותיות מתות מאפשר לנו לשלוט במה שקורה עם הודעה ברגע שהיא לא נמסרה. באמצעות ערוץ Dead Letter נוכל לציין אם להפיץ את החריג שנזרק למתקשר ולאן לנתב את ה- Exchange שנכשל.

כאשר לא ניתן להעביר הודעה, ערוץ המכתבים המתים (אם משתמשים בה) יעביר את ההודעה לנקודת הסיום של האות המתה.

בואו נדגים זאת בדוגמה על ידי השלכת חריג למסלול:

מחלקה ציבורית DeadLetterChannelFileRouter מרחיב את RouteBuilder {פרטית סופית סטרינג מחרוזת SOURCE_FOLDER = "src / test / source-folder"; @Override public void configure () זורק Exception {errorHandler (deadLetterChannel ("log: dead? Level = ERROR") .maximumRedeliveries (3) .redeliveryDelay (1000) .retryAttemptedLogLevel (LoggingLevel.ERROR)); from ("file: //" + SOURCE_FOLDER + "? delete = true"). תהליך (exchange -> {זרוק IllegalArgumentException חדש ("חריג נזרק!");}); }}

כאן הגדרנו errorHandler אשר רושם משלוחים נכשלים ומגדיר אסטרטגיית משלוח מחדש. על פי הגדרה נסה שובAttemptedLogLevel (), כל ניסיון מסירה מחדש יירשם עם רמת יומן מוגדרת.

כדי שזה יהיה פונקציונלי לחלוטין, עלינו להגדיר תצורה של לוגר.

לאחר הפעלת בדיקה זו, הצהרות היומן הבאות גלויות במסוף:

ERROR DeadLetterChannel: 156 - המסירה נכשלה עבור (MessageId: ID-ZAG0025-50922-1481340325657-0-1 ב- ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). בניסיון מסירה: 0 נתפס: java.lang.IllegalArgumentException: חריג נזרק! ERROR DeadLetterChannel: 156 - המסירה נכשלה עבור (MessageId: ID-ZAG0025-50922-1481340325657-0-1 ב- ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). בניסיון מסירה: 1 נתפס: java.lang.IllegalArgumentException: חריג נזרק! ERROR DeadLetterChannel: 156 - אספקה ​​נכשלה עבור (MessageId: ID-ZAG0025-50922-1481340325657-0-1 ב- ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). בניסיון מסירה: 2 נתפסים: java.lang.IllegalArgumentException: חריג נזרק! ERROR DeadLetterChannel: 156 - אספקה ​​נכשלה עבור (MessageId: ID-ZAG0025-50922-1481340325657-0-1 ב- ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). בניסיון מסירה: 3 נתפסו: java.lang.IllegalArgumentException: חריג נזרק! שגיאה מתה: 156 - Exchange [ExchangePattern: InOnly, BodyType: org.apache.camel.component.file.GenericFile, Body: [גוף מבוסס קובץ: GenericFile [File.txt]]]

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

7. מסקנה

במאמר זה הצגנו מבוא לדפוסי אינטגרציה באמצעות אפאצ'י גמל והדגמנו אותם בכמה דוגמאות.

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

קוד ממאמר זה ניתן למצוא באתר GitHub.


$config[zx-auto] not found$config[zx-overlay] not found