1. סקירה כללית
סדרת הServerless Migration Station של Codelabs (מדריכים מעשיים בקצב עצמי) וסרטונים קשורים נועדו לעזור להעביר מפתחים ללא שרת (serverless) של Google Cloud, באמצעות העברת אפליקציות מדור קודם באמצעות שירותי Google Cloud. כך האפליקציות שלכם יהיו יותר ניידות ויהיו לכם יותר אפשרויות וגמישות, כך שתוכלו להשתלב עם מגוון רחב יותר של מוצרי Cloud ולגשת אליהם בקלות, ולהשדרג בקלות רבה יותר לגרסאות חדשות יותר של שפות. הסדרה מתמקדת בהתחלה במשתמשי Cloud הראשונים, ובעיקר מפתחי App Engine (בסביבה סטנדרטית), אבל היא רחבה מספיק כדי לכלול פלטפורמות אחרות ללא שרת (serverless), כמו Cloud Functions ו-Cloud Run, או במקומות אחרים, אם רלוונטי.
המטרה של ה-Codelab הזה היא לנייד את האפליקציה לדוגמה של מודול 8 ל-Python 3, וגם להעביר את הגישה של Datastore (Cloud Firestore במצב Datastore) משימוש ב-Cloud NDB לספריית הלקוח המקורית של Cloud Datastore ולשדרג לגרסה העדכנית של ספריית הלקוח של Cloud Tasks.
הוספנו את השימוש בתכונה 'תור המשימות' למשימות push במודול 7, ואז העברנו את השימוש הזה ל-Cloud Tasks במודול 8. כאן במודול 9, נמשיך אל Python 3 ו-Cloud Datastore. משתמשים שמשתמשים בתכונה 'תורי משימות' למשימות משיכה יועברו ל-Cloud Pub/Sub ויפנו למודולים 18-19 במקום זאת.
כאן אפשר להבין איך
- העברת האפליקציה לדוגמה של מודול 8 ל-Python 3
- העברת הגישה של Datastore מ-Cloud NDB לספריות לקוח של Cloud Datastore
- שדרוג לגרסה האחרונה של ספריית הלקוח ב-Cloud Tasks
למה תזדקק?
- פרויקט ב-Google Cloud Platform עם חשבון פעיל לחיוב ב-GCP
- מיומנויות בסיסיות ב-Python
- ידע בעבודה עם פקודות Linux נפוצות
- ידע בסיסי פיתוח ופריסה של אפליקציות App Engine
- אפליקציה של App Engine מסוג מודול 8 פעיל: משלימים את Module 8 Codelab (מומלץ) או מעתיקים את אפליקציית מודול 8 מהמאגר
סקר
איך תשתמשו במדריך הזה?
איזה דירוג מגיע לדעתך לחוויה שלך עם Python?
איזה דירוג מגיע לדעתך לחוויית השימוש שלך בשירותי Google Cloud?
2. רקע
מודול 7 מדגים איך להשתמש במשימות דחיפת תור המשימות של App Engine באפליקציות Python 2 Flask App Engine. במודול 8, מעבירים את האפליקציה מ'תור המשימות' ל-Cloud Tasks. כאן במודול 9, אתם ממשיכים בתהליך הניוד של האפליקציה ל-Python 3 ומעבירים את הגישה ב-Datastore משימוש ב-Cloud NDB לספריית הלקוח המקורית של Cloud Datastore.
מכיוון ש-Cloud NDB פועל גם ב-Python 2 וגם ב-3, הוא מספיק למשתמשי App Engine שמניידים את האפליקציות שלהם מ-Python 2 לגרסה 3. העברה נוספת של ספריות לקוח ל-Cloud Datastore היא אופציונלית לחלוטין, ויש סיבה אחת בלבד להתחשב בה: יש לכם אפליקציות שאינן של App Engine (ו/או אפליקציות Python 3 App Engine) שכבר משתמשות בספריית הלקוח של Cloud Datastore ואתם רוצים לאחד את ה-codebase כדי לגשת ל-Datastore באמצעות ספריית לקוח אחת בלבד. Cloud NDB נוצר במיוחד למפתחים של Python 2 App Engine ככלי להעברת Python 3, כך שאם אין לך עדיין קוד באמצעות ספריית הלקוח של Cloud Datastore, לא צריך לבצע את ההעברה הזו.
לבסוף, הפיתוח של ספריית הלקוח של Cloud Tasks נמשך רק ב-Python 3, אז אנחנו "מעבירים" מאחת מהגרסאות הסופיות של Python 2 ועד הגרסה העכשווית של Python 3. למרבה המזל, אין שינויים שעלולים לגרום לכשל ב-Python 2, כלומר לא צריך לעשות שום דבר נוסף.
המדריך הזה כולל את השלבים הבאים:
- הגדרה/עבודה מוקדמת
- עדכון ההגדרות האישיות
- שינוי קוד האפליקציה
3. הגדרה/עבודה מוקדמת
בקטע הזה נסביר איך:
- הגדרת פרויקט ב-Cloud
- אחזור של אפליקציה בסיסית לדוגמה
- (מחדש) פריסה ואימות של אפליקציה בסיסית
השלבים האלה נועדו לוודא שאתם מתחילים לעבוד עם קוד ושהוא מוכן להעברה לשירותי Cloud.
1. הגדרת הפרויקט
אם השלמתם את Module 8 Codelab, השתמשו שוב באותו פרויקט (ובקוד). לחלופין, אפשר ליצור פרויקט חדש לגמרי או להשתמש שוב בפרויקט קיים אחר. צריך לוודא שלפרויקט יש חשבון פעיל לחיוב ואפליקציית App Engine מופעלת. אתם יכולים למצוא את מזהה הפרויקט שלכם למקרה הצורך במהלך ה-Codelab הזה, ולהשתמש בו בכל פעם שאתם נתקלים במשתנה PROJECT_ID
.
2. אחזור של אפליקציה בסיסית לדוגמה
אחת מהדרישות המוקדמות היא אפליקציית App Engine פעילה של Module 8: משלימים את Codelab ב-Module 8 (מומלץ) או מעתיקים את אפליקציית Module 8 מהמאגר. בין אם אתם משתמשים בזו שלכם או שלנו, קוד מודול 8 הוא המקום שבו נתחיל ("התחלה"). ה-Codelab הזה ינחה אותך לאורך ההעברה, ויסתיים בקוד שדומה למה שמופיע בתיקיית המאגר של מודול 9 ("FINISH").
- START: מאגר של מודול 8
- FINISH: מאגר מודול 9
- כל המאגר (שכפול או הורדה של קובץ ZIP)
התיקייה צריכה להיראות כמו בדוגמה הבאה, אולי עם התיקייה lib
, בלי קשר לאפליקציית Module 7 שבה אתם משתמשים:
$ ls README.md appengine_config.py requirements.txt app.yaml main.py templates
3. (מחדש) פריסה ואימות של אפליקציה בסיסית
מבצעים את השלבים הבאים כדי לפרוס את אפליקציית מודול 8:
- אם קיימת תיקייה כזו, מוחקים את התיקייה
lib
ומריצים את הפקודהpip install -t lib -r requirements.txt
כדי לאכלס מחדש אתlib
. יכול להיות שתצטרכו להשתמש ב-pip2
במקום זאת, אם במחשב הפיתוח שלכם מותקנות גם Python 2 וגם גרסה 3. - חשוב לוודא שהתקנתם ואתחלתם את כלי שורת הפקודה
gcloud
, ושבדקתם את השימוש בו. - (אופציונלי) אם לא רוצים להזין את ה-
PROJECT_ID
עם כל פקודתgcloud
שיוצרים, מגדירים את הפרויקט ב-Cloud לערךgcloud config set project
PROJECT_ID
. - פריסת האפליקציה לדוגמה באמצעות
gcloud app deploy
- מוודאים שהאפליקציה פועלת כמצופה ללא בעיות. אם השלמתם את ה-Codelab של מודול 8, האפליקציה מציגה את המבקרים המובילים יחד עם הביקורים האחרונים (איור בהמשך). למטה אפשר לראות אילו משימות ישנות יותר יימחקו.
4. עדכון ההגדרות האישיות
requirements.txt
ה-requirements.txt
החדש כמעט זהה לזה שבמודול 8, עם שינוי גדול אחד בלבד: מחליפים את google-cloud-ndb
ב-google-cloud-datastore
. מבצעים את השינוי כך שקובץ requirements.txt
ייראה כך:
flask
google-cloud-datastore
google-cloud-tasks
בקובץ requirements.txt
הזה אין מספרי גרסאות, ולכן נבחרו הגרסאות האחרונות. במקרה של חוסר תאימות, מומלץ להשתמש במספרי גרסאות כדי לנעול גרסאות פעילות של האפליקציה.
app.yaml
זמן הריצה של App Engine מהדור השני לא תומך בספריות מובנות של צד שלישי כמו ב- 2.x ולא תומך בהעתקה של ספריות לא מובנות. הדרישה היחידה לחבילות של צד שלישי היא לרשום אותן ב-requirements.txt
. כתוצאה מכך, ניתן למחוק את כל הקטע libraries
של app.yaml
.
עדכון נוסף הוא שסביבת זמן הריצה של Python 3 דורשת שימוש ב-frameworks של אינטרנט שעושות ניתוב משלהן. לכן צריך לשנות את כל רכיבי ה-handler של הסקריפטים ל-auto
. עם זאת, צריך לשנות את כל המסלולים ל-auto
, ולא מוצגים קבצים סטטיים מהאפליקציה לדוגמה, לכן לא רלוונטי שיהיו אף handlers. לכן צריך להסיר גם את הקטע handlers
כולו.
הדבר היחיד שדרוש ב-app.yaml
הוא להגדיר את סביבת זמן הריצה לגרסה נתמכת של Python 3, למשל 3.10. מבצעים את השינוי הזה כך שה-app.yaml
החדש והמקוצר תהיה רק השורה היחידה הזו:
runtime: python310
מחיקת appengine_config.py ו-lib
סביבות זמן ריצה של App Engine מהדור הבא חידשו את השימוש בחבילות של צד שלישי:
- ספריות מובנות הן ספריות שנבדקו על ידי Google וזמינות בשרתי App Engine, כנראה כי הן מכילות קוד C/C++ שהמפתחים לא מורשים לפרוס בענן – הן כבר לא זמינות בסביבות זמני הריצה של הדור השני.
- אין יותר צורך להעתיק ספריות לא מובנות (שנקראות לפעמים 'ספק' או 'קיבוץ עצמי') בסביבות זמני הריצה של הדור השני. במקום זאת, הם צריכים להופיע ב-
requirements.txt
, שם מערכת ה-build מתקינה אותם באופן אוטומטי בזמן הפריסה.
בעקבות השינויים האלה בניהול חבילות של צד שלישי, אין צורך בקובץ appengine_config.py
או בתיקייה lib
, לכן צריך למחוק אותם. בסביבות זמני ריצה של הדור השני, App Engine מתקין באופן אוטומטי חבילות של צד שלישי שמפורטות ב-requirements.txt
. סיכום:
- לא לכלול ספריות של צד שלישי באריזה עצמית או בהעתקה. צריך לרשום אותם ב-
requirements.txt
- לא
pip install
בתוך תיקייה מסוגlib
, כלומר אין תקופה שלlib
תיקייה - אין רישום של ספריות מובְנות של צד שלישי (כלומר, לא בקטע
libraries
) ב-app.yaml
; צריך לרשום אותם ב-requirements.txt
- אין ספריות של צד שלישי להפניה מהאפליקציה שלך. פירוש הדבר שאין קובץ
appengine_config.py
הדרישה היחידה למפתחים היא להציג את כל הספריות הרצויות של צד שלישי ב-requirements.txt
.
5. עדכון קובצי אפליקציה
יש רק קובץ אפליקציה אחד, main.py
, כך שכל השינויים בקטע הזה ישפיעו רק על הקובץ הזה. לפניכם 'הבדלים' איור של השינויים הכוללים שצריך לבצע כדי לארגן מחדש את הקוד הקיים באפליקציה החדשה. אין לצפות מהקוראים לקרוא את הקוד שורה אחרי שורה, כי המטרה שלו היא לקבל סקירה כללית של מה שנחוץ בהגדרה מחדש (אבל אפשר לפתוח את הקוד בכרטיסייה חדשה או להוריד אותו ולהגדיל את התצוגה אם רוצים).
ייבוא ואתחול של עדכונים
קטע הייבוא ב-main.py
למודול 8 משתמש ב-Cloud NDB וב-Cloud Tasks. היא אמורה להיראות כך:
לפני:
from datetime import datetime
import json
import logging
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, tasks
app = Flask(__name__)
ds_client = ndb.Client()
ts_client = tasks.CloudTasksClient()
הרישום ביומן פשוט יותר ומשופר בסביבות זמני ריצה של דור שני, כמו Python 3:
- כדי ליהנות מחוויית רישום מקיפה ביומן, כדאי להשתמש ב-Cloud Logging
- לרישום פשוט ביומן, צריך לשלוח אל
stdout
(או אלstderr
) דרךprint()
- אין צורך להשתמש במודול
logging
של Python (לכן צריך להסיר אותו)
לכן, צריך למחוק את הייבוא של logging
ולהחליף את הערך של google.cloud.ndb
ב-google.cloud.datastore
. באופן דומה, משנים את ds_client
כדי להפנות ללקוח Datastore במקום ללקוח NDB. אחרי ביצוע השינויים, החלק העליון של האפליקציה החדשה נראה כך:
אחרי:
from datetime import datetime
import json
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import datastore, tasks
app = Flask(__name__)
ds_client = datastore.Client()
ts_client = tasks.CloudTasksClient()
העברה ל-Cloud Datastore
זה הזמן להחליף את השימוש בספריית הלקוח של NDB ב-Datastore. גם ל-App Engine NDB וגם ל-Cloud NDB נדרש מודל נתונים (מחלקה) האפליקציה הזו היא Visit
. הפונקציה store_visit()
פועלת באופן זהה בכל המודולים האחרים של העברה: היא רושמת ביקור על ידי יצירת רשומת Visit
חדשה, ושמירת כתובת ה-IP של הלקוח שמבקרים בו וסוכן המשתמש (סוג הדפדפן).
לפני:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
עם זאת, Cloud Datastore לא משתמש במחלקה של מודל נתונים, ולכן מוחקים את המחלקה. בנוסף, Cloud Datastore לא יוצר חותמת זמן באופן אוטומטי בזמן יצירת הרשומות, מה שמחייב אתכם לעשות זאת באופן ידני – הפעולה הזו מתבצעת באמצעות הקריאה datetime.now()
.
בלי סיווג הנתונים, הערך של store_visit()
שערכתם אמור להיראות כך:
אחרי:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
פונקציית המפתח היא fetch_visits()
. כלומר, הפקודה לא רק מבצעת את השאילתה המקורית עבור ה-Visit
האחרונים, אלא גם מאחזרת את חותמת הזמן של Visit
האחרונים המוצגים ויוצרת את משימת הדחיפה שקוראת ל-/trim
(כלומר trim()
) כדי למחוק בבת אחת את ה-Visit
הישנים. כאן הוא משתמש ב-Cloud NDB:
לפני:
def fetch_visits(limit):
'get most recent visits & add task to delete older visits'
with ds_client.context():
data = Visit.query().order(-Visit.timestamp).fetch(limit)
oldest = time.mktime(data[-1].timestamp.timetuple())
oldest_str = time.ctime(oldest)
logging.info('Delete entities older than %s' % oldest_str)
task = {
'app_engine_http_request': {
'relative_uri': '/trim',
'body': json.dumps({'oldest': oldest}).encode(),
'headers': {
'Content-Type': 'application/json',
},
}
}
ts_client.create_task(parent=QUEUE_PATH, task=task)
return (v.to_dict() for v in data), oldest_str
השינויים העיקריים:
- להחליף את שאילתת Cloud NDB לערך המקביל ב-Cloud Datastore; סגנונות השאילתה שונים מעט.
- ב-Datastore לא נדרש שימוש במנהל הקשר ולכן לא ניתן לחלץ את הנתונים שלו (באמצעות
to_dict()
) כמו ב-Cloud NDB. - החלפה של רישום השיחות ביומן ב-
print()
לאחר השינויים האלה, fetch_visits()
ייראה כך:
אחרי:
def fetch_visits(limit):
'get most recent visits & add task to delete older visits'
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
visits = list(query.fetch(limit=limit))
oldest = time.mktime(visits[-1]['timestamp'].timetuple())
oldest_str = time.ctime(oldest)
print('Delete entities older than %s' % oldest_str)
task = {
'app_engine_http_request': {
'relative_uri': '/trim',
'body': json.dumps({'oldest': oldest}).encode(),
'headers': {
'Content-Type': 'application/json',
},
}
}
ts_client.create_task(parent=QUEUE_PATH, task=task)
return visits, oldest_str
בדרך כלל זה כל מה שנחוץ. לצערנו, יש בעיה משמעותית אחת.
(כנראה) יצירת תור חדש (push)
במודול 7 הוספנו את השימוש ב-App Engine taskqueue
לאפליקציית מודול 1 הקיימת. אחד היתרונות המרכזיים של שימוש במשימות דחיפה כתכונה מדור קודם של App Engine הוא "ברירת מחדל". 'הבאים בתור' נוצר באופן אוטומטי. כשהאפליקציה הזו הועברה ל-Cloud Tasks במודול 8, תור ברירת המחדל כבר היה שם, כך שעדיין לא היינו צריכים לדאוג לגבי זה באותו זמן. זה משתנה כאן במודול 9.
היבט קריטי אחד שחשוב להביא בחשבון הוא שאפליקציית App Engine החדשה כבר לא משתמשת בשירותי App Engine, ולכן כבר אי אפשר להניח ש-App Engine יוצר תור משימות באופן אוטומטי במוצר אחר (Cloud Tasks). כפי שכתוב, יצירת משימה ב-fetch_visits()
(בתור שלא קיים) תיכשל. דרושה פונקציה חדשה כדי לבדוק אם קיים תור (ברירת מחדל), ואם לא, ליצור תור.
צריך לקרוא לפונקציה _create_queue_if()
ולהוסיף אותה לאפליקציה ממש מעל fetch_visits()
, כי שם היא נקראת. גוף הפונקציה להוספה:
def _create_queue_if():
'app-internal function creating default queue if it does not exist'
try:
ts_client.get_queue(name=QUEUE_PATH)
except Exception as e:
if 'does not exist' in str(e):
ts_client.create_queue(parent=PATH_PREFIX,
queue={'name': QUEUE_PATH})
return True
לפונקציה create_queue()
של Cloud Tasks נדרש שם הנתיב המלא של התור, חוץ משם התור. כדי לשמור על פשטות, אפשר ליצור משתנה נוסף PATH_PREFIX
שמייצג את QUEUE_PATH
פחות שם התור (QUEUE_PATH.rsplit('/', 2)[0]
). מוסיפים את ההגדרה שלו בחלק העליון של הדף כך שבלוק הקוד עם כל ההקצאות הקבועות ייראה כך:
_, PROJECT_ID = google.auth.default()
REGION_ID = 'REGION_ID' # replace w/your own
QUEUE_NAME = 'default' # replace w/your own
QUEUE_PATH = ts_client.queue_path(PROJECT_ID, REGION_ID, QUEUE_NAME)
PATH_PREFIX = QUEUE_PATH.rsplit('/', 2)[0]
עכשיו צריך לשנות את השורה האחרונה ב-fetch_visits()
כך שתשתמש ב-_create_queue_if()
. קודם יוצרים את התור אם צריך ואז יוצרים את המשימה לאחר מכן:
if _create_queue_if():
ts_client.create_task(parent=QUEUE_PATH, task=task)
return visits, oldest_str
עכשיו הנתונים של _create_queue_if()
ושל fetch_visits()
צריכים להיראות כך באופן מצטבר:
def _create_queue_if():
'app-internal function creating default queue if it does not exist'
try:
ts_client.get_queue(name=QUEUE_PATH)
except Exception as e:
if 'does not exist' in str(e):
ts_client.create_queue(parent=PATH_PREFIX,
queue={'name': QUEUE_PATH})
return True
def fetch_visits(limit):
'get most recent visits & add task to delete older visits'
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
visits = list(query.fetch(limit=limit))
oldest = time.mktime(visits[-1]['timestamp'].timetuple())
oldest_str = time.ctime(oldest)
print('Delete entities older than %s' % oldest_str)
task = {
'app_engine_http_request': {
'relative_uri': '/trim',
'body': json.dumps({'oldest': oldest}).encode(),
'headers': {
'Content-Type': 'application/json',
},
}
}
if _create_queue_if():
ts_client.create_task(parent=QUEUE_PATH, task=task)
return visits, oldest_str
חוץ מזה שצריך להוסיף את הקוד הנוסף הזה, רוב הקוד של Cloud Tasks נשאר ללא שינוי ממודול 8. קטע הקוד האחרון שצריך לבחון הוא ה-handler של המשימה.
עדכון handler (התראות) במשימה
ב-handler של המשימות, trim()
, שאילתות הקוד של Cloud NDB לביקורים ישנים יותר מהישן לחדש. היא משתמשת בשאילתה למפתחות בלבד כדי לזרז את התהליך – למה לאחזר את כל הנתונים אם צריך רק את מזהי הביקורים? אחרי שמקבלים את כל מזהי הביקורים, מוחקים את כולם בקבוצה באמצעות הפונקציה delete_multi()
של Cloud NDB.
לפני:
@app.route('/trim', methods=['POST'])
def trim():
'(push) task queue handler to delete oldest visits'
oldest = float(request.get_json().get('oldest'))
with ds_client.context():
keys = Visit.query(
Visit.timestamp < datetime.fromtimestamp(oldest)
).fetch(keys_only=True)
nkeys = len(keys)
if nkeys:
logging.info('Deleting %d entities: %s' % (
nkeys, ', '.join(str(k.id()) for k in keys)))
ndb.delete_multi(keys)
else:
logging.info(
'No entities older than: %s' % time.ctime(oldest))
return '' # need to return SOME string w/200
בדומה ל-fetch_visits()
, רוב השינויים כוללים החלפת קוד Cloud NDB ל-Cloud Datastore, שינוי סגנונות של השאילתות, הסרת השימוש במנהל ההקשר ושינוי הקריאות לרישום ביומן ל-print()
.
אחרי:
@app.route('/trim', methods=['POST'])
def trim():
'(push) task queue handler to delete oldest visits'
oldest = float(request.get_json().get('oldest'))
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '<', datetime.fromtimestamp(oldest))
query.keys_only()
keys = list(visit.key for visit in query.fetch())
nkeys = len(keys)
if nkeys:
print('Deleting %d entities: %s' % (
nkeys, ', '.join(str(k.id) for k in keys)))
ds_client.delete_multi(keys)
else:
print('No entities older than: %s' % time.ctime(oldest))
return '' # need to return SOME string w/200
אין שינויים ב-handler הראשי של האפליקציה root()
.
יציאה אל Python 3
האפליקציה לדוגמה הזו מיועדת לפעול גם ב-Python בגרסה 2 וגם ב-3. השינויים הספציפיים ל-Python 3 כבר פורטו בקטעים הרלוונטיים במדריך הזה. אין שלבים נוספים או ספריות תאימות.
עדכון ל-Cloud Tasks
הגרסה הסופית של ספריית הלקוח של Cloud Tasks שתומכת ב-Python 2 היא 1.5.0. נכון לזמן הכתיבה הזו, הגרסה העדכנית ביותר של ספריית הלקוח עבור Python 3 תואמת באופן מלא לגרסה הזו, כך שאין צורך בעדכונים נוספים.
עדכון של תבנית HTML
גם בקובץ תבנית ה-HTML, templates/index.html
, אין צורך לבצע שינויים, לכן סיכום זה כולל את כל השינויים הנחוצים כדי להגיע לאפליקציית מודול 9.
6. סיכום/ניקוי
פריסה ואימות של אפליקציה
אחרי שמשלימים את עדכוני הקוד, בעיקר את היציאה ל-Python 3, פורסים את האפליקציה באמצעות gcloud app deploy
. הפלט אמור להיות זהה לאפליקציות שבאפליקציה ממודולים 7 ו-8, אלא שהעברת את הגישה למסד הנתונים לספריית הלקוח של Cloud Datastore וששדרגתם ל-Python 3:
השלב הזה מסתיים ב-Codelab. אנחנו מזמינים אתכם להשוות את הקוד שלכם לקוד שמופיע בתיקיית מודול 9. מעולה!
הסרת המשאבים
כללי
אם סיימתם בינתיים, מומלץ להשבית את אפליקציית App Engine כדי להימנע מצבירת חיובים. עם זאת, אם אתם רוצים להתנסות בפיצ'רים נוספים או להתנסות בהם, בפלטפורמת App Engine יש מכסה בחינם, וכל עוד אתם לא חורגים ממכסת השימוש הזו, לא נחייב אתכם. הבקשה נועדה למחשוב, אבל ייתכן שיחולו חיובים גם על שירותים רלוונטיים של App Engine. למידע נוסף, יש לעיין בדף התמחור של האפליקציה. אם ההעברה הזו כוללת שירותי ענן אחרים, הם מחויבים בנפרד. בכל מקרה, אם רלוונטי, ראו "ספציפי ל-Codelab זה" שבהמשך.
גילוי נאות מלא, פריסה בפלטפורמת מחשוב ללא שרת (serverless) של Google Cloud, כמו App Engine, כרוכה בעלויות נמוכות של build ואחסון. ל-Cloud Build יש מכסה משלה בחינם, כמו גם ל-Cloud Storage. נפח האחסון של התמונה הזו תופס חלק מהמכסה. עם זאת, ייתכן שאתם גרים באזור שאין בו תוכנית ללא תשלום כזה, לכן כדאי שתהיו מודעים לשימוש שלכם בנפח האחסון כדי למזער את העלויות הפוטנציאליות. 'תיקיות' ספציפיות של Cloud Storage כדאי לבדוק:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
- הקישורים לנפח האחסון שלמעלה תלויים במאפיין
PROJECT_ID
ובמאפיין *LOC
*שלך, לדוגמה, "us
" אם האפליקציה מתארחת בארה"ב.
מצד שני, אם אתם לא מתכוונים להמשיך להשתמש באפליקציה הזו או ב-Codelabs קשורים אחרים ורוצים למחוק את הכול לחלוטין, כדאי להשבית את הפרויקט.
ספציפי ל-Codelab הזה
השירותים שמפורטים בהמשך הם ייחודיים ל-Codelab הזה. אפשר לקרוא מידע נוסף במסמכי התיעוד של כל מוצר:
- ל-Cloud Tasks יש תוכנית ללא תשלום; פרטים נוספים זמינים בדף התמחור שלו.
- שירות App Engine Datastore ניתן על ידי Cloud Datastore (Cloud Firestore במצב Datastore), שגם לו יש תוכנית ללא תשלום; בדף התמחור שלו יש מידע נוסף.
השלבים הבאים
סיימנו את ההעברה שלנו ממשימות הדחיפה לתור המשימות של App Engine אל Cloud Tasks. גם ההעברה האופציונלית מ-Cloud NDB ל-Cloud Datastore מתבצעת בעצמה (ללא 'תור משימות' או Cloud Tasks) במודול 3. בנוסף למודול 3, קיימים מודולים אחרים של העברה שמתמקדים בהפסקת השירותים בחבילה מהדור הקודם של App Engine, כולל:
- מודול 2: העברה מ-App Engine NDB ל-Cloud NDB
- מודול 3: העברה מ-Cloud NDB ל-Cloud Datastore
- מודולים 12-13: העברה מ-Memcache של App Engine ל-Cloud Memorystore
- מודולים 15-16: העברה מ-App Engine Blobstore ל-Cloud Storage
- מודולים 18-19: תור המשימות של App Engine (משימות משיכה) אל Cloud Pub/Sub
App Engine היא כבר לא הפלטפורמה היחידה ללא שרת (serverless) ב-Google Cloud. אם יש לכם אפליקציה קטנה של App Engine או אפליקציה שיש לה פונקציונליות מוגבלת ואתם רוצים להפוך אותה למיקרו-שירות (microservice) עצמאי, או שאתם רוצים לפצל אפליקציה מונוליתית למספר רכיבים לשימוש חוזר, כדאי לשקול לעבור ל-Cloud Functions. אם יצירת קונטיינרים הפכה לחלק מתהליך פיתוח האפליקציות שלכם, במיוחד אם היא מורכבת מצינור עיבוד נתונים של CI/CD (אינטגרציה רציפה (CI/CD)/פיתוח רציף (continuous delivery) או פריסה), מומלץ לעבור ל-Cloud Run. התרחישים האלה מתוארים במודולים הבאים:
- מעבר מ-App Engine ל-Cloud Functions: ראו מודול 11
- מעבר מ-App Engine ל-Cloud Run: אפשר לעיין במודול 4 ליצירת קונטיינרים לאפליקציה באמצעות Docker, או במודול 5 כדי לבצע אותו ללא קונטיינרים, ידע ב-Docker או
Dockerfile
המעבר לפלטפורמה אחרת ללא שרת הוא אופציונלי, ומומלץ לבדוק את האפשרויות הטובות ביותר לאפליקציות ולתרחישים לדוגמה לפני שמבצעים שינויים.
בלי קשר למודול ההעברה הרצוי, כל התוכן של תחנת המיגרציה ללא שרת (serverless) (codelabs, סרטונים, קוד מקור [אם הוא זמין]) יהיה זמין במאגר הקוד הפתוח שלו. README
של המאגר גם מספק הדרכה לגבי ההעברות שכדאי לשקול ו"הזמנה" רלוונטית של מודולי העברה.
7. מקורות מידע נוספים
בעיות/משוב על Codelabs
אם נתקלתם בבעיות ב-Codelab הזה, צריך קודם לחפש את הבעיה לפני השליחה. קישורים לחיפוש וליצירת בעיות חדשות:
משאבים להעברה
בטבלה שלמטה מופיעים הקישורים לתיקיות המאגר של מודול 8 (START) ומודול 9 (FINISH). אפשר לגשת אליהן גם דרך המאגר לכל העברות Codelab ב-App Engine, שאותו ניתן לשכפל או להוריד בקובץ ZIP.
Codelab | ֶPython 2 | ֶPython 3 |
(לא רלוונטי) | ||
יחידת לימוד 9 | (לא רלוונטי) |
מקורות מידע אונליין
בהמשך מופיעים מקורות מידע מקוונים שעשויים להיות רלוונטיים למדריך זה:
App Engine
- מסמכי התיעוד של App Engine
- זמן ריצה של Python 2 App Engine (סביבה סטנדרטית)
- זמן ריצה של Python 3 App Engine (סביבה סטנדרטית)
- ההבדלים בין Python 2 לבין Python 3 זמני ריצה של App Engine (סביבה רגילה)
- מדריך להעברת אפליקציות מ-Python 2-3 App Engine (סביבה סטנדרטית)
- מידע על תמחור ומכסות של App Engine
NDB בענן
Cloud Datastore
Cloud Tasks
מידע אחר בענן
- Python ב-Google Cloud Platform
- ספריות הלקוח של Google Cloud Python
- "חינם תמיד" ב-Google Cloud שכבה
- Google Cloud SDK (כלי שורת הפקודה
gcloud
) - כל משאבי העזרה של Google Cloud
רישיון
היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.