מבוא לאוטובוס כור הפרויקט

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

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

2. היסודות של כור הפרויקט

2.1. למה כור?

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

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

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

2.2. תרחישים לדוגמא

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

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

3. תלות Maven

נתחיל להשתמש באוטובוס Project Reactor על ידי הוספת התלות הבאה שלנו pom.xml:

 io.projectreactor reactor-bus 2.0.8.RELEASE 

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

4. בניית אפליקציית הדגמה

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

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

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

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

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

4.1. POJO פשוט

ראשית, בואו ניצור מחלקת POJO שתייצג את נתוני ההודעות:

NotificationData בכיתה ציבורית {מזהה פרטי פרטי; שם מחרוזת פרטי; דוא"ל מחרוזת פרטי; סלולרי פרטי מחרוזת; // שיטות גטר וקובע}

4.2. שכבת השירות

בואו נגדיר שכבת שירות פשוטה:

ממשק ציבורי NotificationService {void initiateNotification (NotificationData notificationData) זורק InterruptedException; }

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

@Service מחלקה ציבורית NotificationServiceimpl מיישמת NotificationService {@Override public void initiateNotification (NotificationData notificationData) זורק InterruptedException {System.out.println ("שירות ההודעות התחיל עבור" + "מזהה הודעה:" + notificationData.getId ()); Thread.sleep (5000); System.out.println ("שירות ההודעות הסתיים עבור" + "מזהה הודעה:" + notificationData.getId ()); }}

שימו לב שכדי להמחיש תרחיש אמיתי של שליחת הודעות באמצעות SMS או שער דוא"ל, אנו מכוונים בכוונה עיכוב של חמש שניות initiateNotification שיטה עם Thread.sleep (5000).

כתוצאה מכך, כאשר חוט יכה בשירות, הוא ייחסם למשך חמש שניות.

4.3. הצרכן

בואו נקפוץ להיבטים היותר תגוביים של היישום שלנו וניישם צרכן - אותו נמפה לאוטובוס האירועים בכור:

@Service בכיתה ציבורית NotificationConsumer מיישם את הצרכן {@ שירות הודעות שירות NotificationService פרטי; @ קביעת חלל ציבורי באופן קבוע (NotificationDataEvent של האירוע) {NotificationData notificationData = notificationDataEvent.getData (); נסה את {notificationService.initiateNotification (notificationData); } לתפוס (InterruptedException e) {// להתעלם}}}

כפי שאנו רואים, הצרכן שיצרנו מיישם את צרכן מִמְשָׁק. ההיגיון העיקרי שוכן ב לְקַבֵּל שיטה.

זו גישה דומה בה אנו יכולים לפגוש ביישום מאזין אופייני טיפוסי.

4.4. הבקר

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

אנו נעשה זאת בבקר פשוט:

@Controller NotificationController בכיתה ציבורית {@ EventBus פרטי EventBus פרטי; @GetMapping ("/ startNotification / {param}") public public startNotification (@PathVariable Parameter Integer) {עבור (int i = 0; i <param; i ++) {NotificationData data = new NotificationData (); data.setId (i); eventBus.notify ("notificationConsumer", Event.wrap (data)); System.out.println ("הודעה" + i + ": משימת התראות הוגשה בהצלחה"); }}}

זה די מובן מאליו - אנחנו פולטים אירועים דרך EventBus פה.

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

4.5. התצורה של Java

בואו כעת נרכיב הכל וניצור אפליקציית Spring Boot פשוטה.

ראשית, עלינו להגדיר את התצורה EventBus ו סביבה שעועית:

@Configuration public class Config {@Bean סביבה ציבורית סביבה () {return Environment.initializeIfEmpty (). AssignErrorJournal (); } @Bean EventBus ציבורי createEventBus (env סביבה) {return EventBus.create (env, Environment.THREAD_POOL); }}

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

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

EventBus evBus = EventBus.create (env, Environment.newDispatcher (REACTOR_CAPACITY, REACTOR_CONSUMERS_COUNT, DispatcherType.THREAD_POOL_EXECUTOR));

כעת, אנו מוכנים ליצור קוד יישום ראשי:

ייבוא ​​כור סטטי. bus.selector.Selectors. $; @SpringBootApplication הודעה בכיתה ציבורית NotificationApplication מיישם את CommandLineRunner {@AutBired פרטי EventBus eventBus; @ Autowired פרטי Notification צרכנים הודעה צרכנים; ריצה בטלנית ציבורית של @Override (String ... args) זורקת Exception {eventBus.on ($ ("notificationConsumer"), notificationConsumer); } ריק סטטי ציבורי ראשי (String [] args) {SpringApplication.run (NotificationApplication.class, args); }}

בשלנו לָרוּץ שיטה אנחנו רושמים את notificationConsumer שיופעל כאשר ההודעה תואמת לבורר נתון.

שימו לב כיצד אנו משתמשים בייבוא ​​הסטטי של ה- $ תכונה ליצור a בוחר לְהִתְנַגֵד.

5. בדוק את היישום

בואו ניצור מבחן כדי לראות את שלנו NotificationApplication בִּפְעוּלָה:

@RunWith (SpringRunner.class) @SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) NotificationApplicationIntegrationTest {@LocalServerPort כניסה פרטית פרטית; @ מבחן הריק ציבורי שניתן AppStarted_whenNotificationTasksSubmitted_thenProcessed () {RestTemplate restTemplate = RestTemplate חדש (); restTemplate.getForObject ("// localhost:" + port + "/ startNotification / 10", String.class); }}

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

הודעה 0: משימת ההודעה הוגשה בהצלחה התראה 1: משימת ההודעה הוגשה בהצלחה התראה 2: משימת ההודעה הוגשה בהצלחה התראה 3: משימת ההודעה הוגשה בהצלחה הודעה 4: משימת ההודעה הוגשה בהצלחה הודעה 5: משימת ההודעה הוגשה בהצלחה הודעה 6: משימת ההודעה הוגשה בהצלחה 7: משימת ההודעה הוגשה בהצלחה התראה 8: משימת ההודעה הוגשה בהצלחה התראה 9: משימת ההודעה הוגשה בהצלחה שירות ההודעות התחיל עבור מזהה ההודעה: 1 שירות ההודעות התחיל עבור מזהה ההודעה: 2 שירות ההודעות התחיל עבור מזהה ההודעה: 3 שירות ההודעות התחיל עבור מזהה ההודעה : 0 שירות ההודעות הסתיים עבור מזהה ההודעה: 1 שירות ההודעות הסתיים עבור מזהה ההתראה: 0 שירות ההתראות התחיל עבור מזהה ההודעה: 4 שירות ההודעות הסתיים עבור מזהה ההודעה: 3 שירות ההודעות הסתיים עבור מזהה הודעה: 2 שירות ההודעות התחיל עבור מזהה ההודעה: 6 שירות ההודעות התחיל עבור מזהה ההודעה: 5 שירות ההודעות התחיל עבור מזהה ההודעה: 7 שירות ההודעות הסתיים עבור מזהה ההודעה: 4 שירות ההודעות התחיל עבור מזהה ההתראה: 8 שירות ההודעות הסתיים מזהה הודעה: 6 שירות ההודעות הסתיים עבור מזהה ההודעה: 5 שירות ההתראות התחיל עבור מזהה ההתראה: 9 שירות ההתראות הסתיים עבור מזהה ההודעה: 7 שירות ההודעות הסתיים עבור מזהה ההודעה: 8 שירות ההודעות הסתיים עבור מזהה ההודעה: 9

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

6. מסקנה

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

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

כמו תמיד, קוד המקור זמין ב- GitHub.


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