1. סקירה כללית
מטרת סדרת ה-codelabs של Serverless Migration Station (הדרכות מעשיות בקצב אישי) והסרטונים שקשורים אליה היא לעזור למפתחים של Google Cloud Serverless לחדש את האפליקציות שלהם. לשם כך, הם מקבלים הדרכה לגבי העברה אחת או יותר, בעיקר מעבר משירותים מדור קודם. כך האפליקציות שלכם יהיו ניידות יותר, ותקבלו יותר אפשרויות וגמישות. תוכלו לשלב את האפליקציות עם מגוון רחב יותר של מוצרי Cloud ולגשת אליהם, ולשדרג בקלות רבה יותר לגרסאות חדשות יותר של השפה. הסדרה הזו מתמקדת בהתחלה במשתמשי הענן הראשונים, בעיקר מפתחים של App Engine (סביבה רגילה), אבל היא רחבה מספיק כדי לכלול פלטפורמות אחרות של Serverless כמו Cloud Functions ו-Cloud Run, או במקומות אחרים אם רלוונטי.
ב-Codelab הזה (מודול 15) מוסבר איך להוסיף נתוני שימוש ב-App Engine blobstore לאפליקציה לדוגמה ממודול 0. אחר כך תוכלו להעביר את השימוש הזה ל-Cloud Storage, כפי שמוסבר במודול 16.
כאן אפשר להבין איך
- הוספת שימוש ב-App Engine Blobstore API/library
- אחסון העלאות של משתמשים בשירות
blobstore - הכנה לשלב הבא של המעבר ל-Cloud Storage
הדרישות
- פרויקט ב-Google Cloud Platform עם חשבון לחיוב פעיל ב-GCP
- מיומנויות בסיסיות ב-Python
- ידע מעשי בפקודות נפוצות של Linux
- ידע בסיסי בפיתוח ופריסה של אפליקציות App Engine
- אפליקציית App Engine של מודול 0 (אפשר להוריד מהמאגר)
סקר
איך תשתמשו במדריך הזה?
איך היית מדרג את חוויית השימוש שלך ב-Python?
איזה דירוג מתאים לדעתך לחוויית השימוש שלך בשירותי Google Cloud?
2. רקע
כדי לבצע מיגרציה מ-App Engine Blobstore API, מוסיפים את השימוש בו לאפליקציית App Engine הקיימת ndb ממודול 0. באפליקציה לדוגמה מוצגים עשרת הביקורים האחרונים של המשתמש. אנחנו משנים את האפליקציה כך שהיא תבקש ממשתמש הקצה להעלות ארטיפקט (קובץ) שמתאים ל'ביקור' שלו. אם המשתמש לא רוצה לעשות זאת, יש לו אפשרות 'דילוג'. לא משנה מה ההחלטה של המשתמש, הדף הבא מציג את אותה הפלט כמו האפליקציה ממודול 0 (והרבה מהמודולים האחרים בסדרה הזו). אחרי שמטמיעים את השילוב הזה של App Engine blobstore, אפשר להעביר אותו אל Cloud Storage בסדנת הקוד הבאה (מודול 16).
App Engine מספק גישה למערכות התבניות Django ו-Jinja2. דבר נוסף שמבדיל את הדוגמה הזו (מלבד הוספת גישה ל-Blobstore) הוא המעבר משימוש ב-Django במודול 0 לשימוש ב-Jinja2 במודול 15. שלב חשוב במודרניזציה של אפליקציות App Engine הוא העברה של מסגרות אינטרנט מ-webapp2 ל-Flask. האחרון משתמש ב-Jinja2 כמערכת ברירת המחדל ליצירת תבניות, ולכן אנחנו מתחילים לפעול בכיוון הזה על ידי הטמעה של Jinja2 תוך שמירה על webapp2 לגישה ל-Blobstore. מכיוון ש-Flask משתמש ב-Jinja2 כברירת מחדל, לא יהיה צורך לבצע שינויים בתבנית בהמשך, במודול 16.
3. הגדרה/עבודה מקדימה
לפני שנתחיל בחלק העיקרי של המדריך, צריך להגדיר את הפרויקט, לקבל את הקוד ולפרוס את אפליקציית ה-Baseline כדי להתחיל עם קוד עובד.
1. הגדרת פרויקט
אם כבר פרסתם את אפליקציית מודול 0, מומלץ להשתמש מחדש באותו פרויקט (ובאותו קוד). אפשר גם ליצור פרויקט חדש לגמרי או להשתמש בפרויקט קיים אחר. מוודאים שלפרויקט יש חשבון פעיל לחיוב ושהשירות App Engine מופעל.
2. קבלת אפליקציה לדוגמה של ערך בסיס
אחד מהתנאים המוקדמים ל-codelab הזה הוא שיש לכם אפליקציית דוגמה תקינה של מודול 0. אם אין לכם אותה, תוכלו להוריד אותה מהתיקייה START של מודול 0 (הקישור מופיע בהמשך). ב-Codelab הזה מוסבר כל שלב, ובסופו מוצג קוד שדומה למה שמופיע בתיקייה FINISH של מודול 15.
- התחלה: תיקיית מודול 0 (Python 2)
- סיום: תיקיית מודול 15 (Python 2)
- מאגר שלם (לשיבוט או להורדה של קובץ ZIP)
הספרייה של קובצי ההתחלה של מודול 0 צריכה להיראות כך:
$ ls README.md index.html app.yaml main.py
3. (Re)Deploy baseline app
השלבים הנותרים שצריך לבצע עכשיו:
- כדאי להכיר מחדש את כלי שורת הפקודה
gcloud - פריסה מחדש של האפליקציה לדוגמה עם
gcloud app deploy - אישור שהאפליקציה פועלת ב-App Engine ללא בעיות
אחרי שתבצעו את השלבים האלה בהצלחה ותראו שאפליקציית האינטרנט פועלת (עם פלט שדומה לזה שמוצג בהמשך), תוכלו להוסיף לאפליקציה שימוש במטמון.

4. עדכון קובצי תצורה
app.yaml
אין שינויים מהותיים בהגדרת האפליקציה, אבל כמו שציינו קודם, אנחנו עוברים מ-Django templating (ברירת מחדל) ל-Jinja2. כדי לעבור, המשתמשים צריכים לציין את הגרסה האחרונה של Jinja2 שזמינה בשרתי App Engine. כדי לעשות זאת, צריך להוסיף אותה לקטע של ספריות צד שלישי מובנות ב-app.yaml.
לפני:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
עורכים את קובץ app.yaml ומוסיפים קטע חדש של libraries כמו בדוגמה הבאה:
אחרי:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
אין צורך לעדכן קובצי הגדרה אחרים, אז נמשיך לקובצי האפליקציה.
5. שינוי קבצים של אפליקציות
ייבוא ותמיכה ב-Jinja2
השינויים הראשונים ב-main.py כוללים הוספה של שימוש ב-Blobstore API והחלפה של Django templating ב-Jinja2. אלה השינויים שיחולו:
- המטרה של מודול
osהיא ליצור שם נתיב של קובץ לתבנית Django. אנחנו עוברים ל-Jinja2, שבו הטיפול הזה מתבצע, ולכן אין יותר צורך בשימוש ב-osובמנוע רינדור התבניות של Django, google.appengine.ext.webapp.template, ואנחנו מסירים אותם. - מייבאים את Blobstore API:
google.appengine.ext.blobstore - מייבאים את ה-handlers של Blobstore שנמצאים ב-framework המקורי
webapp– הם לא זמינים ב-webapp2:google.appengine.ext.webapp.blobstore_handlers - ייבוא תמיכה ב-Jinja2 מחבילת
webapp2_extras
לפני:
import os
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
כדי להטמיע את השינויים שברשימה שלמעלה, צריך להחליף את קטע הייבוא הנוכחי ב-main.py בקטע הקוד שלמטה.
אחרי:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
אחרי הייבוא, מוסיפים קוד boilerplate כדי לתמוך בשימוש ב-Jinja2 כמו שמוגדר במסמכי webapp2_extras. קטע הקוד הבא עוטף את המחלקה הרגילה של webapp2 לטיפול בבקשות בפונקציונליות של Jinja2, ולכן צריך להוסיף את בלוק הקוד הזה ל-main.py מיד אחרי הייבוא:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
הוספת תמיכה ב-Blobstore
בניגוד להעברות אחרות בסדרה הזו, שבהן אנחנו שומרים על הפונקציונליות או על הפלט של האפליקציה לדוגמה זהים (או כמעט זהים) בלי (הרבה) שינויים בחוויית המשתמש, בדוגמה הזו אנחנו חורגים מהנורמה בצורה משמעותית יותר. במקום לרשום מיד ביקור חדש ואז להציג את עשרת הביקורים האחרונים, אנחנו מעדכנים את האפליקציה כך שהיא תבקש מהמשתמש קובץ ארטיפקט כדי לרשום את הביקור שלו. משתמשי הקצה יכולים להעלות קובץ מתאים או לבחור באפשרות 'דילוג' כדי לא להעלות כלום. אחרי שתסיימו את השלב הזה, יוצג הדף 'הביקורים האחרונים'.
השינוי הזה מאפשר לאפליקציה שלנו להשתמש בשירות Blobstore כדי לאחסן (ואולי גם לעבד בהמשך) את התמונה או סוג קובץ אחר בדף הביקורים האחרונים.
עדכון מודל הנתונים והטמעת השימוש בו
אנחנו מאחסנים יותר נתונים, ובאופן ספציפי, מעדכנים את מודל הנתונים כדי לאחסן את המזהה (שנקרא BlobKey) של הקובץ שהועלה ל-Blobstore, ומוסיפים הפניה כדי לשמור את המזהה ב-store_visit(). מכיוון שהנתונים הנוספים האלה מוחזרים יחד עם כל השאר בשאילתה, fetch_visits() נשאר ללא שינוי.
אלה השינויים שיתבצעו בעקבות העדכונים האלה, עם file_blob, ndb.BlobKeyProperty:
לפני:
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'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
אחרי:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
לפניכם תמונה שממחישה את השינויים שבוצעו עד עכשיו:

תמיכה בהעלאות של קבצים
השינוי המשמעותי ביותר בפונקציונליות הוא תמיכה בהעלאות של קבצים, בין אם מדובר בהצגת בקשה למשתמש להעלות קובץ, בתמיכה בתכונה 'דילוג' או בעיבוד של קובץ שמתאים לביקור. הכול חלק מהתמונה. אלה השינויים שנדרשים כדי לתמוך בהעלאות של קבצים:
- הבקשה של המטפל הראשי
GETלא מאחזרת יותר את הביקורים האחרונים להצגה. במקום זאת, המשתמש מתבקש להעלות את הקובץ. - כשמשתמש קצה שולח קובץ להעלאה או מדלג על התהליך הזה,
POSTמהטופס מעביר את השליטה אלUploadHandlerהחדש, שנגזר מ-google.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler. - השיטה
UploadHandlerשלPOSTמבצעת את ההעלאה, קוראת ל-store_visit()כדי לרשום את הביקור ומפעילה הפניה אוטומטית מסוג HTTP 307 כדי להחזיר את המשתמש אל '/', כאשר... - השיטה
POSTשל המטפל הראשי שולחת שאילתה לגבי הביקורים האחרונים (דרךfetch_visits()) ומציגה אותם. אם המשתמש בוחר באפשרות 'דילוג', לא מתבצעת העלאה של קובץ, אבל הביקור עדיין נרשם ואחריו מתבצעת אותה הפניה אוטומטית. - התצוגה 'הביקורים האחרונים' כוללת שדה חדש שמוצג למשתמש. אם קובץ להעלאה זמין, מוצג קישור 'צפייה', אחרת מוצג 'ללא'. השינויים האלה מיושמים בתבנית ה-HTML, ובנוסף מתווסף טופס העלאה (מידע נוסף על כך יפורסם בקרוב).
- אם משתמש קצה לוחץ על הקישור 'הצגה' לביקור כלשהו עם סרטון שהועלה, נשלחת
GETבקשה ל-ViewBlobHandlerחדש, שנגזר מ-google.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler. הקובץ מוצג אם הוא תמונה (בדפדפן אם הוא נתמך), או שמוצגת בקשה להורדה אם הוא לא תמונה, או שמוחזרת שגיאת HTTP 404 אם הקובץ לא נמצא. - בנוסף לצמד החדש של מחלקות handler ולצמד חדש של נתיבים לשליחת תנועה אליהם, ה-handler הראשי צריך שיטת
POSTחדשה כדי לקבל את ההפניה האוטומטית 307 שמתוארת למעלה.
לפני העדכונים האלה, באפליקציה Module 0 היה רק handler ראשי עם שיטה GET ונתיב אחד:
לפני:
class MainHandler(webapp2.RequestHandler):
'main application (GET) handler'
def get(self):
store_visit(self.request.remote_addr, self.request.user_agent)
visits = fetch_visits(10)
tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(tmpl, {'visits': visits}))
app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
אחרי הטמעת העדכונים האלה, יש עכשיו שלושה handlers: 1) upload handler עם שיטת POST, 2) download handler של 'view blob' עם שיטת GET, 3) handler ראשי עם שיטות GET ו-POST. מבצעים את השינויים האלה כדי ששאר האפליקציה ייראו כמו בדוגמה שלמטה.
אחרי:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
יש כמה קריאות חשובות בקוד שזה עתה הוספנו:
- ב-
MainHandler.get, יש שיחה אלblobstore.create_upload_url. הקריאה הזו יוצרת את כתובת ה-URL שאליה הטופסPOSTנשלח, ומפעילה את ה-handler להעלאה כדי לשלוח את הקובץ ל-Blobstore. - ב-
UploadHandler.post, יש שיחה אלblobstore_handlers.BlobstoreUploadHandler.get_uploads. זה הקסם האמיתי שמעביר את הקובץ ל-Blobstore ומחזיר מזהה ייחודי וקבוע לקובץ הזה, שהואBlobKey. - ב-
ViewBlobHandler.get, קריאה ל-blobstore_handlers.BlobstoreDownloadHandler.sendעםBlobKeyשל קובץ גורמת לאחזור הקובץ ולהעברתו לדפדפן של משתמש הקצה
הקריאות האלה מייצגות את רוב הגישה לתכונות שנוספו לאפליקציה. הנה ייצוג גרפי של השינויים השני והאחרון ב-main.py:

עדכון תבנית HTML
חלק מהעדכונים באפליקציה הראשית משפיעים על ממשק המשתמש (UI) של האפליקציה, ולכן נדרשים שינויים תואמים בתבנית האינטרנט, למעשה שני שינויים:
- נדרש טופס להעלאת קבצים עם 3 רכיבי קלט: קובץ וצמד לחצני שליחה להעלאת קובץ ודילוג, בהתאמה.
- עדכון הפלט של הביקורים האחרונים על ידי הוספת קישור 'צפייה' לביקורים עם העלאת קובץ תואמת, או 'none' אחרת.
לפני:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
</body>
</html>
מבצעים את השינויים ברשימה שלמעלה כדי ליצור את התבנית המעודכנת:
אחרי:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
{% if upload_url %}
<h3>Welcome... upload a file? (optional)</h3>
<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><p></p>
<input type="submit"> <input type="submit" value="Skip">
</form>
{% else %}
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }}
<i><code>
{% if visit.file_blob %}
(<a href="/view/{{ visit.file_blob }}" target="_blank">view</a>)
{% else %}
(none)
{% endif %}
</code></i>
from {{ visit.visitor }}
</li>
{% endfor %}
</ul>
{% endif %}
</body>
</html>
בתמונה הזו מוצגים העדכונים הנדרשים ב-index.html:

שינוי אחרון הוא ש-Jinja2 מעדיף שהתבניות שלו יהיו בתיקייה templates, לכן צריך ליצור את התיקייה הזו ולהעביר את index.html לתוכה. בשלב הזה סיימתם את כל השינויים הנדרשים כדי להוסיף את השימוש ב-Blobstore לאפליקציית הדוגמה של מודול 0.
(אופציונלי) 'שיפור' של Cloud Storage
בסופו של דבר, האחסון ב-Blobstore התפתח ל-Cloud Storage. המשמעות היא שהעלאות ל-Blobstore גלויות במסוף Cloud, ובמיוחד בדפדפן Cloud Storage. השאלה היא איפה. התשובה היא קטגוריית Cloud Storage שמוגדרת כברירת מחדל באפליקציית App Engine. השם שלו הוא השם של הדומיין המלא של אפליקציית App Engine, PROJECT_ID.appspot.com. זה מאוד נוח כי כל מזהי הפרויקטים הם ייחודיים, נכון?
העדכונים שבוצעו באפליקציית הדוגמה גורמים להעלאת הקבצים ל-bucket הזה, אבל למפתחים יש אפשרות לבחור מיקום ספציפי יותר. אפשר לגשת אל דלי ברירת המחדל באופן פרוגרמטי באמצעות google.appengine.api.app_identity.get_default_gcs_bucket_name(), ולכן צריך לייבא מחדש אם רוצים לגשת לערך הזה, למשל כדי להשתמש בו כקידומת לארגון קבצים שהועלו. לדוגמה, מיון לפי סוג קובץ:

כדי להטמיע משהו כזה לתמונות, למשל, תצטרכו להשתמש בקוד כמו זה שבהמשך, יחד עם קוד שבודק את סוגי הקבצים כדי לבחור את שם הדלי הרצוי:
ROOT_BUCKET = app_identity.get_default_gcs_bucket_name()
IMAGE_BUCKET = '%s/%s' % (ROOT_BUCKET, 'images')
כדי לוודא את סוג התמונה, אפשר גם לאמת את התמונות שהועלו באמצעות כלי כמו הספרייה הרגילה של Python, מודול imghdr. לבסוף, כדאי להגביל את גודל ההעלאות למקרה של גורמים זדוניים.
נניח שכל זה כבר נעשה. איך אפשר לעדכן את האפליקציה שלנו כך שתתמוך בציון המיקום לאחסון הקבצים שהועלו? כדי לציין את המיקום הרצוי ב-Cloud Storage להעלאה, צריך לשנות את הקריאה ל-blobstore.create_upload_url ב-MainHandler.get ולהוסיף את הפרמטר gs_bucket_name כך:
blobstore.create_upload_url('/upload', gs_bucket_name=IMAGE_BUCKET))
מכיוון שזהו עדכון אופציונלי, אם רוצים לציין לאן ההעלאות צריכות להגיע, הוא לא חלק מהקובץ main.py במאגר. במקום זאת, יש מאגר עם שם חלופי main-gcs.py שזמין לבדיקה. במקום להשתמש בתיקייה נפרדת של קטגוריה, הקוד ב-main-gcs.py מאחסן העלאות בקטגוריית הבסיס (PROJECT_ID.appspot.com) בדיוק כמו ב-main.py, אבל הוא מספק את ה-scaffolding שדרושה לכם אם תרצו להפוך את הדוגמה למשהו נוסף, כמו שמוסבר בקטע הזה. למטה מוצגת המחשה של ההבדלים בין main.py ל-main-gcs.py.

6. סיכום/ניקוי
בקטע הזה מסכמים את ה-codelab הזה על ידי פריסת האפליקציה, אימות הפעולה שלה כמצופה ובכל פלט שמשתקף. אחרי אימות האפליקציה, מבצעים את שלבי הניקוי ושוקלים את השלבים הבאים.
פריסה ואימות של האפליקציה
מבצעים פריסה מחדש של האפליקציה עם gcloud app deploy, ומוודאים שהאפליקציה פועלת כמו שמתואר, עם חוויית משתמש שונה מזו של אפליקציית מודול 0. עכשיו יש באפליקציה שני מסכים שונים. הראשון הוא ההנחיה למילוי הטופס להעלאת קובץ הביקור:
משם, משתמשי הקצה יכולים להעלות קובץ וללחוץ על 'שליחה', או ללחוץ על 'דילוג' כדי לא להעלות כלום. בכל מקרה, התוצאה היא המסך של הביקור האחרון, שעכשיו מופיעים בו קישורים ל'צפייה' או 'ללא' בין חותמות הזמן של הביקור לבין פרטי המבקר:

סיימתם את ה-codelab הזה, והוספתם שימוש ב-Blobstore של App Engine לאפליקציית הדוגמה Module 0. הקוד שלכם צריך להיות זהה לקוד שבתיקייה FINISH (Module 15). הקובץ החלופי main-gcs.py נמצא גם הוא בתיקייה הזו.
הסרת המשאבים
כללי
אם סיימתם לעכשיו, מומלץ להשבית את האפליקציה שלכם ב-App Engine כדי להימנע מחיובים. עם זאת, אם רוצים לבצע עוד בדיקות או ניסויים, בפלטפורמת App Engine יש מכסת שימוש בחינם, ולכן כל עוד לא חורגים מרמת השימוש הזו, לא אמורים לחייב אתכם. החישוב הזה מתייחס ל-Compute, אבל יכול להיות שיהיו גם חיובים על שירותים רלוונטיים של App Engine. לכן, כדאי לעיין בדף התמחור שלו כדי לקבל מידע נוסף. אם ההעברה הזו כוללת שירותי ענן אחרים, הם יחויבו בנפרד. בכל מקרה, אם רלוונטי, כדאי לעיין בקטע 'ספציפי ל-codelab הזה' שבהמשך.
חשוב לדעת: פריסה בפלטפורמת מחשוב ללא שרת של Google Cloud, כמו App Engine, כרוכה בעלויות קלות של בנייה ואחסון. ל-Cloud Build יש מכסת שימוש משלו בחינם, כמו גם ל-Cloud Storage. האחסון של התמונה הזו תופס חלק מהמכסה. עם זאת, יכול להיות שאתם גרים באזור שבו אין תוכנית בחינם כזו, ולכן חשוב לעקוב אחרי השימוש בנפח האחסון הנדרש כדי לצמצם את העלויות הפוטנציאליות. התיקיות הספציפיות ב-Cloud Storage שצריך לבדוק כוללות:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- הקישורים לאחסון שלמעלה תלויים ב
PROJECT_IDובמיקום *LOC*ation, לדוגמה,usאם האפליקציה מאוחסנת בארה"ב.
מצד שני, אם אתם לא מתכוונים להמשיך עם האפליקציה הזו או עם Codelabs אחרים שקשורים להעברה, ואתם רוצים למחוק הכול באופן סופי, אתם יכולים להשבית את הפרויקט.
ספציפי ל-Codelab הזה
השירותים שמופיעים בהמשך הם ייחודיים ל-codelab הזה. מידע נוסף זמין במסמכי התיעוד של כל מוצר:
- השירות App Engine Blobstore נכלל במכסות ומגבלות של נתונים מאוחסנים, ולכן כדאי לעיין גם בדף התמחור של חבילות שירותים מדור קודם.
- שירות App Engine Datastore מסופק על ידי Cloud Datastore (Cloud Firestore במצב Datastore), שגם לו יש רמת שירות בחינם. מידע נוסף זמין במחירון שלו.
השלבים הבאים
ההעברה הבאה שכדאי לשקול מוסברת ביחידה 16, שבה מוסבר למפתחים איך להעביר את הנתונים משירות Blobstore של App Engine לשימוש בספריית הלקוח של Cloud Storage. השדרוג מאפשר לכם לגשת ליותר תכונות של Cloud Storage, ולהכיר ספריית לקוח שמתאימה לאפליקציות מחוץ ל-App Engine, בין אם ב-Google Cloud, בעננים אחרים או אפילו בשרתים מקומיים. אם אתם לא חושבים שאתם צריכים את כל התכונות שזמינות ב-Cloud Storage או שאתם חוששים מההשפעות שלו על העלויות, אתם יכולים להמשיך להשתמש ב-App Engine Blobstore.
מעבר למודול 16 יש עוד הרבה אפשרויות להעברה, כמו Cloud NDB ו-Cloud Datastore, Cloud Tasks או Cloud Memorystore. יש גם העברות בין מוצרים אל Cloud Run ו-Cloud Functions. מאגר ההעברה כולל את כל דוגמאות הקוד, קישורים לכל סדנאות ה-codelab והסרטונים שזמינים, וגם הנחיות לגבי ההעברות שכדאי לבצע וסדר ההעברות הרלוונטי.
7. מקורות מידע נוספים
בעיות או משוב לגבי Codelab
אם נתקלתם בבעיות ב-codelab הזה, כדאי לחפש את הבעיה לפני ששולחים דיווח. קישורים לחיפוש וליצירה של בעיות חדשות:
מקורות מידע על העברת נתונים
בטבלה שלמטה מופיעים קישורים לתיקיות של מאגר המידע עבור מודול 0 (התחלה) ומודול 15 (סיום). אפשר גם לגשת אליהם ממאגר המידע של כל ההעברות של Codelabs של App Engine, שאפשר לשכפל או להוריד כקובץ ZIP.
Codelab | Python 2 | Python 3 |
יחידת לימוד 0 | לא רלוונטי | |
יחידת לימוד 15 (ה-Codelab הזה) | לא רלוונטי |
משאבים באינטרנט
בהמשך מופיעים מקורות מידע באינטרנט שעשויים להיות רלוונטיים למדריך הזה:
App Engine
- שירות Blobstore של App Engine
- מכסות ומגבלות של נתונים מאוחסנים ב-App Engine
- מסמכי App Engine
- זמן ריצה של Python 2 App Engine (סביבה סטנדרטית)
- שימוש בספריות מובנות של App Engine ב-Python 2 App Engine
- מידע על התמחור ועל המכסות ב-App Engine
- השקת פלטפורמת App Engine מהדור השני (2018)
- השוואה בין פלטפורמות מהדור הראשון לבין פלטפורמות מהדור השני
- תמיכה לטווח ארוך בסביבות זמן ריצה מדור קודם
- מאגר דוגמאות להעברת תיעוד
- מאגר דוגמאות להעברה שנוצרו על ידי הקהילה
Google Cloud
- Python ב-Google Cloud Platform
- ספריות לקוח Python של Google Cloud
- רמת השימוש 'תמיד בחינם' ב-Google Cloud
- Google Cloud SDK (כלי שורת הפקודה של Google Cloud)
- כל מסמכי התיעוד של Google Cloud
Python
- מערכות תבניות של Django ו-Jinja2
webapp2web frameworkwebapp2מסמכי תיעודwebapp2_extrasקישוריםwebapp2_extrasמסמכי התיעוד של Jinja2
סרטונים
- Serverless Migration Station
- מסעות ללא שרת
- הרשמה למינוי לערוץ Google Cloud Tech
- הרשמה לניוזלטר של Google Developers
רישיון
עבודה זו מורשית תחת רישיון Creative Commons שמותנה בייחוס 2.0 כללי.