במדריך זה תלמדו מהם שירותי מיקרו של Java, כיצד לעצב וליצור אותם. זה גם מכסה שאלות על ספריות מיקרו-שירותי Java ועל היתכנות השימוש בשירותי מיקרו. תרגום והתאמה של Java Microservices: מדריך מעשי .
Java Microservices: יסודות
כדי להבין מיקרו-שירותים, תחילה עליך להגדיר מה הם לא. האם זה לא "מונוליט" - מונוליט ג'אווה: מה זה ומה היתרונות או החסרונות שלו?מהו מונוליט ג'אווה?
תאר לעצמך שאתה עובד עבור בנק או סטארטאפ פינטק. אתה מספק למשתמשים אפליקציה לנייד שבה הם יכולים להשתמש כדי לפתוח חשבון בנק חדש. בקוד Java זה יגרום לנוכחות של מחלקת בקר. בפשטות, זה נראה כך:@Controller
class BankController {
@PostMapping("/users/register")
public void register(RegistrationForm form) {
validate(form);
riskCheck(form);
openBankAccount(form);
// etc..
}
}
אתה צריך את הבקר כדי:
- אישר את טופס ההרשמה.
- בדק את הסיכונים בכתובת המשתמש כדי להחליט אם לספק לו חשבון בנק.
- פתח חשבון בנק.
BankController
תיארז יחד עם שאר המקורות שלך לקובץ bank.jar או bank.war לצורך פריסה - זהו מונוליט ישן וטוב המכיל את כל הקוד הדרוש להפעלת הבנק שלך. כהערכה גסה, הגודל הראשוני של קובץ jar (או .war) ינוע בין 1 ל-100 MB. עכשיו אתה יכול פשוט להריץ את קובץ ה-.jar בשרת שלך... וזה כל מה שאתה צריך לעשות כדי לפרוס את יישום ה-Java שלך. תמונה, מלבן שמאל למעלה: פריסה של בנק מונו(ליטי) java -jar bank.jar (cp .war/.ear לתוך appserver). מלבן ימני: פתח דפדפן.
מה הבעיה עם מונוליטים של Java?
אין שום דבר רע מטבעו במונוליטים של Java. עם זאת, הניסיון הראה שאם בפרויקט שלך:- יש הרבה מתכנתים/צוותים/יועצים שעובדים...
- ...על אותו מונוליט תחת לחץ של לקוחות עם דרישות מאוד מעורפלות...
- תוך כמה שנים...
כיצד להקטין את הגודל של מונוליט ג'אווה?
מתעוררת שאלה טבעית: איך להקטין את המונוליט? כרגע bank.jar שלך פועל על JVM אחד, תהליך אחד על שרת אחד. לא יותר, לא פחות. וכרגע עלולה לעלות בראש מחשבה הגיונית: "אבל שירות אימות הסיכונים יכול לשמש מחלקות אחרות בחברה שלי! זה לא קשור ישירות לאפליקציה הבנקאית המונוליטית שלי! אולי צריך לחתוך אותו מהמונוליט ולפרוס אותו כמוצר נפרד? כלומר, מבחינה טכנית, להריץ אותו כתהליך Java נפרד."מהו מיקרו-שירות Java?
בפועל, הביטוי הזה אומר שכעת קריאת השיטהriskCheck()
לא תתבצע מ-BankController: שיטה זו או רכיב שעועית עם כל מחלקות העזר שלו יועברו לפרויקט Maven או Gradle משלו. זה גם ייפרס ויועבר תחת בקרת גרסאות ללא תלות במונוליט הבנקאי. עם זאת, כל תהליך החילוץ הזה לא הופך את מודול RiskCheck החדש שלך למיקרו-שירות כשלעצמו, מכיוון שההגדרה של מיקרו-שירות פתוחה לפרשנות. זה מוביל לדיונים תכופים בתוך צוותים וחברות.
- האם 5-7 כיתות בפרויקט מיקרו או מה?
- 100 או 1000 שיעורים... עדיין מיקרו?
- האם שירות מיקרו בדרך כלל קשור למספר השיעורים או לא?
- בואו נקרא לכל השירותים הפרוסים בנפרד למיקרו-שירותים, ללא קשר לגודלם או לגבולות הדומיין שלהם.
- בואו נחשוב איך לארגן תקשורת בין שירותים. שירותי המיקרו שלנו זקוקים לדרכים לתקשר זה עם זה.
כיצד ליצור תקשורת בין שירותי מיקרו Java?
באופן כללי ובכלל, קיימות שתי אפשרויות - תקשורת סינכרונית וא-סינכרונית.תקשורת סינכרונית: (HTTP)/REST
בדרך כלל, תקשורת מסונכרנת בין שירותי מיקרו מתרחשת באמצעות שירותים כמו HTTP ו-REST המחזירים XML או JSON. כמובן, עשויות להיות אפשרויות אחרות - קח לפחות מאגר פרוטוקול של Google . אם אתה צריך מענה מיידי, עדיף להשתמש בתקשורת REST. בדוגמה שלנו, זה בדיוק מה שצריך לעשות, מכיוון שנדרש אימות סיכונים לפני פתיחת חשבון. אם אין בדיקת סיכונים, אין חשבון. נדון בכלים להלן, בסעיף " אילו ספריות הן הטובות ביותר עבור קריאות Java REST סינכרוניות ".הודעות - תקשורת אסינכרונית
תקשורת מיקרו-שירות אסינכרונית מתבצעת בדרך כלל על ידי החלפת הודעות עם מימוש JMS ו/או שימוש בפרוטוקול כגון AMQP . כתבנו כאן "בדרך כלל" מסיבה: נניח שאי אפשר לזלזל במספר שילובי הדוא"ל/SMTP. השתמש בו כאשר אתה לא צריך תגובה מיידית. לדוגמה, המשתמש לוחץ על כפתור "קנה עכשיו", ואתה, בתורו, רוצה להפיק חשבונית. תהליך זה בהחלט לא אמור להתרחש בתוך מחזור בקשת הרכישה-תגובה של המשתמש. להלן נתאר אילו כלים הם הטובים ביותר עבור הודעות Java אסינכרוניות .דוגמה: קריאת REST API ב-Java
נניח שאנו בוחרים בתקשורת מיקרו שירות סינכרונית. במקרה זה, קוד ה-Java שלנו (זה שהצגנו למעלה) ברמה נמוכה ייראה בערך כך. (ברמה נמוכה כאן אנו מתכוונים לעובדה שעבור תקשורת מיקרו-שירותים, בדרך כלל נוצרות ספריות לקוח שמפשטות אותך מקריאות ה-HTTP בפועל).@Controller
class BankController {
@Autowired
private HttpClient httpClient;
@PostMapping("/users/register")
public void register(RegistrationForm form) {
validate(form);
httpClient.send(riskRequest, responseHandler());
setupAccount(form);
// etc..
}
}
בהתבסס על הקוד, מתברר שעלינו לפרוס שני שירותי Java (מיקרו), Bank ו-RiskCheck. כתוצאה מכך, יהיו לנו שני תהליכי JVM פועלים. זה כל מה שאתה צריך כדי לפתח פרויקט Java microservices: פשוט לבנות ולפרוס נתחים קטנים יותר (קובצי .jar או .war) במקום אחד מונוליטי. התשובה לשאלה נותרה לא ברורה: כיצד עלינו לחתוך את המונוליט לשירותי מיקרו? כמה קטנים צריכים להיות החלקים האלה, איך לקבוע את הגודל הנכון? בוא נבדוק.
ארכיטקטורת Java Microservices
בפועל, חברות מפתחות פרויקטי מיקרו-שירות בדרכים שונות. הגישה תלויה בשאלה האם אתה מנסה להפוך מונוליט קיים לפרויקט מיקרו-שירותים או להתחיל את הפרויקט מאפס.ממונוליט לשירותי מיקרו
אחד הרעיונות ההגיוניים ביותר הוא לחלץ שירותי מיקרו ממונוליט קיים. שימו לב שהקידומת "מיקרו" כאן לא אומרת למעשה שהשירותים שחולצו יהיו קטנים באמת; זה לא בהכרח המקרה. בואו נסתכל על הרקע התיאורטי.רעיון: לפרק את המונוליט למיקרו-שירותים
ניתן ליישם גישת מיקרו-שירות על פרויקטים מדור קודם. וזה למה:- לרוב קשה לתחזק/לשנות/להרחיב פרויקטים כאלה.
- כולם, ממפתחים ועד ניהול, רוצים פישוט.
- יש לך גבולות תחום ברורים (יחסית), כלומר אתה יודע בדיוק מה התוכנה שלך צריכה לעשות.
- לכן, יהיה זה הגיוני להפריד את העיבוד של נתוני המשתמש (כגון שמות, כתובות, מספרי טלפון) למיקרו-שירות נפרד "ניהול חשבון".
- או "מודול בודק סיכונים" הנ"ל שבודק את רמות הסיכון של המשתמש ויכול לשמש פרויקטים רבים אחרים או אפילו מחלקות בחברה.
- או מודול חשבונית ששולח חשבוניות בפורמט PDF או בדואר.
יישום רעיון: תן למישהו אחר לעשות את זה
הגישה שתוארה לעיל נראית נהדר על נייר ודיאגרמות דמויות UML. עם זאת, הכל לא כל כך פשוט. היישום המעשי שלו דורש הכנה טכנית רצינית: הפער בין ההבנה שלנו מה יהיה נחמד לחלץ ממונוליט לבין תהליך החילוץ עצמו הוא עצום. רוב הפרויקטים הארגוניים מגיעים לשלב שבו מפתחים חוששים, למשל, לשדרג גרסה בת 7 שנים של Hibernate לגרסה חדשה יותר. הספריות יתעדכנו יחד עם זה, אבל יש סכנה ממשית לשבור משהו. אז אותם מפתחים צריכים כעת לחפור בקוד מדור קודם עם גבולות עסקאות לא ברורים של מסד נתונים ולחלץ שירותי מיקרו מוגדרים היטב? לא פעם, בעיה זו מורכבת מאוד ולא ניתן "לפתור" אותה על לוח או בפגישות אדריכלות. כדי לצטט את מפתח הטוויטר @simonbrown: אני אגיד את זה שוב ושוב... אם אנשים לא יכולים לבנות מונוליטים בצורה נכונה, מיקרו-שירותים לא יעזרו. סיימון בראוןפרויקט מאפס מבוסס על ארכיטקטורת microservice
במקרה של פרויקטים חדשים של Java, שלוש הנקודות הממוספרות מהחלק הקודם נראות מעט שונות:- אתה מתחיל עם לוח נקי, כך שאין "כבודה" לשמור.
- המפתחים היו רוצים לשמור על דברים פשוטים בעתיד.
- בעיה: יש לך תמונה הרבה יותר מטושטשת של גבולות תחום: אתה לא יודע מה התוכנה שלך אמורה לעשות (רמז: זריז ;))
ארכיטקטורת מיקרו שירות טכנית
נראה שהנקודה הראשונה היא הברורה ביותר עבור מפתחים, אבל יש גם מי שמונעים ממנה בתוקף. האדי חרירי ממליצה על ה-Refactoring "Extract Microservice" ב-IntelliJ. ולמרות שהדוגמה הבאה מפושטת מאוד, ההטמעות שנצפו בפרויקטים אמיתיים, למרבה הצער, לא מתרחקות ממנה. לפני שירותי מיקרו@Service
class UserService {
public void register(User user) {
String email = user.getEmail();
String username = email.substring(0, email.indexOf("@"));
// ...
}
}
עם תת מחרוזת Java microservice
@Service
class UserService {
@Autowired
private HttpClient client;
public void register(User user) {
String email = user.getEmail();
//теперь вызываем substring microservice via http
String username = httpClient.send(substringRequest(email), responseHandler());
// ...
}
}
אז אתה בעצם עוטף קריאת שיטת Java בקריאת HTTP, ללא סיבה ברורה לעשות זאת. עם זאת, סיבה אחת היא זו: חוסר ניסיון וניסיון לכפות גישת מיקרו-שירותי Java. המלצה: אל תעשה זאת.
ארכיטקטורת מיקרו-שירותים מוכוונת זרימת עבודה
הגישה הנפוצה הבאה היא לחלק את שירותי המיקרו של Java למודולים מבוססי זרימת עבודה. דוגמה לחיים האמיתיים: בגרמניה, כאשר אתה הולך לרופא (ציבורי), הוא חייב לתעד את הביקור שלך במערכת ה-CRM הרפואית שלו. כדי לקבל תשלום מהביטוח, הוא ישלח נתונים על הטיפול שלך (והטיפול בחולים אחרים) למתווך באמצעות XML. המתווך יסתכל על קובץ ה-XML הזה ו(בפשטות):- יבדוק אם התקבל קובץ ה-XML הנכון.
- זה יבדוק את הסבירות של ההליכים: נניח, ילד בן שנה שקיבל שלושה הליכי ניקוי שיניים ביום אחד מרופא נשים נראה חשוד במקצת.
- ישלב XML עם כמה נתונים בירוקרטיים אחרים.
- יעביר את קובץ ה-XML לחברת הביטוח ליזום תשלומים.
- והוא יעביר את התוצאה לרופא, ויספק לו את ההודעה "הצלחה" או "אנא שלח מחדש את ההקלטה הזו ברגע שזה יהיה הגיוני."
- האם יש צורך לפרוס שש יישומים כדי לעבד קובץ XML אחד?
- האם שירותי המיקרו האלה באמת בלתי תלויים זה בזה? האם ניתן לפרוס אותם ללא תלות זה בזה? עם גרסאות וסכימות API שונות?
- מה עושה מיקרו-שירות האמינות אם מיקרו-שירות האימות לא עובד? האם המערכת עדיין עובדת?
- האם המיקרו-שירותים האלה חולקים את אותו מסד נתונים (הם בהחלט צריכים כמה נתונים נפוצים בטבלאות DB), או שלכל אחד מהם יש משלהם?
- … ועוד הרבה.
- אתה לא צריך רק לפרוס יישום אחד, אלא לפחות שישה.
- ייתכן אפילו שתצטרך לפרוס מסדי נתונים מרובים, תלוי כמה רחוק אתה רוצה ללכת לארכיטקטורת שירותי המיקרו.
- עליך לוודא שכל מערכת מקוונת ופועלת כהלכה.
- עליך לוודא שהשיחות שלך בין מיקרו-שירותים באמת גמישות (ראה כיצד להפוך מיקרו-שירותי Java לחוסן?).
- וכל מה שההגדרה הזו מרמזת - מהגדרות פיתוח מקומיות ועד לבדיקות אינטגרציה.
- אם אתה לא נטפליקס (רוב הסיכויים שאתה לא נטפליקס)...
- אלא אם כן יש לך כישורי עבודה סופר חזקים שבהם אתה פותח את סביבת הפיתוח וזה גורם לקוף כאוס שזורק את מסד הנתונים הייצור שלך אשר משוחזר בקלות תוך 5 שניות.
- או שאתה מרגיש כמו @monzo ומוכן לנסות 1500 מיקרו-שירותים רק בגלל שאתה יכול.
GO TO FULL VERSION