איך להשתמש ב-blobstore של App Engine (מודול 15)

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

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

בשיעור ה-Codelab הזה של יחידת לימוד 15 נסביר איך להוסיף את השימוש ב-App Engine blobstore לאפליקציה לדוגמה מיחידת לימוד 0. אחרי שתסיימו את יחידת הלימוד הזו, תהיו מוכנים להעביר את השימוש ל-Cloud Storage ביחידת הלימוד הבאה (מספר 16).

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

  • הוספת השימוש ב-API או בספרייה של App Engine Blobstore
  • אחסון העלאות של משתמשים בשירות blobstore
  • הכנה לשלב הבא במעבר ל-Cloud Storage

הדרישות

סקר

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

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

איך היית מדרג את הניסיון שלך עם Python?

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

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

מתחילים רמת ביניים מתקדמים

2. רקע

כדי לעבור מ-App Engine Blobstore API, צריך להוסיף את השימוש בו לאפליקציית App Engine ndb הבסיסית הקיימת מיחידת לימוד 0. באפליקציה לדוגמה מוצגים עשרת הביקורים האחרונים של המשתמש. אנחנו משנים את האפליקציה כך שתבקש ממשתמש הקצה להעלות פריט מידע (קובץ) שמתאים ל "ביקור" שלו. אם המשתמש לא רוצה לעשות את זה, הוא יכול ללחוץ על "דילוג". לא משנה מה המשתמש יחליט, הדף הבא יציג את אותו פלט כמו האפליקציה ממודול 0 (ורבים מהמודולים האחרים בסדרה הזו). אחרי שמטמיעים את השילוב הזה של App Engine blobstore, אפשר להעביר אותו ל-Cloud Storage ב-Codelab הבא (יחידת לימוד 16).

ב-App Engine יש גישה למערכות התבניות Django ו-Jinja2. אחד הדברים שמבדילים את הדוגמה הזו (מלבד הוספת הגישה ל-Blobstore) הוא המעבר משימוש ב-Django ביחידת לימוד 0 ל-Jinja2 כאן ביחידת לימוד 15. שלב חשוב במודרניזציה של אפליקציות App Engine הוא להעביר את מסגרות האינטרנט מ-webapp2 ל-Flask. ב-Python 3, ברירת המחדל של מערכת התבניות היא Jinja2, אז נתחיל לעבור לכיוון הזה על ידי הטמעת Jinja2, אבל נמשיך להשתמש ב-webapp2 כדי לגשת ל-Blobstore. מכיוון ש-Flask משתמש ב-Jinja2 כברירת מחדל, לא נדרשים שינויים בתבנית בהמשך במודול 16.

3. הגדרה/הכנה

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

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

אם כבר פרסתם את האפליקציה של מודול 0, מומלץ להשתמש שוב באותו פרויקט (ובאותו קוד). אפשר גם ליצור פרויקט חדש או להשתמש בפרויקט קיים אחר. מוודאים שלפרויקט יש חשבון לחיוב פעיל ושהאפליקציה App Engine מופעלת.

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

אחת מהדרישות המוקדמות ל-Codelab הזה היא אפליקציה לדוגמה של מודול 0. אם אין לכם אותה, אתם יכולים להוריד אותה מהתיקייה START של מודול 0 (קישור בהמשך). ב-Codelab הזה נסביר על כל שלב, ובסוף נציג קוד שדומה למה שמופיע בתיקייה FINISH של מודול 15.

הספרייה של קובצי START של מודול 0 אמורה להיראות כך:

$ ls
README.md               index.html
app.yaml                main.py

3. פריסה (מחדש) של אפליקציית הבסיס

השלבים שנותרו לביצוע לפני ההעברה:

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

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

a7a9d2b80d706a2b.png

4. עדכון קובצי תצורה

app.yaml

אין שינויים מהותיים בהגדרות של האפליקציה, אבל כמו שציינו קודם, אנחנו עוברים מתבניות Django (ברירת המחדל) ל-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 ב-Jinja2. מה ישתנה?

  1. המטרה של המודול os היא ליצור נתיב קובץ לתבנית Django. אנחנו עוברים ל-Jinja2, שבו זה מטופל, ולכן אין יותר צורך ב-os ובמנוע הרינדור של תבניות Django,‏ google.appengine.ext.webapp.template, והם יוסרו.
  2. מייבאים את Blobstore API: google.appengine.ext.blobstore
  3. מייבאים את ה-handlers של Blobstore שנמצאים ב-framework המקורי של webapp – הם לא זמינים ב-webapp2: google.appengine.ext.webapp.blobstore_handlers
  4. מייבאים תמיכה ב-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. קטע הקוד הבא כולל את המחלקה הרגילה של ה-handler לבקשות של 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)

הנה ייצוג חזותי של השינויים שבוצעו עד עכשיו:

2270783776759f7f.png

תמיכה בהעלאת קבצים

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

  1. הבקשה הראשית של ה-handler‏ GET לא מאחזרת יותר את הביקורים האחרונים לתצוגה. במקום זאת, המשתמש מתבקש להעלות קובץ.
  2. כשמשתמש קצה שולח קובץ להעלאה או מדלג על התהליך הזה, POST מהטופס מעביר את השליטה ל-UploadHandler החדש, שנגזר מ-google.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler.
  3. השיטה POST של UploadHandler מבצעת את ההעלאה, קוראת ל-store_visit() כדי לרשום את הביקור ומפעילה הפניה אוטומטית מסוג HTTP 307 כדי להחזיר את המשתמש ל-"/", שם...
  4. ה-method‏ POST של ה-handler הראשי שולחת שאילתה (דרך fetch_visits()) ומציגה את הביקורים האחרונים. אם המשתמש בוחר באפשרות "דילוג", לא מועלה קובץ, אבל הביקור עדיין נרשם ואחריו מתבצעת אותה הפניה אוטומטית.
  5. התצוגה של הביקורים האחרונים כוללת שדה חדש שמוצג למשתמש: היפר-קישור "צפייה" אם יש קובץ העלאה זמין, או "אין" אם אין קובץ כזה. השינויים האלה מיושמים בתבנית ה-HTML, וגם נוסף טופס העלאה (מידע נוסף על כך יפורסם בקרוב).
  6. אם משתמש קצה לוחץ על הקישור "צפייה" של ביקור כלשהו עם סרטון שהועלה, הוא שולח בקשת GET ל-ViewBlobHandler חדש, שנגזר מ-google.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler , ומציג את הקובץ אם מדובר בתמונה (בדפדפן אם יש תמיכה), מבקש להוריד אם לא, או מחזיר שגיאת HTTP 404 אם לא נמצא.
  7. בנוסף לצמד החדש של מחלקות ה-handler ולצמד החדש של הנתיבים לשליחת תנועה אליהן, ה-handler הראשי צריך שיטה חדשה של POST כדי לקבל את ההפניה האוטומטית מסוג 307 שמתוארת למעלה.

לפני העדכונים האלה, האפליקציה של מודול 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) handler של העלאה עם שיטת POST, ‏2) 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שולח את הנתונים, וקוראת ל-upload handler כדי לשלוח את הקובץ ל-Blobstore.
  • ב-UploadHandler.post, יש קריאה אל blobstore_handlers.BlobstoreUploadHandler.get_uploads. זה הקסם האמיתי שמעביר את הקובץ ל-Blobstore ומחזיר מזהה ייחודי וקבוע לקובץ, ה-BlobKey שלו.
  • ב-ViewBlobHandler.get, קריאה ל-blobstore_handlers.BlobstoreDownloadHandler.send עם BlobKey של קובץ גורמת לאחזור הקובץ ולהעברה שלו לדפדפן של משתמש הקצה

הקריאות האלה מייצגות את רוב הגישה לתכונות שנוספו לאפליקציה. הנה ייצוג גרפי של קבוצת השינויים השנייה והאחרונה ב-main.py:

da2960525ac1b90d.png

עדכון תבנית HTML

חלק מהעדכונים באפליקציה הראשית משפיעים על ממשק המשתמש (UI) של האפליקציה, ולכן צריך לבצע שינויים תואמים בתבנית האינטרנט, למעשה שניים:

  1. צריך טופס להעלאת קבצים עם 3 רכיבי קלט: קובץ וזוג לחצני שליחה להעלאת קובץ ולדילוג, בהתאמה.
  2. כדי לעדכן את הפלט של הביקורים האחרונים, צריך להוסיף קישור "צפייה" לביקורים עם העלאת קובץ תואמת, או "ללא" במקרים אחרים.

לפני:

<!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:

8583e975f25aa9e7.png

שינוי אחרון: ב-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. זה מאוד נוח כי כל מזהי הפרויקטים הם ייחודיים, נכון?

העדכונים שבוצעו באפליקציה לדוגמה מעבירים את הקבצים שהועלו לקטגוריה הזו, אבל המפתחים יכולים לבחור מיקום ספציפי יותר. אפשר לגשת לקטגוריית ברירת המחדל באופן פרוגרמטי דרך google.appengine.api.app_identity.get_default_gcs_bucket_name(), וצריך לייבא מחדש אם רוצים לגשת לערך הזה, למשל כדי להשתמש בו בתור קידומת לארגון הקבצים שהועלו. לדוגמה, מיון לפי סוג קובץ:

f61f7a23a1518705.png

כדי להטמיע משהו כזה לתמונות, למשל, יהיה לכם קוד כזה יחד עם קוד שבודק את סוגי הקבצים כדי לבחור את שם הקטגוריה הרצוי:

ROOT_BUCKET = app_identity.get_default_gcs_bucket_name()
IMAGE_BUCKET = '%s/%s' % (ROOT_BUCKET, 'images')

כדי לאמת את סוג התמונה, אתם גם תאמתו את התמונות שהועלו באמצעות כלי כמו המודול imghdr של Python Standard Library. לבסוף, כדאי להגביל את גודל ההעלאות למקרה של גורמים זדוניים.

נניח שכל זה כבר נעשה. איך אפשר לעדכן את האפליקציה שלנו כדי לתמוך בציון המיקום שבו יאוחסנו הקבצים שהועלו? העיקרון הוא לשנות את הקריאה ל-blobstore.create_upload_url ב-MainHandler.get כדי לציין את המיקום הרצוי ב-Cloud Storage להעלאה, על ידי הוספת הפרמטר 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, אבל מספק את התשתית שצריך כדי להפיק מהדוגמה משהו נוסף, כפי שמוסבר בקטע הזה. בהמשך מוצג איור של ההבדלים בין main.py ל-main-gcs.py.

256e1ea68241a501.png

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

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

פריסה ואימות של האפליקציה

פורסים מחדש את האפליקציה באמצעות gcloud app deploy, ומוודאים שהיא פועלת כמו שצריך, עם חוויית משתמש (UX) שונה מזו של האפליקציה ממודול 0. עכשיו יש שני מסכים שונים באפליקציה, והראשון הוא הבקשה להעלאת קובץ הביקור:

f5b5f9f19d8ae978.pngבשלב הזה, משתמשי הקצה יכולים להעלות קובץ וללחוץ על "שליחה" או ללחוץ על "דילוג" כדי לא להעלות שום דבר. בשני המקרים, התוצאה היא מסך הביקורים האחרונים, שכולל עכשיו קישורי "צפייה" או "אין" בין חותמות הזמן של הביקורים לבין פרטי המבקרים:

f5ac6b98ee8a34cb.png

כל הכבוד! סיימתם את ה-Codelab הזה והוספתם את השימוש ב-App Engine Blobstore לאפליקציה לדוגמה של מודול 0. הקוד שלכם אמור עכשיו להתאים למה שנמצא בתיקייה FINISH (מודול 15). החלופה main-gcs.py נמצאת גם היא בתיקייה הזו.

הסרת המשאבים

כללי

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

חשוב לדעת: פריסה בפלטפורמת מחשוב בלי שרת (serverless computing) של Google Cloud, כמו App Engine, כרוכה בעלויות קטנות של פיתוח ואחסון. ל-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*ation, לדוגמה, "us" אם האפליקציה מתארחת בארה"ב.

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

ספציפי ל-Codelab הזה

השירותים שמפורטים בהמשך ייחודיים ל-Codelab הזה. מידע נוסף זמין במסמכי התיעוד של כל מוצר:

השלבים הבאים

ההעברה הלוגית הבאה שכדאי לשקול מופיעה ביחידת לימוד 16, שבה מוסבר למפתחים איך לעבור משירות Blobstore של App Engine לשימוש בספריית הלקוח של Cloud Storage. היתרונות של השדרוג כוללים גישה לתכונות נוספות של Cloud Storage, והיכרות עם ספריית לקוח שפועלת באפליקציות מחוץ ל-App Engine, בין אם ב-Google Cloud, בעננים אחרים או אפילו באופן מקומי. אם אתם לא צריכים את כל התכונות שזמינות ב-Cloud Storage או שאתם חוששים מההשפעה על העלות, אתם יכולים להמשיך להשתמש ב-Blobstore של App Engine.

מעבר ליחידת לימוד 16, יש עוד הרבה אפשרויות העברה, כמו Cloud NDB ו-Cloud Datastore, ‏Cloud Tasks או Cloud Memorystore. יש גם העברות בין מוצרים ל-Cloud Run ול-Cloud Functions. במאגר ההעברה יש את כל דוגמאות הקוד, קישורים לכל ה-Codelabs והסרטונים הזמינים, וגם הנחיות לגבי ההעברות שכדאי לשקול ו "סדר" ההעברות הרלוונטי.

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

בעיות או משוב בנוגע ל-Codelab

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

משאבים להעברת נתונים

בטבלה הבאה יש קישורים לתיקיות המאגר של מודול 0 (התחלה) ומודול 15 (סיום). אפשר גם לגשת אליהם מהמאגר של כל ההעברות ב-App Engine codelab, שאותו אפשר לשכפל או להוריד כקובץ ZIP.

Codelab

Python 2

Python 3

יחידת לימוד 0

קוד

לא רלוונטי

מודול 15 (ה-Codelab הזה)

קוד

לא רלוונטי

משאבים באינטרנט

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

App Engine

Google Cloud

Python

סרטונים

רישיון

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