مهاجرت از App Engine Blobstore به Cloud Storage (ماژول 16)

1. بررسی اجمالی

مجموعه کدهای ایستگاه انتقال بدون سرور (آموزش‌های عملی) و ویدیوهای مرتبط با هدف کمک به توسعه‌دهندگان بدون سرور Google Cloud برای مدرن کردن برنامه‌های خود با هدایت آنها از طریق یک یا چند انتقال، عمدتاً از سرویس‌های قدیمی دور می‌شوند. انجام این کار برنامه های شما را قابل حمل تر می کند و گزینه ها و انعطاف پذیری بیشتری در اختیار شما قرار می دهد و به شما امکان می دهد با طیف وسیع تری از محصولات Cloud ادغام شده و به آنها دسترسی داشته باشید و راحت تر به نسخه های زبان جدیدتر ارتقا دهید. در حالی که در ابتدا بر روی اولین کاربران Cloud، عمدتاً توسعه دهندگان App Engine (محیط استاندارد) تمرکز می شود، این مجموعه به اندازه کافی گسترده است که شامل سایر پلتفرم های بدون سرور مانند Cloud Functions و Cloud Run یا در صورت وجود جاهای دیگر است.

این کد لبه به شما می آموزد که چگونه از App Engine Blobstore به فضای ذخیره سازی ابری مهاجرت کنید. همچنین مهاجرت های ضمنی از:

برای اطلاعات گام به گام بیشتر به هر ماژول مهاجرت مرتبط مراجعه کنید.

شما یاد خواهید گرفت که چگونه

  • استفاده از App Engine Blobstore API/کتابخانه را اضافه کنید
  • آپلودهای کاربران را در سرویس Blobstore ذخیره کنید
  • برای مرحله بعدی مهاجرت به فضای ذخیره سازی ابری آماده شوید

آنچه شما نیاز دارید

نظرسنجی

چگونه از این آموزش استفاده خواهید کرد؟

فقط از طریق آن را بخوانید آن را بخوانید و تمرینات را کامل کنید

تجربه خود را با پایتون چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

تجربه خود را در استفاده از خدمات Google Cloud چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

2. پس زمینه

این نرم افزار کد با نمونه برنامه ماژول 15 شروع می شود و نحوه مهاجرت از Blobstore (و NDB) به Cloud Storage (و Cloud NDB) را نشان می دهد. فرآیند مهاجرت شامل جایگزینی وابستگی‌ها به سرویس‌های همراه قدیمی App Engine است که به شما امکان می‌دهد در صورت تمایل، برنامه‌های خود را به پلتفرم دیگر بدون سرور Cloud یا پلتفرم میزبانی دیگر منتقل کنید.

این مهاجرت در مقایسه با سایر مهاجرت های این مجموعه کمی تلاش بیشتری می طلبد. Blobstore به چارچوب اصلی برنامه وب وابستگی دارد و به همین دلیل است که برنامه نمونه از چارچوب webapp2 به جای Flask استفاده می کند. این آموزش شامل مهاجرت به Cloud Storage، Cloud NDB، Flask و Python 3 است.

این برنامه همچنان «بازدید» کاربر نهایی را ثبت می‌کند و ده مورد اخیر را نمایش می‌دهد، اما نسخه قبلی (ماژول 15) قابلیت جدیدی را برای استفاده از Blobstore اضافه کرده است: برنامه از کاربران نهایی می‌خواهد که مصنوع (فایلی) را آپلود کنند. "بازدید" آنها کاربران می توانند این کار را انجام دهند یا "پرش" را برای انصراف انتخاب کنند. صرف نظر از تصمیم کاربر، صفحه بعدی همان خروجی نسخه های قبلی این برنامه را ارائه می دهد و آخرین بازدیدها را نمایش می دهد. یک پیچ اضافی این است که بازدیدهایی با مصنوعات مربوطه دارای یک پیوند "نما" برای نمایش مصنوع یک بازدید هستند. این Codelab با حفظ عملکرد توصیف شده، مهاجرت هایی را که قبلا ذکر شد پیاده سازی می کند.

3. راه اندازی/پیش کار

قبل از اینکه به بخش اصلی آموزش برسیم، بیایید پروژه خود را راه‌اندازی کنیم، کد را دریافت کنیم، سپس برنامه پایه را اجرا کنیم تا بدانیم با کد کار شروع کرده‌ایم.

1. پروژه راه اندازی

اگر قبلاً برنامه ماژول 15 را مستقر کرده اید، توصیه می کنیم از همان پروژه (و کد) دوباره استفاده کنید. از طرف دیگر، می توانید یک پروژه کاملاً جدید ایجاد کنید یا از پروژه موجود دیگری استفاده مجدد کنید. مطمئن شوید که پروژه دارای حساب صورتحساب فعال است و App Engine فعال است.

2. برنامه نمونه پایه را دریافت کنید

یکی از پیش نیازهای این نرم افزار کد، داشتن یک برنامه نمونه کار با ماژول 15 است. اگر آن را ندارید، می توانید آن را از پوشه "START" ماژول 15 (لینک زیر) دریافت کنید. این لبه کد شما را در هر مرحله راهنمایی می کند و با کدی که شبیه آنچه در پوشه "FINISH" ماژول 16 است به پایان می رسد.

دایرکتوری فایل های شروع ماژول 15 باید به شکل زیر باشد:

$ ls
README.md       app.yaml        main-gcs.py     main.py         templates

فایل main-gcs.py نسخه جایگزین main.py از ماژول 15 است که امکان انتخاب یک سطل فضای ذخیره‌سازی ابری متفاوت با پیش‌فرض URL اختصاص‌یافته برنامه بر اساس شناسه پروژه را فراهم می‌کند: PROJECT_ID .appspot.com . این فایل هیچ نقشی در این (ماژول 16) نرم افزار کد ندارد مگر اینکه در صورت تمایل می توان تکنیک های مشابهی را برای انتقال به آن فایل اعمال کرد.

3. (دوباره) استقرار برنامه پایه

مراحل پیش‌کار باقی‌مانده برای اجرا اکنون:

  1. دوباره با ابزار خط فرمان gcloud آشنا شوید
  2. برنامه نمونه را با gcloud app deploy مجدداً مستقر کنید
  3. تأیید کنید که برنامه بدون مشکل در App Engine اجرا می شود

هنگامی که آن مراحل را با موفقیت انجام دادید و تأیید کردید که برنامه ماژول 15 کار می کند. صفحه اولیه با فرمی به کاربران خوشامد می‌گوید که از یک فایل مصنوع بازدید برای آپلود همراه با یک گزینه، دکمه «پرش» برای انصراف درخواست می‌کند:

f5b5f9f19d8ae978.png

هنگامی که کاربران یک فایل را آپلود می کنند یا از آن پرش می کنند، برنامه صفحه آشنا "آخرین بازدیدها" را نمایش می دهد:

f5ac6b98ee8a34cb.png

بازدیدهایی که دارای یک مصنوع هستند یک پیوند "مشاهده" در سمت راست مهر زمان بازدید برای نمایش (یا دانلود) مصنوع خواهند داشت. هنگامی که عملکرد برنامه را تأیید کردید، آماده هستید که از سرویس های قدیمی App Engine (webapp2، NDB، Blobstore) به گزینه های جایگزین امروزی (Flask، Cloud NDB، Cloud Storage) مهاجرت کنید.

4. فایل های پیکربندی را به روز کنید

سه فایل پیکربندی برای نسخه به روز شده برنامه ما وارد عمل می شوند. وظایف مورد نیاز عبارتند از:

  1. کتابخانه‌های شخص ثالث داخلی مورد نیاز را در app.yaml به‌روزرسانی کنید و همچنین درب را برای مهاجرت Python 3 باز بگذارید.
  2. یک requirements.txt اضافه کنید، که تمام کتابخانه‌های مورد نیاز را که داخلی نیستند، مشخص می‌کند
  3. appengine_config.py را اضافه کنید تا برنامه از کتابخانه های شخص ثالث داخلی و غیر داخلی پشتیبانی کند

app.yaml

فایل app.yaml خود را با به روز رسانی بخش libraries ویرایش کنید. jinja2 بردارید و grpcio ، setuptools و ssl را اضافه کنید. آخرین نسخه موجود برای هر سه کتابخانه را انتخاب کنید. دستور runtime پایتون 3 را نیز اضافه کنید، اما نظر داده شده است. وقتی کارتان تمام شد، باید به این شکل باشد (اگر پایتون 3.9 را انتخاب کرده باشید):

قبل از:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

بعد از:

#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

تغییرات در درجه اول مربوط به کتابخانه های داخلی پایتون 2 است که در سرورهای App Engine موجود است (بنابراین شما مجبور نیستید آنها را خود بسته بندی کنید). ما Jinja2 را حذف کردیم زیرا با Flask همراه است که می خواهیم آن را به reqs.txt اضافه کنیم. هر زمان که از کتابخانه های سرویس گیرنده Google Cloud، مانند کتابخانه های Cloud NDB و Cloud Storage استفاده می شود، به grpcio و setuptools نیاز است. در نهایت، Cloud Storage خود به کتابخانه ssl نیاز دارد. دستورالعمل زمان اجرا در بالا برای زمانی است که شما آماده پورت کردن این برنامه به پایتون 3 هستید. ما این موضوع را در پایان این آموزش پوشش خواهیم داد.

الزامات. txt

یک فایل requirements.txt اضافه کنید که به چارچوب Flask نیاز دارد و کتابخانه های سرویس گیرنده Cloud NDB و Cloud Storage که هیچ کدام داخلی نیستند. فایل را با این محتوا ایجاد کنید:

flask
google-cloud-ndb
google-cloud-storage

زمان اجرا Python 2 App Engine نیاز به بسته‌بندی کتابخانه‌های شخص ثالث غیر داخلی دارد، بنابراین دستور زیر را برای نصب این کتابخانه‌ها در پوشه lib اجرا کنید:

pip install -t lib -r requirements.txt

اگر هم پایتون 2 و هم 3 را روی دستگاه توسعه خود دارید، ممکن است مجبور شوید از دستور pip2 برای اطمینان از دریافت نسخه های Python 2 این کتابخانه ها استفاده کنید. پس از ارتقاء به پایتون 3، دیگر نیازی به بسته‌بندی خودکار ندارید.

appengine_config.py

یک فایل appengine_config.py اضافه کنید که از کتابخانه های شخص ثالث داخلی و غیر داخلی پشتیبانی می کند. فایل را با این محتوا ایجاد کنید:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

مراحلی که به تازگی تکمیل شده اند باید مشابه یا مشابه مراحل فهرست شده در بخش نصب کتابخانه ها برای برنامه های پایتون 2 در اسناد App Engine باشند، و به طور خاص، محتویات appengine_config.py باید با آنچه در مرحله 5 وجود دارد مطابقت داشته باشد.

کار روی فایل‌های پیکربندی کامل شده است، بنابراین بیایید به سمت برنامه حرکت کنیم.

5. فایل های برنامه را تغییر دهید

واردات

اولین مجموعه تغییرات برای main.py شامل تعویض همه چیزهایی است که جایگزین می شوند. این چیزی است که در حال تغییر است:

  1. webapp2 با Flask جایگزین شده است
  2. به جای استفاده از Jinja2 از webapp2_extras ، از Jinja2 همراه با Flask استفاده کنید
  3. App Engine Blobstore و NDB با Cloud NDB و Cloud Storage جایگزین شدند
  4. کنترل کننده های Blobstore در webapp با ترکیبی از ماژول کتابخانه استاندارد io ، Flask و ابزارهای werkzeug جایگزین شده اند.
  5. به‌طور پیش‌فرض، Blobstore در یک سطل فضای ذخیره‌سازی ابری با نام URL برنامه شما ( PROJECT_ID.appspot.com ) می‌نویسد. از آنجایی که ما در حال انتقال به کتابخانه سرویس گیرنده Cloud Storage هستیم، google.auth برای دریافت شناسه پروژه برای تعیین نام دقیق سطل استفاده می شود. (می توانید نام سطل را تغییر دهید زیرا دیگر کدگذاری نشده است.)

قبل از:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

با جایگزین کردن بخش واردات فعلی در main.py با قطعه کد زیر، تغییرات را در لیست بالا اعمال کنید.

بعد از:

import io

from flask import (Flask, abort, redirect, render_template,
        request, send_file, url_for)
from werkzeug.utils import secure_filename

import google.auth
from google.cloud import exceptions, ndb, storage

مقداردهی اولیه و پشتیبانی غیر ضروری Jinja2

بلوک بعدی کدی که باید جایگزین شود BaseHandler است که استفاده از Jinja2 را از webapp2_extras مشخص می کند. این غیرضروری است زیرا Jinja2 با Flask همراه است و موتور قالب پیش فرض آن است، بنابراین آن را حذف کنید.

در سمت ماژول 16، اشیایی را که در برنامه قدیمی‌تر نداشتیم، نمونه برداری کنید. این شامل مقداردهی اولیه برنامه Flask و ایجاد کلاینت های API برای Cloud NDB و Cloud Storage است. در نهایت، نام سطل Cloud Storage را همانطور که در بالا در بخش واردات توضیح داده شد، قرار دادیم. در اینجا قبل و بعد از اجرای این به روز رسانی ها آمده است:

قبل از:

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))

بعد از:

app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID

دسترسی به Datastore را به روز کنید

Cloud NDB بیشتر با App Engine NDB سازگار است. یکی از تفاوت هایی که قبلاً پوشش داده شده است، نیاز به مشتری API است. مورد دوم این است که دسترسی به Datastore توسط مدیر زمینه Python کلاینت API کنترل شود. اساساً، این بدان معناست که همه تماس‌های دسترسی به Datastore با استفاده از کتابخانه سرویس گیرنده Cloud NDB فقط می‌توانند در پایتون with بلوک‌ها انجام شوند.

این یک تغییر است. مورد دیگر این است که Blobstore و اشیاء آن، به عنوان مثال، BlobKey s، توسط Cloud Storage پشتیبانی نمی شوند، بنابراین file_blob به یک ndb.StringProperty تغییر دهید. در زیر کلاس مدل داده و توابع به روز شده store_visit() و fetch_visits() که این تغییرات را منعکس می کنند، آمده است:

قبل از:

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)

بعد از:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.StringProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

در اینجا یک نمایش تصویری از تغییراتی است که تاکنون ایجاد شده است:

a8f74ca392275822.png

به روز رسانی کنترل کننده ها

کنترل کننده آپلود

هندلرها در webapp2 کلاس هستند در حالی که توابع در Flask هستند. به جای روش فعل HTTP، Flask از فعل برای تزئین تابع استفاده می کند. Blobstore و کنترل‌کننده‌های webapp آن با قابلیت‌های Cloud Storage و همچنین Flask و ابزارهای آن جایگزین شده‌اند:

قبل از:

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)

بعد از:

@app.route('/upload', methods=['POST'])
def upload():
    'Upload blob (POST) handler'
    fname = None
    upload = request.files.get('file', None)
    if upload:
        fname = secure_filename(upload.filename)
        blob = gcs_client.bucket(BUCKET).blob(fname)
        blob.upload_from_file(upload, content_type=upload.content_type)
    store_visit(request.remote_addr, request.user_agent, fname)
    return redirect(url_for('root'), code=307)

چند نکته در رابطه با این به روز رسانی:

  • به جای blob_id ، مصنوعات فایل اکنون با نام فایل ( fname ) در صورت وجود شناسایی می شوند و در غیر این صورت None (کاربر از آپلود فایل منصرف شد).
  • کنترل‌کننده‌های Blobstore فرآیند آپلود را از کاربران خود انتزاع می‌کنند، اما Cloud Storage این کار را نمی‌کند، بنابراین می‌توانید کد جدید اضافه‌شده را ببینید که شی blob و مکان فایل (سطل) و همچنین تماسی را که آپلود واقعی را انجام می‌دهد را تنظیم می‌کند. ( upload_from_file() ).
  • webapp2 از یک جدول مسیریابی در پایین فایل برنامه استفاده می کند در حالی که مسیرهای Flask در هر کنترل کننده تزئین شده یافت می شود.
  • هر دو کنترل کننده عملکرد خود را با هدایت به خانه ( / ) جمع بندی می کنند و در عین حال درخواست POST را با یک کد بازگشتی HTTP 307 حفظ می کنند.

کنترل کننده دانلود

به روز رسانی کنترل کننده دانلود از یک الگوی مشابه با کنترل کننده آپلود پیروی می کند، فقط کد بسیار کمتری برای مشاهده وجود دارد. عملکرد Blobstore و webapp را با Cloud Storage و Flask جایگزین کنید:

قبل از:

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)

بعد از:

@app.route('/view/<path:fname>')
def view(fname):
    'view uploaded blob (GET) handler'
    blob = gcs_client.bucket(BUCKET).blob(fname)
    try:
        media = blob.download_as_bytes()
    except exceptions.NotFound:
        abort(404)
    return send_file(io.BytesIO(media), mimetype=blob.content_type)

نکات مربوط به این به روز رسانی:

  • مجدداً، Flask توابع کنترلر را با مسیر خود تزئین می کند در حالی که webapp این کار را در جدول مسیریابی در پایین انجام می دهد، بنابراین الگوی دستوری مطابق الگوی ('/view/([^/]+)?' ) در مقابل Flask's ( '/view/<path:fname>' ) را بشناسید. '/view/<path:fname>' ).
  • مانند کنترل کننده آپلود، برای عملکردی که توسط کنترل کننده های Blobstore انتزاع شده است، کمی کار بیشتری در سمت ذخیره سازی ابری لازم است، یعنی شناسایی فایل (blob) مورد نظر و دانلود صریح متد send_blob() باینری در مقابل کنترل کننده Blobstore. تماس بگیرید.
  • در هر دو مورد، اگر مصنوع پیدا نشد، یک خطای HTTP 404 به کاربر برگردانده می‌شود.

کنترل کننده اصلی

تغییرات نهایی در برنامه اصلی در کنترل کننده اصلی انجام می شود. متدهای فعل webapp2 HTTP با یک تابع واحد که عملکرد آنها را ترکیب می کند جایگزین می شود. کلاس MainHandler را با تابع root() جایگزین کنید و جدول مسیریابی webapp2 را مطابق شکل زیر حذف کنید:

قبل از:

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)

بعد از:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

به جای جدا کردن متدهای get() و post() ، آنها اساساً یک عبارت if-else در root() هستند. همچنین، از آنجایی که root() یک تابع واحد است، تنها یک فراخوانی برای ارائه الگو برای GET و POST وجود دارد، در حالی که واقعاً در webapp2 این امکان وجود ندارد.

در اینجا یک نمایش تصویری از دومین و آخرین مجموعه تغییرات به main.py است:

5ec38818c32fec2.png

(اختیاری) "افزایش" سازگاری با عقب

بنابراین راه حل ایجاد شده در بالا کاملاً کار می کند ... اما فقط در صورتی که از ابتدا شروع کنید و فایل های ایجاد شده توسط Blobstore را ندارید. از آنجایی که ما برنامه را به‌روزرسانی کردیم تا فایل‌ها را به‌جای BlobKey با نام فایل شناسایی کنیم، برنامه تکمیل‌شده ماژول 16 آنطور که هست نمی‌تواند فایل‌های Blobstore را مشاهده کند. به عبارت دیگر، ما با انجام این مهاجرت یک تغییر ناسازگار با عقب را ایجاد کردیم. ما اکنون یک نسخه جایگزین از main.py به نام main-migrate.py (موجود در مخزن) ارائه می کنیم که تلاش می کند این شکاف را پر کند.

اولین "افزونه" برای پشتیبانی از فایل‌های ایجاد شده توسط Blobstore، یک مدل داده است که دارای یک BlobKeyProperty (علاوه بر StringProperty برای فایل‌های ایجاد شده در فضای ابری) است:

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()  # backwards-compatibility
    file_gcs  = ndb.StringProperty()

ویژگی file_blob برای شناسایی فایل‌های ایجاد شده توسط Blobstore استفاده می‌شود در حالی که file_gcs برای فایل‌های Cloud Storage است. اکنون هنگام ایجاد بازدیدهای جدید، به‌صراحت یک مقدار را به جای file_gcs file_blob کنید، بنابراین store_visit کمی متفاوت به نظر می‌رسد:

قبل از:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

بعد از:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_gcs=upload_key).put()

هنگام واکشی آخرین بازدیدها، داده ها را قبل از ارسال به الگو "عادی" کنید:

قبل از:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

بعد از:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = etl_visits(fetch_visits(10))
    return render_template('index.html', **context)

سپس وجود file_blob یا file_gcs (یا هیچکدام) را تایید کنید. اگر فایلی در دسترس است، فایل موجود را انتخاب کنید و از آن شناسه استفاده کنید ( BlobKey برای فایل‌های ایجاد شده توسط Blobstore یا نام فایل برای فایل‌های ایجاد شده توسط Cloud Storage). وقتی می‌گوییم «فایل‌های ایجاد شده در فضای ذخیره‌سازی ابری»، منظور فایل‌هایی است که با استفاده از کتابخانه سرویس گیرنده فضای ذخیره‌سازی ابری ایجاد شده‌اند. Blobstore همچنین به Cloud Storage نیز می نویسد، اما در این مورد، آن ها فایل های ایجاد شده توسط Blobstore هستند.

اکنون مهمتر از آن، این تابع etl_visits() چیست که برای عادی سازی یا ETL (استخراج، تبدیل و بارگذاری) داده ها برای کاربر نهایی استفاده می شود؟ به نظر می رسد این است:

def etl_visits(visits):
    return [{
            'visitor': v.visitor,
            'timestamp': v.timestamp,
            'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
                    and v.file_gcs else v.file_blob
            } for v in visits]

احتمالاً شبیه چیزی است که انتظار داشتید: کد در تمام بازدیدها حلقه می زند، و برای هر بازدید، داده های بازدیدکننده و مهر زمانی را به کلمه کلمه می گیرد، سپس بررسی می کند که آیا file_gcs یا file_blob وجود دارد یا خیر، و اگر چنین است، یکی از آنها را انتخاب می کند (یا اگر None ) وجود ندارد).

در اینجا تصویری از تفاوت های main.py و main-migrate.py آمده است:

718b05b2adadb2e1.png

اگر بدون فایل‌های ایجاد شده توسط Blobstore از ابتدا شروع می‌کنید، از main.py استفاده کنید، اما اگر می‌خواهید فایل‌های پشتیبانی ایجاد شده توسط Blobstore و Cloud Storage را تغییر دهید، main-migrate.py را به‌عنوان نمونه‌ای از نحوه برخورد بررسی کنید. با سناریویی مانند کمک به برنامه ریزی مهاجرت برای برنامه های خود. هنگام انجام مهاجرت‌های پیچیده، موارد خاصی احتمالاً به وجود می‌آیند، بنابراین این مثال برای نشان دادن تمایل بیشتری به مدرن‌سازی اپلیکیشن‌های واقعی با داده‌های واقعی است.

6. خلاصه/پاکسازی

این بخش با استقرار برنامه، این کد را جمع‌بندی می‌کند و تأیید می‌کند که آن‌طور که در نظر گرفته شده و در هر خروجی منعکس‌شده کار می‌کند. پس از تأیید اعتبار برنامه، مراحل پاکسازی را انجام دهید و مراحل بعدی را در نظر بگیرید.

استقرار و تأیید برنامه

قبل از استقرار مجدد برنامه خود، مطمئن شوید که pip install -t lib -r requirements.txt اجرا کنید تا کتابخانه های شخص ثالث خود همراه را در پوشه lib دریافت کنید. اگر می خواهید راه حل سازگار با عقب را اجرا کنید، ابتدا نام main-migrate.py را به main.py تغییر دهید. اکنون gcloud app deploy اجرا کنید و تأیید کنید که برنامه همانند برنامه Module 15 کار می کند. صفحه فرم به شکل زیر است:

f5b5f9f19d8ae978.png

آخرین صفحه بازدیدها به این صورت است:

f5ac6b98ee8a34cb.png

بابت تکمیل این کد لبه جایگزین App Engine Blobstore با Cloud Storage، App Engine NDB با Cloud NDB، و webapp2 با Flask را به شما تبریک می‌گوییم. اکنون کد شما باید با آنچه در پوشه FINISH (ماژول 16) است مطابقت داشته باشد. جایگزین main-migrate.py نیز در آن پوشه وجود دارد.

"مهاجرت" پایتون 3

دستورالعمل runtime پایتون 3 در بالای app.yaml تمام چیزی است که برای پورت کردن این برنامه به پایتون 3 لازم است. کد منبع خود از قبل با پایتون 3 سازگار است، بنابراین هیچ تغییری در آنجا لازم نیست. برای استقرار این برنامه به عنوان یک برنامه پایتون 3، مراحل زیر را اجرا کنید:

  1. دستور runtime پایتون 3 را در بالای app.yaml لغو نظر کنید.
  2. تمام خطوط دیگر را در app.yaml حذف کنید.
  3. فایل appengine_config.py حذف کنید. (استفاده نشده در زمان اجرا پایتون 3)
  4. در صورت وجود پوشه lib حذف کنید. (غیر ضروری در زمان اجرای پایتون 3)

پاک کن

ژنرال

اگر فعلاً کارتان تمام شده است، توصیه می‌کنیم برنامه App Engine خود را غیرفعال کنید تا از پرداخت صورت‌حساب جلوگیری کنید. با این حال، اگر می‌خواهید بیشتر آزمایش یا آزمایش کنید، پلتفرم App Engine یک سهمیه رایگان دارد، و تا زمانی که از آن سطح استفاده تجاوز نکنید، هزینه‌ای از شما دریافت نمی‌شود. این برای محاسبه است، اما ممکن است هزینه‌هایی برای خدمات App Engine مربوطه نیز وجود داشته باشد، بنابراین صفحه قیمت آن را برای اطلاعات بیشتر بررسی کنید. اگر این انتقال شامل سایر سرویس‌های Cloud باشد، آن‌ها جداگانه صورت‌حساب می‌شوند. در هر صورت، در صورت وجود، بخش «ویژه این کد آزمایشگاه» را در زیر ببینید.

برای افشای کامل، استقرار در یک پلت فرم محاسباتی بدون سرور 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 * شما بستگی دارد، به عنوان مثال، اگر برنامه شما در ایالات متحده میزبانی می شود، " us ".

از سوی دیگر، اگر نمی‌خواهید با این برنامه یا دیگر کدهای مهاجرت مرتبط ادامه دهید و می‌خواهید همه چیز را به طور کامل حذف کنید، پروژه خود را خاموش کنید .

مخصوص این کد لبه

خدمات لیست شده در زیر منحصر به این کدلب است. برای اطلاعات بیشتر به مستندات هر محصول مراجعه کنید:

توجه داشته باشید که اگر از ماژول 15 به ماژول 16 مهاجرت کرده اید، همچنان در Blobstore داده خواهید داشت، بنابراین ما اطلاعات قیمت گذاری آن را در بالا اضافه می کنیم.

مراحل بعدی

فراتر از این آموزش، ماژول‌های مهاجرت دیگری که بر دور شدن از سرویس‌های همراه قدیمی تمرکز دارند عبارتند از:

App Engine دیگر تنها پلتفرم بدون سرور در Google Cloud نیست. اگر یک برنامه App Engine کوچک یا برنامه‌ای دارید که عملکرد محدودی دارد و می‌خواهید آن را به یک میکروسرویس مستقل تبدیل کنید، یا می‌خواهید یک برنامه یکپارچه را به چندین مؤلفه قابل استفاده مجدد تقسیم کنید، اینها دلایل خوبی برای فکر رفتن به Cloud Functions هستند. اگر کانتینری‌سازی بخشی از گردش کار توسعه برنامه شما شده است، به‌ویژه اگر شامل یک خط لوله CI/CD (ادغام پیوسته/تحویل مداوم یا استقرار) باشد، مهاجرت به Cloud Run را در نظر بگیرید. این سناریوها توسط ماژول های زیر پوشش داده می شوند:

  • مهاجرت از App Engine به Cloud Functions: به ماژول 11 مراجعه کنید
  • مهاجرت از App Engine به Cloud Run: به ماژول 4 مراجعه کنید تا برنامه خود را با Docker محفظه کنید، یا ماژول 5 را بدون کانتینر، دانش Docker یا Dockerfile s انجام دهید.

جابجایی به یک پلتفرم بدون سرور دیگر اختیاری است، و توصیه می‌کنیم قبل از هر گونه تغییر، بهترین گزینه‌ها را برای برنامه‌ها و موارد استفاده خود در نظر بگیرید.

صرف نظر از اینکه کدام ماژول مهاجرت را بعدی در نظر می گیرید، تمام محتوای ایستگاه مهاجرت بدون سرور (مجموعه کدها، ویدیوها، کد منبع [در صورت وجود]) را می توان در مخزن منبع باز آن دسترسی داشت. README مخزن همچنین راهنمایی هایی را ارائه می دهد که کدام مهاجرت ها باید در نظر گرفته شود و هر "ترتیب" مربوط به ماژول های مهاجرت.

7. منابع اضافی

مسائل/بازخوردهای Codelab

اگر مشکلی در این کد لبه پیدا کردید، لطفاً قبل از تشکیل پرونده ابتدا مشکل خود را جستجو کنید. پیوندهایی برای جستجو و ایجاد مسائل جدید:

منابع مهاجرت

پیوندهای پوشه‌های مخزن برای ماژول 15 (START) و ماژول 16 (FINISH) را می‌توانید در جدول زیر بیابید. همچنین می‌توانید از مخزن برای همه انتقال‌های نرم‌افزار App Engine که می‌توانید یک فایل ZIP را شبیه‌سازی یا دانلود کنید، دسترسی پیدا کنید.

Codelab

پایتون 2

پایتون 3

ماژول 15

کد

N/A

ماژول 16 (این آزمایشگاه کد)

کد

(همان پایتون 2)

منابع آنلاین

در زیر منابع آنلاینی وجود دارد که ممکن است برای این آموزش مرتبط باشد:

موتور برنامه Blobstore و Cloud Storage

پلت فرم App Engine

سایر اطلاعات Cloud

پایتون

ویدئوها

مجوز

این اثر تحت مجوز Creative Commons Attribution 2.0 Generic مجوز دارد.