מסגרת האביב מאסטרינג 5, חלק 2: אביב WebFlux

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

מדריכי אביב על JavaWorld

אם אתה לא חדש בתחום האביב, אני ממליץ להתחיל באחת מהמדריכים הקודמים בסדרה זו:

  • מהו אביב? פיתוח מבוסס רכיבים עבור Java
  • מסגרת האביב המאסטרינג 5: MVC האביב

מערכות תגובתיות ו- Spring WebFlux

המונח תגובתי פופולרי כיום בקרב מפתחים ומנהלי IT, אך שמתי לב לחוסר וודאות לגבי משמעותו בפועל. כדי להבין יותר טוב מהן מערכות תגובתיות, כדאי להבין את הבעיה הבסיסית שתוכננה לפתור. בחלק זה נדבר על מערכות תגובתיות באופן כללי, ואציג את ה- Reactive Streams API ליישומי Java.

מדרגיות ב- MVC באביב

אביב MVC זכה במקומו בין האפשרויות המובילות ביותר לבניית יישומי אינטרנט ושירותי אינטרנט של Java. כפי שגילינו במסגרת Mastering Spring 5, חלק 1, Spring MVC משלב בצורה חלקה ביאורים בארכיטקטורה החזקה של יישום מבוסס אביב. זה מאפשר למפתחים המכירים את Spring לבנות במהירות יישומי אינטרנט מספקים ופונקציונליים במיוחד. מדרגיות היא אתגר עבור יישומי אביב MVC. זו הבעיה ש- Spring WebFlux מבקשת לטפל בה.

חסימה לעומת מסגרות אינטרנט שאינן חוסמות

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

סטיבן היינס

מסגרות אינטרנט לא חוסמות כגון NodeJS ו- Play נוקטות בגישה שונה. במקום לבצע בקשת חסימה ולהמתין להשלמתה, הם משתמשים ב- I / O שאינו חוסם. בפרדיגמה זו, יישום מבצע בקשה, מספק קוד לביצוע כאשר תשובה מוחזרת ואז מחזיר את השרשור לשרת. כאשר משאב חיצוני מחזיר תגובה, הקוד שבוצע יבוצע. באופן פנימי, מסגרות שאינן חוסמות פועלות באמצעות לולאת אירועים. בתוך הלולאה, קוד היישום מספק שיחה חוזרת או עתיד המכיל את הקוד לביצוע לאחר השלמת הלולאה האסינכרונית.

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

התקשרות, הבטחות וחוזים עתידיים

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

תכנות תגובתי

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

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

איור 2 מראה כיצד תכונות אלה זורמות יחדיו במערכת תגובתי.

סטיבן היינס

מאפייני מערכת תגובתי

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

המניפסט הריאקטיבי הוא מופשט, אך יישומים תגובתי מתאפיינים הרכיבים או הטכניקות הבאות:

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

ממשק ה- API של זרמים ריאקטיביים

ה- API החדש של זרמים ריאקטיביים נוצר על ידי מהנדסים מ- Netflix, Pivotal, Lightbend, RedHat, Twitter ו- Oracle, בין היתר. פורסם בשנת 2015, ה- Reactive Streams API הוא כעת חלק מג'אווה 9. הוא מגדיר ארבעה ממשקים:

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

איור 3 מציג את הקשר בין מפרסם, מנוי ומנוי.

סטיבן היינס

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

כעת, כשיודעים מעט על מערכות תגובתיות ועל ממשק ה- API של זרמים ריאקטיביים, בואו נפנה את תשומת ליבנו לכלים ש- Spring משתמשת בהם כדי להטמיע מערכות תגובתיות: Spring WebFlux וספריית הכורים.

כור הפרויקט

Project Reactor היא מסגרת של צד שלישי המבוססת על מפרט הזרמים התגוביים של Java, המשמש לבניית יישומי אינטרנט שאינם חוסמים. Project Reactor מספק שני מפרסמים שמשתמשים בהם רבות ב- Spring WebFlux:

  • מונו : מחזיר 0 או 1 אלמנט.
  • שטף : מחזיר 0 אלמנטים או יותר. שטף יכול להיות אינסופי, כלומר הוא יכול להמשיך ולפלט אלמנטים לנצח, או שהוא יכול להחזיר רצף של אלמנטים ואז לשלוח הודעת סיום כאשר הוא החזיר את כל האלמנטים שלו.

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

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

תכנות תגובתי עם MongoDB

נכון לעכשיו, אין הרבה ספריות מסדי נתונים תגובתיות, כך שאולי אתה תוהה אם זה מעשי לכתוב שירותים תגוביים. החדשות הטובות הן של- MongoDB יש תמיכה תגובתית ויש כמה מנהלי מסדי נתונים תגובתי של צד שלישי עבור MySQL ו- Postgres. בכל מקרי השימוש האחרים, WebFlux מספק מנגנון לביצוע שיחות JDBC באופן תגובתי, אם כי באמצעות מאגר חוטים משני שעושה חסימת שיחות JDBC.

התחל לעבוד עם Spring WebFlux

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

התחל בנווט אל דף הבית של Spring Initializr, שם תבחר פרויקט Maven עם Java ותבחר במהדורה העדכנית ביותר של Spring Boot (2.0.3 בזמן כתיבת שורות אלה). תן לפרויקט שלך שם קבוצתי, כגון "com.javaworld.webflux", ושם חפץ, כגון "שירות ספרים". הרחב את המעבר לקישור הגרסה המלאה כדי להציג את רשימת התלות המלאה. בחר את התלות הבאות עבור היישום לדוגמה:

  • אינטרנט -> אינטרנט תגובתי : תלות זו כוללת Spring WebFlux.
  • NoSQL -> MongoDB תגובתי : תלות זו כוללת את מנהלי ההתקן המגיבים עבור MongoDB.
  • NoSQL -> Embedded MongoDB : תלות זו מאפשרת לנו להריץ גרסה מוטמעת של MongoDB, כך שאין צורך להתקין מופע נפרד. בדרך כלל זה משמש לבדיקה, אך נכלול אותו בקוד השחרור שלנו כדי להימנע מהתקנת MongoDB.
  • Core -> Lombok : השימוש ב- Lombok הוא אופציונלי מכיוון שאתה לא צריך את זה כדי לבנות יישום Spring WebFlux. היתרון של שימוש פרויקט Lombok הוא שזה מאפשר לכם להוסיף הערות כיתות כי יהיה ליצור באופן אוטומטי עסקנים ו קובעים, בנאים, hashCode(), equals(), ועוד.

כשתסיים אתה אמור לראות משהו דומה לאיור 4.

סטיבן היינס

לחיצה על Generate Project תגרום להורדת קובץ zip המכיל את קוד המקור של הפרויקט. פתח את הקובץ שהורדת ופתח אותו ב- IDE המועדף עליך. אם אתה משתמש ב- IntelliJ, בחר קובץ ואז פתח ונווט לספרייה בה דחיסה של קובץ ה- zip שהורדת.

תגלה כי אביב Initializr יצר שני קבצים חשובים:

  1. pom.xmlקובץ Maven , הכולל את כל התלות הדרושה ליישום.
  2. BookserviceApplication.java, שהוא כיתת המתנע של Spring Boot ליישום.

רישום 1 מציג את התוכן של קובץ pom.xml שנוצר.