זהו המדריך השני בתוכנית לימודים שמסבירה איך ליצור מודולריזציה של אפליקציה מונוליטית ולהעביר אותה לקונטיינר.
תוכנית הלימודים כוללת את המדריכים הבאים:
- סקירה כללית
- הסבר על המונולית
- פירוק המונוליט למודולים (המדריך הזה)
- הכנת האפליקציה המודולרית להעברה לקונטיינר
- העברת האפליקציה המודולרית לקונטיינר
- פריסת האפליקציה באשכול GKE
במדריך הקודם, הסבר על המונולית, למדתם על אפליקציה מונוליתית בשם Cymbal Books. הפעלתם את המונוליט במחשב המקומי שלכם והבנתם שחלקים שונים במונוליט מתקשרים זה עם זה דרך נקודות הקצה שלהם.
במדריך הזה מוסבר איך לחלק את המונוליט למודולים כדי להכין אותו להעברה לקונטיינר. אתם לא צריכים לבצע את שלבי המודולריזציה בעצמכם כי הקוד כבר עודכן בשבילכם. המשימה שלך היא לפעול לפי ההוראות במדריך ולעיין בגרסה המודולרית של האפליקציה במאגר כדי לראות מה ההבדלים בינה לבין המונוליט המקורי.
עלויות
אפשר להשלים את המדריך הזה בלי לשלם על כלום. עם זאת, אם תבצעו את השלבים שמפורטים במדריך האחרון בסדרה הזו, יחולו חיובים על חשבוןGoogle Cloud . העלויות מתחילות כשמפעילים את GKE ופורסים את אפליקציית Cymbal Books באשכול GKE. העלויות האלה כוללות חיובים לכל אשכול ב-GKE, כפי שמפורט בדף התמחור, וחיובים על הפעלת מכונות וירטואליות ב-Compute Engine.
כדי להימנע מחיובים מיותרים, חשוב להשבית את GKE או למחוק את הפרויקט אחרי שמסיימים את המדריך הזה.
לפני שמתחילים
לפני שמתחילים את המדריך הזה, חשוב לוודא שסיימתם את המדריך הראשון, הסבר על המונולית. במדריך הזה מריצים את הגרסה המודולרית של Cymbal Books במחשב המקומי. כדי לעשות את זה, צריך להגדיר את הסביבה. אם כבר השלמתם את המדריך הראשון, שכפלתם מאגר GitHub. כל שלוש הגרסאות של אפליקציית Cymbal Books נמצאות במאגר הזה, בתיקיות הבאות:
monolith/modular/containerized/
לפני שממשיכים, צריך לוודא שהתיקיות האלה נמצאות במחשב. חשוב לוודא גם שהסביבה הווירטואלית book-review-env פעילה. אם אתם צריכים תזכורת לגבי אופן ההפעלה, תוכלו לעיין במאמר יצירה והפעלה של סביבה וירטואלית מהמדריך הראשון. הפעלת הסביבה מוודאת שבגרסה המודולרית של האפליקציה יש את כל מה שצריך כדי להפעיל אותה.
מהי מודולריזציה?
במדריך הזה תלמדו איך להפוך את האפליקציה המונוליטית למודולרית כדי להכין אותה להעברה לקונטיינר. מודולריזציה היא תהליך של הפיכת מונוליט לאפליקציה מודולרית. כמו שלמדתם במדריך הקודם, המאפיין המבחין של מונוליט הוא שהרכיבים שלו לא יכולים לפעול או להתרחב באופן עצמאי. אפליקציה מודולרית שונה: הפונקציונליות שלה מחולקת למודולים שיכולים לפעול ולהתרחב באופן עצמאי.
למרות שלרוב מבצעים מודולריזציה וקונטיינריזציה יחד, בסדרת המדריכים הזו אנחנו מתייחסים אליהם כאל שלבים נפרדים כדי לעזור לכם להבין כל מושג בבירור. במדריך הזה מוסבר איך להפוך מונוליט למודולרי, ובמדריך נוסף מוסבר איך להוסיף את האפליקציה המודולרית למאגר.
מודולריזציה מצטברת
בסביבות ייצור, בדרך כלל מחלקים למודולים רכיב אחד בכל פעם. אתם מחלקים את הרכיב למודולים, משלבים את המודול עם המונוליט ומוודאים שהכול פועל לפני שאתם עובדים על הרכיב הבא. מצב היברידי כזה, שבו חלק מהרכיבים מודולריים וחלקם נשארים חלק מהמונולית, נקרא מיקרולית. עם זאת, במדריך הזה, כל הרכיבים של האפליקציה עוברים מודולריזציה בו-זמנית כדי לספק דוגמה מלאה לאופן שבו מבצעים מודולריזציה של אפליקציה.
איך מחלקים את המונוליט למודולים
בקטע הזה נסביר איך המונוליט של Cymbal Books חולק למודולים נפרדים. השלבים מפורטים כדי לעזור לכם להבין את תהליך המודולריזציה, כך שתוכלו ליישם אותו באפליקציות שלכם. עם זאת, לא צריך לבצע את השלבים האלה במדריך הזה כי המאגר המשוכפל כבר כולל את הגרסה המודולרית של האפליקציה:
- זיהוי הפונקציות הייחודיות של האפליקציה
- יצירת המודולים
- הפעלת תקשורת בין המודולים
- הענקת גישה לכל מודול רק לנתונים שהוא צריך
זיהוי הפונקציות הייחודיות של האפליקציה
השלב הראשון בפיצול המונוליט של Cymbal Books למודולים הוא זיהוי הפונקציות העיקריות שלו. באפליקציית הדוגמה Cymbal Books, למונוליט יש את ארבע הפונקציות הנפרדות הבאות:
- הצגת דף הבית
- הצגת פרטי הספר
- הצגת ביקורות על ספרים
- הצגת תמונות שער של ספרים
יצירת המודולים
כפי שראיתם במדריך הקודם, המונוליט הוא אפליקציית Flask יחידה שמטמיעה את ארבע הפונקציות שזוהו בקטע הקודם כמטפלות בבקשות (route handlers). כדי להפוך את האפליקציה למודולרית, לוקחים כל handler של נתיב ומכניסים אותו לאפליקציית Flask משלו. במקום אפליקציית Flask אחת עם ארבעה handlers של נתיבים, יש ארבע אפליקציות Flask, שלכל אחת מהן יש handler יחיד של נתיב.
בתרשים הבא מוצג תהליך ההמרה מאפליקציית Flask אחת לארבע אפליקציות Flask נפרדות:

באפליקציה המודולרית, כל אפליקציית Flask פועלת באופן עצמאי ומאזינה ליציאה אחרת (8080, 8081, 8082, 8083), כמו שמוצג בתרשים. ההגדרה הזו נדרשת כי בהמשך המדריך הזה תבדקו את האפליקציה המודולרית, ותריצו את כל המודולים באותו מחשב. לכל אפליקציה צריך להיות מספר יציאה שונה כדי למנוע התנגשויות.
למודול של דף הבית יש שתי משימות: הוא מציג את דף הבית ומתקשר עם המודולים האחרים כדי לאסוף נתונים שצריך להציג בדף אינטרנט. כל אחד מהמודולים האחרים מתמקד בפונקציה אחת: הצגת ביקורות, פרטים או תמונות. המודולים האלה לא מתקשרים ביניהם – הם מגיבים רק לבקשות מהמודול של דף הבית.
למרות שלמודול של דף הבית יש תפקיד נוסף של תיאום, האפליקציה עדיין מודולרית באמת כי אפשר לעדכן כל מודול בלי להשפיע על המודולים האחרים. אפליקציית Flask הגדולה חולקה לארבעה חלקים, וכל אחד מהם מטפל בחלק ספציפי בפונקציונליות של האפליקציה.
הפעלת תקשורת בין המודולים
אחרי שיוצרים את המודולים, השלב הבא הוא לוודא שהם יכולים לתקשר ביניהם. באפליקציית Cymbal Books, לוגיקת התקשורת הזו כבר הוטמעה בשבילכם. בתיקייה modular/ של הקוד שהורדתם, אפשר לראות שכל אחת מהתכונות העיקריות של האפליקציה – הצגת דף הבית, פרטי הספר, הביקורות והתמונות – מיושמת כאפליקציית Flask נפרדת. כל אחת מהאפליקציות האלה מגדירה נקודת קצה משלה של HTTP, והמודולים מתקשרים באמצעות שליחת בקשות HTTP לנקודות הקצה האלה.
הפיכת המונוליט של Cymbal Books למודולרי הייתה פשוטה. למונולית יש רכיבים מוגדרים היטב שמיושמים כמטפלי נתיבים, ולכל מטפל נתיבים יש נקודת קצה מוגדרת היטב. כשמציבים את הפונקציות האלה לטיפול בבקשות במסגרת אפליקציות נפרדות של Flask, הן שומרות על היכולת שלהן לתקשר דרך נקודות הקצה שלהן. הפעולה הפשוטה של העברת הפונקציות לטיפול בניתוב לאפליקציות Flask נפרדות יוצרת את המודולים ומאפשרת למודולים לתקשר זה עם זה.
גישה נפוצה לתקשורת בין מודולים היא הטמעה של ממשקי REST API, שמאפשרים למודולים לשלוח זה לזה בקשות HTTP. כך זה עובד ב-Cymbal Books: כל מודול מגדיר נקודות קצה של REST באמצעות הכלים המובנים של Flask. גישה פופולרית נוספת היא gRPC, שמאפשרת למודולים לקרוא ישירות לפונקציות של מודולים אחרים.
למה התקשורת פשוטה ב-Cymbal Books
כל מודול באפליקציה המודולרית הוא אפליקציית Flask נפרדת שפועלת בתוך שרת אינטרנט. לדוגמה, מודול דף הבית מציג את דף הבית, ומודול פרטי הספר מציג את פרטי הספר. התקשורת בין המודולים פשוטה כי שרתי אינטרנט מיועדים לטפל בבקשות ובתגובות HTTP. כל מודול חושף נקודות קצה שמודולים אחרים יכולים להשתמש בהן כדי לבקש נתונים.
לתת לכל מודול גישה רק לנתונים שהוא צריך
כדי להפוך את המונוליט למודולרי בצורה נכונה, צריך לוודא שלכל מודול יש גישה רק לנתונים שהוא צריך. העיקרון הזה, שנקרא בידוד נתונים, הוא מרכיב חיוני ביצירת ארכיטקטורה מודולרית באמת.
טעות נפוצה שאנשים עושים במהלך מודולריזציה היא לאפשר לכמה מודולים לגשת לאותם נתונים, כמו מסד נתונים יחיד. סוג ההטמעה הזה יוצר בעיות כמו:
- צימוד הדוק: אם המבנה של הנתונים המשותפים משתנה – למשל, אם משנים את השם של טבלת מסד נתונים או מוסיפים עמודה – צריך לעדכן כל מודול שמסתמך על הנתונים האלה. כדי למנוע את הבעיה הזו, צריך להשתמש במודולריזציה נכונה.
- בעיות בסובלנות לתקלות: כשכמה מודולים משתמשים באותו מקור נתונים, כשלים בזמן ריצה במודול אחד – כמו שאילתות לא תקינות או תנועה עמוסה מדי – עלולים לשבש מודולים אחרים. כשל בחלק אחד של המערכת יכול להוביל לכשלים בחלקים אחרים של המערכת.
- צווארי בקבוק בביצועים: מקור נתונים יחיד ומשותף יכול להפוך לצוואר בקבוק, כלומר הוא עלול להאט את כל האפליקציה כשכמה מודולים מנסים ליצור איתו אינטראקציה.
כדי למנוע את הבעיות האלה, לכל מודול צריך להיות מקור נתונים משלו.
אם חברת Cymbal Books הייתה משתמשת במסד נתונים כדי לאחסן את הנתונים שלה, היה צורך לשכפל או לחלק את מסד הנתונים כדי לאכוף בידוד נתונים ולוודא שכל מודול ניגש רק לנתונים שהוא צריך. שכפול כולל שמירה של עותקים נפרדים של מסד הנתונים לכל מודול, בעוד שחלוקה למחיצות מגבילה את הגישה לטבלאות או לשורות ספציפיות. שתי הגישות מונעות ממודולים להפריע לנתונים של מודולים אחרים.
בתרשים הבא מוצגת השוואה בין הארכיטקטורה של אפליקציית הספרים המונוליטית לבין הארכיטקטורה המודולרית של אפליקציית הספרים:

ההטמעה של המונולית לא עומדת בדרישות של עיקרון בידוד הנתונים, כי הפונקציות של המונולית ניגשות לספרייה אחת של data/.
לעומת זאת, אפליקציה מודולרית משיגה מידה מסוימת של בידוד נתונים על ידי פיצול הנתונים לספריות נפרדות, ומוודאת שכל מודול יקיים אינטראקציה רק עם הנתונים שיועדו לו:
- מודול פרטי הספר מקבל נתונים רק מהספרייה
details_data/. - מודול ביקורות הספרים מקבל נתונים רק מהספרייה
reviews_data/. - המודול 'תמונות' מקבל נתונים רק מהספרייה
images/.
במדריך נוסף בהמשך, מוסבר איך אפשר לשפר עוד יותר את הבידוד של הנתונים באמצעות יצירת קונטיינר לאפליקציה.
מה שראיתם עכשיו
בתעשיית פיתוח התוכנה, נתקלים לעיתים קרובות במונחים מיקרו-שירותים ומערכות מבוזרות. בקטע הזה נסביר איך המונחים האלה קשורים להטמעה המודולרית של Cymbal Books.
מיקרו-שירותים
מיקרו-שירותים הם מודולים אוטונומיים שמבצעים משימות ספציפיות. המודולים האלה מתקשרים עם מודולים אחרים באמצעות ממשקים כמו נקודות קצה.
כל מודול בגרסה המודולרית של Cymbal Books מתאים להגדרה הזו, ולכן אפשר להתייחס אליו כאל מיקרו-שירות. כשמכניסים את האפליקציה המודולרית לקונטיינר במדריך מאוחר יותר, הקוד שרץ בתוך הקונטיינר יכול להיקרא גם מיקרו-שירות, כי זה אותו קוד שרץ בתוך מודול.
מערכות מבוזרות
מערכת מבוזרת מורכבת ממודולים עצמאיים שמתקשרים דרך רשת כדי להשיג מטרה משותפת. המודולים האלה יכולים לפעול במכונות שונות, אבל הם פועלים יחד כמערכת אחת.
גם אפליקציית Cymbal Books המודולרית מתאימה להגדרה הזו: המודולים שלה פועלים באופן עצמאי ומחליפים נתונים באמצעות HTTP, אבל ביחד הם פועלים כמערכת אחת. בקטע הבא, מריצים את כל המודולים במכונה אחת כדי לפשט את התהליך, אבל זה לא חובה. כל מודול יכול לפעול בקלות בשרת אחר, ולכן אפשר לסווג את הגרסה המודולרית של אפליקציית Cymbal Books כמערכת מבוזרת.
בדיקת ההטמעה המודולרית
עכשיו, אחרי שראיתם איך המונוליט של Cymbal Books הופך לאפליקציה מודולרית שהמודולים שלה הם אפליקציות Flask, אתם יכולים לבדוק את האפליקציה ולראות שכל מודול פועל באופן עצמאי.
במדריך הזה, מריצים את המודולים באותה מכונה. עם זאת, אפשר גם להריץ כל מודול בשרת נפרד: כל מודול הוא אוטונומי, ולכן הוא יכול לתקשר עם המודולים האחרים דרך נקודות הקצה שלהם.
מגדירים את הסביבה
כדי להתכונן לבדיקה:
במסוף, נכנסים לספרייה
modularבמאגר המשוכפל:cd modularמוודאים שהסביבה הווירטואלית
book-review-envפעילה. אם אתם צריכים תזכורת לגבי שלבי ההפעלה, תוכלו לעיין במאמר יצירה והפעלה של סביבה וירטואלית.
הפעלת אפליקציית Flask
התיקייה /modular מכילה סקריפט bash שמתחיל את כל אפליקציות Flask בו-זמנית. כל מודול באפליקציה מאזין ליציאה ייחודית, כמו 8080 או 8081:
- אפליקציית Flask בדף הבית (home.py): יציאה 8080
- Book details Flask app (book_details.py): port 8081
- אפליקציית Flask לביקורות על ספרים (book_reviews.py): יציאה 8082
- אפליקציית Flask של תמונות (images.py): יציאה 8083
כל מודול צריך להאזין למספר יציאה ייחודי כי כל המודולים פועלים באותו מחשב. אם כל מודול היה בשרת אחר, כל אחד מהם היה יכול להאזין לאותו מספר יציאה בלי ליצור התנגשויות בין יציאות.
מריצים את סקריפט ה-Bash באמצעות הפקודה הבאה:
bash ./start_services.sh
הסקריפט יוצר קובץ יומן נפרד לכל אפליקציית Flask (לדוגמה, home.py.log, book_details.py.log) כדי לעזור לכם לזהות בעיות בהפעלה.
כשהסקריפט מסתיים בהצלחה, מוצגת ההודעה הבאה:
All services have been started. Access the app at http://localhost:8080/
בדיקה של כל אפליקציית Flask
כדי לבדוק את המודולים, עוברים לכתובות ה-URL הבאות בדפדפן:
- דף הבית:
http://localhost:8080/מציג את דף הבית של אפליקציית הספרים המודולרית Cymbal Books. בדף הזה מאוחזרים פרטי הספר, ביקורות ותמונות על ידי שליחת בקשות למודולים האחרים. - פרטי הספר:
http://localhost:8081/book/1מחזירה את הפרטים של הספר עם המזהה 1. התשובה הזו היא נתוני JSON שהאפליקציה מעצבת ומציגה בצורה קריאה יותר. - ביקורות על ספרים:
http://localhost:8082/book/1/reviewsמאחזר ומחזיר את הביקורות על הספר עם המזהה 1. הביקורות הן בפורמט JSON. מודול דף הבית שולח בקשה לנתונים האלה ומשלב אותם בדף הפרטים של הספר. - Images:
http://localhost:8083/images/fungi_frontier.jpgמציג את תמונת השער של הספר Fungi Frontier. אם כתובת ה-URL נכונה, התמונה אמורה להיטען ישירות בדפדפן.
עצירת אפליקציות Flask
כשמסיימים את הבדיקה, מפסיקים את כל אפליקציות Flask באמצעות הפקודה הבאה:
kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)
סיכום
במדריך הזה למדתם איך להפוך את המונוליט של Cymbal Books למודולרי. התהליך כולל את השלבים הבאים:
- זיהוי הרכיבים הייחודיים של האפליקציה
- יצירת המודולים
- לוודא שלכל מודול יש גישה רק לנתונים שהוא צריך
לאחר מכן בדקתם את ההטמעה המודולרית במחשב המקומי.
המאמרים הבאים
במדריך הבא, הכנת האפליקציה המודולרית להעברה לקונטיינר, מוסבר איך להכין את האפליקציה המודולרית להעברה לקונטיינר על ידי עדכון נקודות הקצה לשימוש בשמות שירות Kubernetes במקום localhost.