המדריך הזה מיועד למי שמכיר את הסביבה הרגילה, ומספק מבוא לסביבה הגמישה. במאמר מוסבר על הדמיון וההבדלים העיקריים בין הסביבות, וגם מפורטות בו המלצות כלליות לגבי הארכיטקטורה של אפליקציות שמשתמשות בשתי הסביבות.
למיפוי של שירותים שזמינים בסביבה רגילה לאנלוגים שלהם בסביבה גמישה, אפשר לעיין במאמר העברת שירותים מהסביבה הרגילה לסביבה הגמישה.
נקודות דמיון והבדלים עיקריים
שתי הסביבות מספקות לכם את התשתית של App Engine לפריסה, להצגה ולהתאמה לעומס (scaling). ההבדלים העיקריים הם באופן שבו הסביבה מריצה את האפליקציה, באופן שבו האפליקציה ניגשת לשירותים חיצוניים, באופן שבו מריצים את האפליקציה באופן מקומי ובאופן שבו האפליקציה מתרחבת. אפשר גם לעיין בבחירת סביבה כדי לקבל סיכום כללי של ההבדלים האלה.
הרצת אפליקציה
בסביבה הרגילה, האפליקציה פועלת במכונה קלה בתוך ארגז חול. ארגז החול הזה מגביל את הפעולות שהאפליקציה יכולה לבצע. לדוגמה, ארגז החול מאפשר לאפליקציה להשתמש רק בקבוצה מוגבלת של ספריות בינאריות, והאפליקציה לא יכולה לכתוב לדיסק. בסביבה הרגילה יש גם מגבלות על אפשרויות המעבד והזיכרון שזמינות לאפליקציה. בגלל ההגבלות האלה, רוב האפליקציות הרגילות של App Engine הן אפליקציות אינטרנט חסרות מצב (stateless) שמגיבות במהירות לבקשות HTTP.
לעומת זאת, בסביבה הגמישה האפליקציה פועלת במאגרי Docker במכונות וירטואליות (VM) של Google Compute Engine, שבהן יש פחות הגבלות. לדוגמה, אתם יכולים להשתמש בכל שפת תכנות שתבחרו, לכתוב לדיסק, להשתמש בכל ספרייה שתרצו ואפילו להריץ כמה תהליכים. בסביבה הגמישה אפשר גם לבחור כל סוג מכונה של Compute Engine עבור המכונות הווירטואליות, כדי שלאפליקציה תהיה גישה ליותר זיכרון ו-CPU.
גישה לשירותים חיצוניים
בסביבה הרגילה, האפליקציה שלכם בדרך כלל ניגשת לשירותים כמו Datastore דרך ממשקי ה-API המובנים של google.appengine. עם זאת, בסביבה הגמישה, ממשקי ה-API האלה כבר לא זמינים. במקום זאת, צריך להשתמש בספריות הלקוח של Google Cloud. ספריות הלקוח האלה פועלות בכל מקום, ולכן האפליקציה שלכם ניידת יותר. בדרך כלל, אפליקציות שפועלות בסביבה הגמישה יכולות לפעול ב-Google Kubernetes Engine או ב-Compute Engine בלי שינויים משמעותיים.
פיתוח מקומי
בסביבה הרגילה, בדרך כלל מריצים את האפליקציה באופן מקומי באמצעות App Engine SDK. ערכת ה-SDK מריצה את האפליקציה ומדמה את השירותים של App Engine. בסביבה הגמישה, ה-SDK לא משמש יותר להרצת האפליקציה. במקום זאת, אפליקציות שנכתבות לסביבה הגמישה צריכות להיכתב כמו אפליקציות אינטרנט רגילות שיכולות לפעול בכל מקום. כמו שצוין, בסביבה הגמישה האפליקציה פועלת בקונטיינר Docker. המשמעות היא שכדי לבדוק את האפליקציה באופן מקומי, פשוט מריצים את האפליקציה ישירות. לדוגמה, כדי להריץ אפליקציית Python באמצעות Django, פשוט מריצים את הפקודה python manage.py runserver.
הבדל חשוב נוסף הוא שאפליקציות בסביבה גמישה שפועלות באופן מקומי משתמשות בשירותים בפועל של Cloud Platform, כמו Datastore. כדאי להשתמש בפרויקט נפרד לבדיקות מקומיות, וכשזמין, להשתמש באמולטורים.
מאפייני שינוי הגודל
שתי הסביבות משתמשות בתשתית של App Engine להתאמה אוטומטית לעומס, אבל אופן ההתאמה לעומס שונה. הסביבה הרגילה יכולה להתרחב מאפס מופעים ועד לאלפים במהירות רבה. לעומת זאת, בסביבה גמישה צריכה לפעול לפחות אינטס אחד לכל גרסה פעילה, והרחבת קנה המידה בתגובה לתנועת הגולשים עשויה להימשך זמן רב יותר.
בסביבה רגילה נעשה שימוש באלגוריתם מותאם אישית של שינוי גודל אוטומטי. בסביבה גמישה נעשה שימוש בכלי לשינוי גודל אוטומטי של Compute Engine. שימו לב: בסביבה גמישה לא נתמכות כל האפשרויות של התאמה אוטומטית לעומס שזמינות ב-Compute Engine. App Engine מכבד את כל ההזמנות של מכונות וירטואליות ב-Compute Engine שכבר יש לכם באזור שתואם להגדרה שלכם. שמירת מקום למכונה וירטואלית מגדילה את הסיכוי שתקבלו הקצאת משאבים במהלך מחסור זמני במשאבים.
מפתחים צריכים לבדוק את התנהגות האפליקציה שלהם במגוון תנאים. לדוגמה, כדאי לבדוק איך שינוי הגודל האוטומטי מגיב כשיישום שמוגבל על ידי CPU הופך להיות מוגבל על ידי קלט/פלט בתקופות שבהן יש השהיה מוגברת בקריאות לשירותים מרוחקים.
בדיקות תקינות
בסביבה רגילה, המערכת לא משתמשת בבדיקות תקינות כדי לקבוע אם לשלוח תעבורה למופע. בסביבה גמישה, מפתחי אפליקציות יכולים לכתוב בעצמם את ה-handlers של בדיקות התקינות, שמאזן העומסים ישתמש בהם כדי לקבוע אם לשלוח תעבורה למופע ואם לבצע תיקון אוטומטי. המפתחים צריכים להיזהר כשמוסיפים לוגיקה לבדיקות התקינות. לדוגמה, אם בדיקת התקינות מבצעת קריאה לשירות חיצוני, כשל זמני בשירות הזה עלול לגרום לכל המופעים להיות לא תקינים, ואולי להוביל לכשל מדורג.
הבקשות נדחות כשהעומס גבוה מדי
אפליקציות יכולות להפסיק בקשות כשהן עמוסות מדי, כחלק מאסטרטגיה למניעת כשלים מדורגים. היכולת הזו מובנית בשכבת ניתוב התנועה בסביבה הרגילה. אנחנו ממליצים למפתחים של אפליקציות עם QPS גבוה מאוד בסביבה הגמישה לבנות את היכולת הזו להפסיק תנועה עמוסה מדי באפליקציות שלהם, על ידי הגבלת מספר הבקשות בו-זמנית.
כדי לוודא שהאפליקציה בסביבה הגמישה לא חשופה לסוג הזה של כשלים, אפשר ליצור גרסה עם מגבלה על המספר המקסימלי של מופעים. לאחר מכן, מגדילים בהדרגה את נפח התנועה עד שהבקשות נדחות. חשוב לוודא שהאפליקציה לא נכשלת בבדיקות התקינות במהלך עומס יתר.
ב-Java, אפליקציות Java שמשתמשות ב-Jetty runtime יכולות להגדיר את מסנן איכות השירות כדי להטמיע את התכונה 'הסרת עומס'. באמצעות התכונה הזו, אפשר לקבוע את המספר המקסימלי של בקשות בו-זמניות שהאפליקציות מטפלות בהן, ואת משך הזמן שבו הבקשות ימתינו בתור.
גדלים של מכונות
במקרים של סביבות גמישות, אפשר להגדיר מגבלות גבוהות יותר על השימוש במעבד ובזיכרון בהשוואה למקרים של סביבות רגילות. כך אפשר להריץ על מופעים גמישים אפליקציות שדורשות יותר זיכרון ומעבד. עם זאת, יכול להיות שהיא תגדיל את הסיכוי לבאגים של בו-זמניות (concurrency) בגלל העלייה במספר השרשורים במופע יחיד.
מפתחים יכולים להשתמש ב-SSH כדי להתחבר למופע של סביבה גמישה ולקבל dump של השרשור כדי לפתור בעיות מהסוג הזה.
לדוגמה, אם אתם משתמשים בסביבת זמן הריצה של Java, אתם יכולים להריץ את הפקודה הבאה:
$ ps auwwx | grep java $ sudo kill -3$ sudo docker logs gaeapp
זמן קצוב לתפוגה של בקשה
בסביבה רגילה, הזמן הקצוב לתפוגה של בקשה משתנה בהתאם לסוג ההתאמה שנבחרה, אבל בסביבה גמישה תמיד מוגדר זמן קצוב לתפוגה של 60 דקות. כדי למנוע מצב שבו בקשות נשארות פתוחות למשך 60 דקות מלאות ועלולות לתפוס את כל השרשורים בשרת האינטרנט:
כשמבצעים שיחות לשירותים חיצוניים, צריך לציין זמן קצוב לתפוגה.
מטמיעים מסנן servlet כדי לעצור בקשות שלוקח להן זמן ארוך מדי, למשל 60 שניות. צריך לוודא שהאפליקציה יכולה לחזור למצב עקבי אחרי שהמסנן מפסיק בקשה.
ניהול שרשורים
בסביבות זמן ריצה רגילות של Java לפני Java 8, אפשר היה להשתמש רק בthreads שנוצרו באמצעות SDK של סביבת App Engine רגילה. מפתחים שמבצעים העברה של אפליקציה מסביבת זמן ריצה רגילה של Java מהדור הראשון לסביבה גמישה צריכים לעבור לשימוש בספריות של threads מקוריים. אפליקציות שדורשות מספר גדול מאוד של threads עשויות לפעול בצורה יעילה יותר עם מאגרי threads מאשר עם יצירה מפורשת של threads.
העברת תנועה
סביבת Standard מספקת תכונה להעברת תנועה, שמעבירה בהדרגה את התנועה לגרסה חדשה כדי לצמצם את העליות החדות בזמן האחזור. במאמר העברת תנועה מוסבר איך לוודא שלא תהיה עלייה חדה בזמן האחזור כשמעבירים את התנועה לגרסה חדשה.
כשלים באזור יחיד
אפליקציות בסביבה רגילה הן בעלות כתובת אחת, כלומר כל המופעים של האפליקציה נמצאים באזור זמינות אחד. במקרה של כשל באזור הזה, האפליקציה מפעילה מופעים חדשים באזור אחר באותו אזור, ומאזן העומסים מעביר את התעבורה למופעים החדשים. תהיה עלייה חדה בחביון בגלל טעינת הבקשות, וגם ניקוי של Memcache.
אפליקציות בסביבה גמישה משתמשות בקבוצות של מופעים מנוהלים אזוריים, כלומר המופעים מפוזרים בין כמה אזורי זמינות באזור מסוים. במקרה של כשל באזור יחיד, מאזן העומסים מפסיק להפנות תנועה לאזור הזה. אם הגדרתם את קנה המידה האוטומטי להפעלת המופעים בצורה הכי מהירה שאפשר, תראו תקופה קצרה של עומס יתר לפני שקנה המידה האוטומטי ייצור עוד מופעים.
השוואות עלויות
יש הרבה גורמים שמשפיעים על השוואת העלויות בין עומסי עבודה שפועלים בסביבות רגילות ובסביבות גמישות. למשל:
- המחיר ששולם לכל מחזור חיובים.
- יכולות פלטפורמת ה-CPU, שמשפיעות על העבודה שאפשר לבצע בכל מחזור שעון
- עד כמה אפשר להריץ מופעים בכל פלטפורמה.
- העלות של פריסות, שעשויה להיות שונה בכל פלטפורמה ויכולה להיות משמעותית אם אתם משתמשים בפריסה רציפה לאפליקציה.
- תקורה של זמן הריצה.
תצטרכו להריץ ניסויים כדי לקבוע את העלות של עומס העבודה בכל פלטפורמה. בסביבה גמישה, אפשר להשתמש ב-QPS לכל ליבה כפרוקסי ליעילות העלות של האפליקציה כשמריצים ניסויים כדי לקבוע אם לשינוי יש השפעה על העלויות. בסביבה רגילה אין מנגנון כזה לקבלת מדדים בזמן אמת לגבי היעילות של העלות של האפליקציה. צריך לבצע שינוי ולהמתין עד לסיום מחזור החיוב היומי.
מיקרו-שירותים
הסביבה הרגילה מאפשרת אימות מאובטח בין אפליקציות באמצעות כותרת הבקשה X-Appengine-Inbound-Appid. בסביבה גמישה אין תכונה כזו. הגישה המומלצת לאימות מאובטח בין אפליקציות היא שימוש ב-OAuth.
פריסה
פריסות בסביבה רגילה בדרך כלל מהירות יותר מפריסות בסביבה גמישה. הרחבת גרסה קיימת בסביבה גמישה מהירה יותר מפריסת גרסה חדשה, כי תכנות הרשת של גרסה חדשה הוא בדרך כלל השלב הכי ארוך בפריסה של סביבה גמישה. אחת מהאסטרטגיות לביצוע חזרות מהירות לגרסה קודמת בסביבה גמישה היא לשמור גרסה טובה מוכרת שהוקטנה למופע יחיד. לאחר מכן תוכלו להגדיל את הגרסה הזו ולהפנות אליה את כל התנועה באמצעות חלוקת תנועה.
מתי כדאי להשתמש בסביבה גמישה
הסביבה הגמישה נועדה להשלים את הסביבה הרגילה. אם יש לכם אפליקציה קיימת שפועלת בסביבה הרגילה, בדרך כלל לא צריך להעביר את כל האפליקציה לסביבה הגמישה. במקום זאת, צריך לזהות את החלקים באפליקציה שדורשים יותר מעבד, יותר זיכרון RAM, ספרייה או תוכנה מיוחדת של צד שלישי, או שצריכים לבצע פעולות שלא אפשריות בסביבה הרגילה. אחרי שמזהים את החלקים האלה באפליקציה, יוצרים שירותים קטנים של App Engine שמשתמשים בסביבה הגמישה כדי לטפל רק בחלקים האלה. השירות הקיים שלכם שפועל בסביבה הרגילה יכול לקרוא לשירותים האחרים באמצעות HTTP, Cloud Tasks או Cloud Pub/Sub.
לדוגמה, אם יש לכם אפליקציית אינטרנט שפועלת בסביבה הרגילה ואתם רוצים להוסיף לה תכונה חדשה להמרת קבצים ל-PDF, אתם יכולים לכתוב מיקרו-שירות נפרד שפועל בסביבה הגמישה ומטפל רק בהמרה ל-PDF. המיקרו-שירות הזה יכול להיות תוכנית פשוטה שמורכבת רק ממטפל בקשות אחד או שניים. המיקרו-שירות הזה יכול להתקין ולהשתמש בכל תוכנית לינוקס זמינה כדי לסייע בהמרה, כמו unoconv.
האפליקציה הראשית נשארת בסביבה הרגילה ויכולה להתקשר ישירות למיקרו-שירות הזה באמצעות HTTP. אם אתם צופים שההמרה תימשך זמן רב, האפליקציה יכולה להשתמש ב-Cloud Tasks או ב-Pub/Sub כדי להוסיף את הבקשות לתור.
המאמרים הבאים
ממפים את השירותים שבהם האפליקציה משתמשת בסביבה הרגילה לאנלוגים שלהם בסביבה הגמישה.