יחידת לימוד 11: מעבר מ-Google App Engine ל-Cloud Functions

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

סדרת הServerless Migration Station של Codelabs (מדריכים מעשיים בקצב עצמי) וסרטונים קשורים נועדו לעזור להעביר מפתחים ללא שרת (serverless) של Google Cloud, באמצעות העברת אפליקציות מדור קודם באמצעות שירותי Google Cloud. כך האפליקציות שלכם יהיו יותר ניידות ויהיו לכם יותר אפשרויות וגמישות, כך שתוכלו להשתלב עם מגוון רחב יותר של מוצרי Cloud ולגשת אליהם בקלות, ולהשדרג בקלות רבה יותר לגרסאות חדשות יותר של שפות. הסדרה מתמקדת בהתחלה במשתמשי Cloud הראשונים, ובעיקר מפתחי App Engine (בסביבה סטנדרטית), אבל היא רחבה מספיק כדי לכלול פלטפורמות אחרות ללא שרת (serverless), כמו Cloud Functions ו-Cloud Run, או במקומות אחרים, אם רלוונטי.

יש מצבים שבהם אין לך 'אפליקציה מלאה' כדי לדרוש את המשאבים של App Engine או של Cloud Run. אם הקוד מורכב רק ממיקרו-שירות (microservice) או מפונקציה פשוטה, סביר להניח ש-Cloud Functions יתאים יותר. בשיעור הזה תלמדו איך להעביר אפליקציות פשוטות של App Engine (או לפצל אפליקציות גדולות יותר למספר מיקרו-שירותים) ולפרוס אותן ב-Cloud Functions, פלטפורמה אחרת ללא שרת (serverless) שנוצרה במיוחד לתרחישים לדוגמה כאלה.

כאן אפשר להבין איך

  • שימוש ב-Cloud Shell
  • הפעלת Google Cloud Translation API
  • אימות בקשות API
  • המרת אפליקציה קטנה של App Engine להרצה ב-Cloud Functions
  • פריסת הקוד ב-Cloud Functions

למה תזדקק?

סקר

איך תשתמשו במדריך הזה?

לקריאה בלבד לקרוא אותו ולבצע את התרגילים

איזה דירוג מגיע לדעתך לחוויה שלך עם Python?

מתחילים בינונית בקיאים

איזה דירוג מגיע לדעתך לחוויית השימוש שלך בשירותי Google Cloud?

מתחילים בינונית בקיאים

2. רקע

הרבה יותר נוח למשתמשים במערכות PaaS, כמו Google App Engine ו-Cloud Functions. הפלטפורמות האלה ללא שרת (serverless) מאפשרות לצוות הטכני שלכם להתמקד ביצירת פתרונות עסקיים במקום להשקיע זמן בבדיקת פלטפורמות כדי להשתמש בהן וקביעת כמות החומרה הדרושה. אפליקציות יכולות להתאים לעומס (autoscaling) לפי הצורך, להקטין את ההיקף לאפס באמצעות חיוב לפי שימוש כדי לשלוט בעלויות, והן מאפשרות שימוש במגוון שפות פיתוח נפוצות כיום.

יחד עם זאת, פיתוח פול סטאק או קצוות עורפיים מורכבים לאפליקציות לנייד מתאימים ל-App Engine, אבל לעיתים קרובות מפתחים מנסים לבצע פונקציונליות מסוימת באינטרנט, כמו עדכון פיד חדשות או שליפת התוצאה האחרונה במשחק הפלייאוף של הקבוצה הביתית. בשני התרחישים קיימת לוגיקת קידוד, אבל אף אחד מהם לא נראה מלא 'אפליקציות' שדורשים את העוצמה של App Engine. כאן נכנסים לתמונה Cloud Functions.

השירות Cloud Functions מיועד לפריסה של קטע קוד קטן:

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

אתם יכולים גם להשתמש ב-Cloud Functions כדי לפצל אפליקציה גדולה ומונוליתית למספר מיקרו-שירותים (microservices), שכל אחד מהם משתמש במסד נתונים משותף כמו Cloud Firestore או Cloud SQL. אם אתם רוצים שהפונקציה או המיקרו-שירות (microservice) שלכם יהיו בקונטיינרים ויפעלו ללא שרת (serverless) ב-Cloud Run, אפשר לעשות גם את זה.

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

  • הגדרה/עבודה מוקדמת
  • הסרת קובצי תצורה
  • שינוי קובצי אפליקציה

3. הגדרה/עבודה מוקדמת

ה-Codelab הזה מתחיל בגרסת Python 3 של האפליקציה לדוגמה של App Engine Module 2 Cloud NDB כי ב-Cloud Functions אין תמיכה ב-Python 2. קודם כול, נגדיר את הפרויקט שלנו, נקבל את הקוד ואז נפרוס את אפליקציית הבסיס כדי לוודא שאנחנו מתחילים עם קוד שעובד.

1. הגדרת הפרויקט

אם השלמתם את ה-codelab של מודול 2 (והעברת אותו ל-Python 3), מומלץ להשתמש שוב באותו פרויקט (ובקוד). לחלופין, אפשר ליצור פרויקט חדש לגמרי או להשתמש שוב בפרויקט קיים. מוודאים שלפרויקט יש חשבון פעיל לחיוב עם שירות App Engine מופעל.

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

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

בין אם אתם משתמשים בקוד שלכם או שלנו, קוד Python 3 של מודול 2 הוא המקום שבו נתחיל. Codelab במודול 11 הזה ינחה אותך לאורך כל השלבים, ויסתיים עם קוד שדומה למה שיש בתיקיית המאגר של מודול 11 (FINISH).

הספרייה של קובצי Python 3 STARTing (שלכם או שלנו) אמורה להיראות כך:

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. (Re) פריסת אפליקציות בסיסיות

שאר השלבים לפני העבודה שצריך לבצע עכשיו:

  1. כדאי להכיר מחדש את כלי שורת הפקודה gcloud
  2. פורסים מחדש את האפליקציה לדוגמה באמצעות gcloud app deploy
  3. אישור שהאפליקציה פועלת ב-App Engine ללא בעיות

אחרי שתבצעו את השלבים האלה, תוכלו להמיר אותה לפונקציה של Cloud Functions.

4. הסרת קובצי תצורה

הקובץ app.yaml הוא ארטיפקט של App Engine שלא משתמשים בו עם Cloud Functions, לכן צריך למחוק אותו עכשיו. אם לא תעשו זאת או שכחתם לעשות את זה, לא תוכלו לגרום נזק כי Cloud Functions לא משתמש בה. זהו השינוי היחיד בהגדרה של requirements.txt, כי הוא נשאר זהה למודול 2.

אם אתם גם מניידים אפליקציית Python 2 App Engine אל Python 3, מוחקים את appengine_config.py ואת התיקייה lib, אם יש כזו. אלו פריטי מידע שנוצרו בתהליך פיתוח (Artifact) של App Engine שלא נמצאים בשימוש בזמן הריצה של Python 3.

5. שינוי קובצי אפליקציה

יש רק קובץ אפליקציה אחד, main.py, כך שכל השינויים שדרושים להעברה ל-Cloud Functions מתבצעים בקובץ הזה.

יבוא

מכיוון שאנחנו עובדים רק עם פונקציות, אין צורך ב-framework של אפליקציית אינטרנט. עם זאת, מטעמי נוחות, כשקוראים ל-Cloud Functions שמבוססות על Python, אובייקט הבקשה מועבר באופן אוטומטי לקוד שבו אתם יכולים להשתמש לפי הצורך. (צוות Cloud Functions בחר את האובייקט בתור אובייקט בקשה ב-Flask שיועבר לפונקציה שלכם).

מסגרות אינטרנט (frameworks) הן לא חלק מהתחום של Cloud Functions, ולכן אין ייבוא מ-Flask אלא אם נעשה באפליקציה שימוש בתכונות אחרות של Flask. זה אכן המקרה שלנו, כי עיבוד התבנית עדיין מתבצע אחרי ההמרה לפונקציה, כלומר עדיין צריך לבצע קריאה ל-flask.render_template(), ולכן עדיין נדרש ייבוא מ-Flask. אם אין framework, אין צורך ליצור אפליקציית Flask, אז צריך למחוק את app = Flask(__name__). הקוד נראה כך, לפני ואחרי החלת השינויים:

לפני:

from flask import Flask, render_template, request
from google.cloud import ndb

app = Flask(__name__)
ds_client = ndb.Client()

אחרי:

from flask import render_template
from google.cloud import ndb

ds_client = ndb.Client()

אם אתם תלויים באובייקט האפליקציה (app) או בכל תשתית אחרת של framework, עליכם לפתור את כל יחסי התלות האלה, למצוא פתרונות אפשריים, או להסיר את השימוש בהם לגמרי או למצוא שרתי proxy. לאחר מכן תוכלו להמיר את הקוד לפונקציה של Cloud Functions. אחרת, עדיף להישאר ב-App Engine או לאחסן את האפליקציה בקונטיינרים בשביל Cloud Run

עדכון החתימה של פונקציית ה-handler הראשית

אלה השינויים הנדרשים בחתימת הפונקציה:

  1. לא נעשה יותר שימוש ב-Flask אחרי המרת האפליקציה לפונקציה של Cloud Functions, לכן יש להסיר מעצבי נתיבים.
  2. שירות Cloud Functions מעביר באופן אוטומטי את האובייקט Request (Flask) כפרמטר, ולכן צריך ליצור עבורו משתנה. באפליקציה לדוגמה שלנו, נקרא request.
  3. צריך לתת שם ל-Cloud Functions פרוסות. השם של ה-handler הראשי שלנו מתאים ל-root() ב-App Engine כדי לתאר מה הוא היה (ה-handler של אפליקציית הרמה הבסיסית). פחות הגיוני להשתמש בשם הזה כפונקציה של Cloud Functions. במקום זאת, נפרוס את הפונקציה של Cloud Functions בשם visitme, ולכן עליכם להשתמש בו גם בתור השם של פונקציית Python. באופן דומה, במודולים 4 ו-5, קראנו גם לשירות Cloud Run visitme.

ריכזנו כאן את לפני ואחרי העדכונים:

לפני:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

אחרי:

def visitme(request):
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

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

668f30e3865b27a9.png

פיתוח ובדיקה מקומיים

ל-App Engine יש שרת פיתוח מקומי dev_appserver.py, ואילו ל-Cloud Functions יש Functions Framework. באמצעות המסגרת הזו תוכלו לפתח ולבדוק באופן מקומי. תוכלו לפרוס את הקוד שלכם ב-Cloud Functions, אבל אפשר לפרוס אותו גם בפלטפורמות מחשוב אחרות כמו Compute Engine, Cloud Run או אפילו במערכות ענן מקומיות או היברידיות שתומכות ב-Knative. בהמשך יש קישורים נוספים ל-Functions Framework.

6. פיתוח ופריסה

יש הבדל קל בין הפריסה ב-Cloud Functions לבין App Engine. מאחר שלא נעשה שימוש בקובצי תצורה מחוץ ל-requirements.txt, יש לציין מידע נוסף על הקוד בשורת הפקודה. פורסים את הפונקציה החדשה של Cloud Functions שפועלת ב-HTTP, שפועלת ב-Python 3.10 באמצעות הפקודה הבאה:

$ gcloud functions deploy visitme --runtime python310 --trigger-http --allow-unauthenticated

הפלט אמור להיראות כך:

Deploying function (may take a while - up to 2 minutes)...⠛
For Cloud Build Logs, visit: https://console.cloud.google.com/cloud-build/builds;region=REGION/f5f6fc81-1bb3-4cdb-8bfe?project=PROJECT_ID
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
buildId: f5f6fc81-1bb3-4cdb-8bfe
buildName: projects/PROJECT_ID/locations/REGION/builds/f5f6fc81-1bb3-4cdb-8bfe
dockerRegistry: CONTAINER_REGISTRY
entryPoint: visitme
httpsTrigger:
  securityLevel: SECURE_OPTIONAL
  url: https://REGION-PROJECT_ID.cloudfunctions.net/visitme
ingressSettings: ALLOW_ALL
labels:
  deployment-tool: cli-gcloud
name: projects/PROJECT_ID/locations/REGION/functions/visitme
runtime: python310
serviceAccountEmail: PROJECT_ID@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/uploads-853031211983.REGION.cloudfunctions.appspot.com/8c923758-cee8-47ce-8e97-5720a5301c34.zip
status: ACTIVE
timeout: 60s
updateTime: '2022-05-16T18:28:06.153Z'
versionId: '8'

אחרי שהפונקציה פרוסה, משתמשים בכתובת ה-URL מפלט הפריסה ומבקרים באפליקציה. כתובת ה-URL מופיעה בפורמט: REGION-PROJECT_ID.cloudfunctions.net/visitme. הפלט אמור להיות זהה לפלט שפרסתם קודם ב-App Engine:

2732ae9218f011a2.png

בדומה לרוב ה-Codelabs והסרטונים האחרים בסדרה, הפונקציונליות הבסיסית של האפליקציה לא משתנה. המטרה היא ליישם שיטת מודרניזציה אחת כדי שהאפליקציה תפעל בדיוק כמו קודם אבל היא מופעלת באמצעות תשתית חדשה יותר. לדוגמה, מעבר משירות ישן של App Engine למוצר עצמאי חלופי ב-Cloud, או העברת אפליקציה לפלטפורמה אחרת ללא שרת (serverless) של Google Cloud.

7. סיכום/ניקוי

מעולה! המרת את אפליקציית App Engine הקטנה הזו לפונקציה של Cloud Functions! תרחיש מתאים נוסף: פיצול אפליקציה מונוליתית גדולה של App Engine לסדרה של מיקרו-שירותים (microservices), כל אחד כפונקציה של Cloud Functions. זוהי טכניקת פיתוח מודרנית יותר, שמספקת סגנון רכיב (a la " JAMStack"). הם מאפשרים שילוב והתאמה ושימוש חוזר בקוד, שהם שני יעדים. יתרון נוסף הוא שמיקרו-שירותים האלו ימשיכו לעבור ניפוי באגים לאורך זמן. כלומר, קוד יציב ועלויות תחזוקה נמוכות יותר באופן כללי.

הסרת המשאבים

אחרי השלמת ה-Codelab הזה, אפשר להשבית את אפליקציית Module 2 App Engine (באופן זמני או קבוע) כדי למנוע חיוב. לפלטפורמת App Engine יש מכסה בחינם, כך שלא תחויבו כל עוד לא תהיו במסגרת רמת השימוש שלה. אותו עיקרון חל על Datastore; לפרטים נוספים, ראו מחירון של Cloud Datastore.

פריסה בפלטפורמות כמו App Engine ו-Cloud Functions כרוכה בעלויות קטנות של פיתוח ואחסון. באזורים מסוימים, ל-Cloud Build יש מכסה נפרדת בחינם כמו ב-Cloud Storage. גרסאות build צורכות חלק מהמכסה הזו. כדאי שתהיו מודעים לשימוש שלכם בנפח האחסון כדי לצמצם את העלויות הפוטנציאליות, במיוחד אם אין באזור שלכם תוכנית ללא תשלום כזו.

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

השלבים הבאים

מעבר למדריך הזה, כדאי לבחון מודולים אחרים של העברה שכוללים יצירת קונטיינרים לאפליקציית App Engine עבור Cloud Run. בקישורים הבאים תוכלו למצוא את הקישורים למעבדי הקוד של מודול 4 ומודול 5:

  • מודול 4: מעבר ל-Cloud Run באמצעות Docker
  • יצירת קונטיינרים לאפליקציה להרצה ב-Cloud Run באמצעות Docker
  • ההעברה הזו מאפשרת לכם להישאר ב-Python 2.
  • מודול 5: מעבר ל-Cloud Run עם Cloud Buildpacks
  • יצירת קונטיינרים לאפליקציה כדי לרוץ ב-Cloud Run באמצעות Cloud Buildpacks
  • לא צריך לדעת שום דבר על Docker, על קונטיינרים או על Dockerfile.
  • כדי שהאפליקציה צריכה לעבור כבר ל-Python 3 (ב-Buildpacks אין תמיכה ב-Python 2).

רבים מהמודולים האחרים מתמקדים במראה למפתחים איך לעבור משירותים בחבילה של App Engine להחלפות עצמאיות ב-Cloud:

אם יצירת קונטיינרים הפכה לחלק מתהליך פיתוח האפליקציות שלכם, במיוחד אם היא מורכבת מצינור עיבוד נתונים של CI/CD (אינטגרציה רציפה (CI/CD), פיתוח רציף (continuous delivery) או פריסה), מומלץ לעבור ל-Cloud Run במקום ל-Cloud Functions. אפשר לעיין במודול 4 כדי ליצור קונטיינרים לאפליקציה באמצעות Docker, או במודול 5 כדי לעשות זאת ללא קונטיינרים, ידע ב-Docker או Dockerfile. לא משנה אם אתם שוקלים להשתמש ב-Cloud Functions או ב-Cloud Run, לא חובה לעבור לפלטפורמה אחרת ללא שרת (serverless). לפני שמבצעים שינויים, מומלץ לשקול את האפשרויות הטובות ביותר לאפליקציות ולתרחישים לדוגמה שלכם.

בלי קשר למודול ההעברה הרצוי, כל התוכן של תחנת המיגרציה ללא שרת (serverless) (codelabs, סרטונים, קוד מקור [אם הוא זמין]) יהיה זמין במאגר הקוד הפתוח שלו. README של המאגר גם מספק הדרכה לגבי ההעברות שכדאי לשקול ו"הזמנה" רלוונטית של מודולי העברה.

8. מקורות מידע נוספים

בעיות/משוב על Codelabs עם מודול ההעברה של App Engine

אם נתקלתם בבעיות ב-Codelab הזה, צריך קודם לחפש את הבעיה לפני השליחה. קישורים לחיפוש וליצירת בעיות חדשות:

משאבים להעברה

בטבלה שלמטה מופיעים הקישורים לתיקיות המאגר של מודול 8 (START) ומודול 9 (FINISH). אפשר לגשת אליהן גם דרך המאגר לכל העברות Codelab ב-App Engine, שאותו ניתן לשכפל או להוריד בקובץ ZIP.

Codelab

ֶPython 3

יחידת לימוד 2

קוד

יחידת לימוד 11

קוד

מקורות מידע אונליין

בהמשך מופיעים מקורות מידע מקוונים שעשויים להיות רלוונטיים למדריך זה:

App Engine

Cloud Functions

מידע אחר בענן

סרטונים

רישיון

היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.