مهاجرت یک موتور برنامه پایتون 2 Cloud NDB & برنامه Cloud Tasks به Python 3 و Cloud Datastore (ماژول 9)

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

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

هدف از این کد لبه پورت کردن برنامه نمونه ماژول 8 به پایتون 3 و همچنین تغییر دسترسی Datastore (Cloud Firestore در حالت Datastore) از استفاده از Cloud NDB به کتابخانه کلاینت اصلی Cloud Datastore و ارتقاء به آخرین نسخه Cloud Tasks است. کتابخانه مشتری

ما استفاده از Task Queue را برای وظایف فشاری در ماژول 7 اضافه کردیم، سپس آن استفاده را به وظایف Cloud در ماژول 8 منتقل کردیم. در اینجا در ماژول 9، ما به پایتون 3 و Cloud Datastore ادامه می دهیم. کسانی که از Task Queues برای کارهای کششی استفاده می کنند به Cloud Pub/Sub مهاجرت می کنند و به جای آن باید به ماژول های 18-19 مراجعه کنند.

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

  • برنامه نمونه ماژول 8 را به پایتون 3 پورت کنید
  • دسترسی به Datastore را از Cloud NDB به کتابخانه های سرویس گیرنده Cloud Datastore تغییر دهید
  • به آخرین نسخه کتابخانه سرویس گیرنده Cloud Tasks ارتقا دهید

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

نظرسنجی

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

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

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

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

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

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

2. پس زمینه

ماژول 7 نحوه استفاده از App Engine Task Queue push tasks در برنامه های Python 2 Flask App Engine را نشان می دهد. در ماژول 8 ، آن برنامه را از Task Queue به Cloud Tasks منتقل می کنید. در اینجا در ماژول 9 ، آن سفر را ادامه می دهید و آن برنامه را به پایتون 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 استفاده می‌کنند و می‌خواهید پایگاه کد خود را برای دسترسی به Datastore تنها با یک کتابخانه کلاینت ادغام کنید. Cloud NDB به طور خاص برای توسعه دهندگان Python 2 App Engine به عنوان ابزار مهاجرت Python 3 ایجاد شده است، بنابراین اگر قبلاً کدی با استفاده از کتابخانه سرویس گیرنده Cloud Datastore ندارید، نیازی به در نظر گرفتن این مهاجرت ندارید.

در نهایت، توسعه کتابخانه سرویس گیرنده Cloud Tasks فقط در پایتون 3 ادامه دارد، بنابراین ما در حال "مهاجرت" از یکی از نسخه های نهایی پایتون 2 به پایتون 3 معاصر آن هستیم. خوشبختانه، هیچ تغییری در پایتون 2 وجود ندارد، به این معنی که هیچ چیز دیگری لازم نیست در اینجا انجام دهید.

این آموزش شامل مراحل زیر است:

  1. راه اندازی/پیش کار
  2. پیکربندی را به روز کنید
  3. کد برنامه را تغییر دهید

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

این بخش توضیح می دهد که چگونه:

  1. پروژه Cloud خود را راه اندازی کنید
  2. دریافت نمونه برنامه پایه
  3. (دوباره) استقرار و تأیید اعتبار برنامه پایه

این مراحل تضمین می‌کند که شما با کد کار شروع کرده‌اید و برای انتقال به سرویس‌های Cloud آماده است.

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

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

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

یکی از پیش نیازها یک برنامه موتور اپلیکیشن ماژول 8 است: ماژول 8 را تکمیل کنید (توصیه می شود) یا برنامه ماژول 8 را از مخزن کپی کنید. چه از ما استفاده کنید چه از کد ما، کد ماژول 8 جایی است که ما شروع می کنیم ("START"). این لبه کد شما را در مسیر مهاجرت راهنمایی می کند و با کدی که شبیه آنچه در پوشه مخزن ماژول 9 است ("FINISH") به پایان می رسد.

صرف نظر از اینکه از کدام برنامه ماژول 7 استفاده می کنید، پوشه باید مانند زیر باشد، احتمالاً با یک پوشه lib نیز:

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

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

مراحل زیر را برای استقرار برنامه Module 8 انجام دهید:

  1. در صورت وجود پوشه lib حذف کنید و pip install -t lib -r requirements.txt اجرا کنید تا lib دوباره پر شود. اگر پایتون 2 و 3 را روی دستگاه توسعه خود نصب کرده اید، ممکن است به جای آن نیاز به استفاده از pip2 داشته باشید.
  2. مطمئن شوید که ابزار خط فرمان gcloud را نصب و راه اندازی کرده اید و استفاده از آن را بررسی کرده اید.
  3. (اختیاری) اگر نمی‌خواهید PROJECT_ID با هر دستور gcloud که صادر می‌کنید، پروژه Cloud خود را با gcloud config set project PROJECT_ID تنظیم کنید.
  4. برنامه نمونه را با gcloud app deploy اجرا کنید
  5. تأیید کنید که برنامه همانطور که انتظار می رود بدون مشکل اجرا شود. اگر Lab کد ماژول 8 را تکمیل کرده باشید، برنامه بازدیدکنندگان برتر را به همراه آخرین بازدیدها نمایش می دهد (در زیر نشان داده شده است). در پایین نشانی از کارهای قدیمی است که حذف خواهند شد.

4aa8a2cb5f527079.png

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

الزامات. 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 را حذف کرد.

به روز رسانی دیگر این است که زمان اجرا پایتون 3 نیاز به استفاده از چارچوب های وب دارد که مسیریابی خود را انجام می دهند. در نتیجه، همه کنترل‌کننده‌های اسکریپت باید به auto تغییر کنند. با این حال، از آنجایی که همه مسیرها باید به auto تغییر کنند، و هیچ فایل ثابتی از این برنامه نمونه ارائه نمی‌شود، داشتن هیچ کنترل‌کننده‌ای مهم نیست، بنابراین کل بخش handlers را نیز حذف کنید.

تنها چیزی که در app.yaml مورد نیاز است تنظیم زمان اجرا بر روی یک نسخه پشتیبانی شده از پایتون 3، مثلاً 3.10 است. این تغییر را انجام دهید تا app.yaml جدید و به اختصار فقط این خط باشد:

runtime: python310

appengine_config.py و lib را حذف کنید

نسل بعدی برنامه App Engine استفاده از بسته شخص ثالث را اصلاح می کند:

  • کتابخانه‌های داخلی آنهایی هستند که توسط Google بررسی شده و در سرورهای App Engine در دسترس قرار گرفته‌اند، احتمالاً به این دلیل که حاوی کد C/C++ هستند که توسعه‌دهندگان مجاز به استقرار در فضای ابری نیستند—این‌ها دیگر در زمان‌های اجرا نسل دوم در دسترس نیستند.
  • کپی کردن کتابخانه‌های داخلی (که گاهی اوقات «فروشنده» یا «خود بسته‌بندی» نامیده می‌شود) دیگر در زمان‌های اجرا نسل دوم مورد نیاز نیست. در عوض، آنها باید در requirements.txt فهرست شوند، جایی که سیستم ساخت به طور خودکار آنها را از طرف شما در زمان استقرار نصب می کند.

در نتیجه این تغییرات در مدیریت بسته شخص ثالث، نه فایل appengine_config.py و نه پوشه lib مورد نیاز نیست، بنابراین آنها را حذف کنید. در زمان‌های اجرا نسل دوم، App Engine به‌طور خودکار بسته‌های شخص ثالث فهرست‌شده در requirements.txt را نصب می‌کند. جمع بندی:

  1. بدون کتابخانه شخص ثالث خود همراه یا کپی شده. آنها را در requirements.txt فهرست کنید
  2. بدون pip install در پوشه lib ، به این معنی که دوره پوشه lib وجود ندارد
  3. هیچ فهرستی از کتابخانه های شخص ثالث داخلی (بنابراین بدون بخش libraries ) در app.yaml . آنها را در requirements.txt فهرست کنید
  4. هیچ کتابخانه شخص ثالثی برای ارجاع از برنامه شما به معنای عدم وجود فایل appengine_config.py است

فهرست کردن تمام کتابخانه های شخص ثالث مورد نظر در requirements.txt تنها مورد نیاز توسعه دهنده است.

5. فایل های برنامه را به روز کنید

تنها یک فایل برنامه وجود دارد، main.py ، بنابراین تمام تغییرات این بخش فقط روی آن فایل تأثیر می گذارد. در زیر یک تصویر "تفاوت" در مورد تغییرات کلی وجود دارد که باید برای تغییر کد موجود در برنامه جدید ایجاد شود. از خوانندگان انتظار نمی رود که کد را خط به خط بخوانند، زیرا هدف آن این است که به سادگی یک نمای کلی تصویری از آنچه در این Refactor مورد نیاز است به دست آورید (اما در صورت تمایل می توانید در یک برگه جدید باز کنید یا دانلود کنید و بزرگنمایی کنید).

5d043768ba7be742.png

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

بخش واردات در 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()

گزارش‌گیری در زمان‌های اجرای نسل دوم مانند پایتون 3 ساده‌تر و بهبود یافته است:

  • برای تجربه ثبت جامع، از Cloud Logging استفاده کنید
  • برای ورود ساده، فقط از طریق print() به stdout (یا stderr ) ارسال کنید.
  • نیازی به استفاده از ماژول logging پایتون نیست (پس آن را حذف کنید)

به این ترتیب، وارد کردن logging را حذف کنید و google.cloud.ndb را با google.cloud.datastore تعویض کنید. به طور مشابه، ds_client را تغییر دهید تا به جای یک کلاینت NDB به یک سرویس گیرنده Datastore اشاره کند. با این تغییرات ایجاد شده، قسمت بالای برنامه جدید شما اکنون به شکل زیر است:

بعد از:

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

تغییرات اولیه:

  1. پرس و جوی Cloud NDB را با معادل Cloud Datastore تعویض کنید. سبک های پرس و جو کمی متفاوت است.
  2. Datastore نیازی به استفاده از یک مدیر زمینه ندارد و شما را مجبور نمی کند مانند Cloud NDB داده های آن را (با to_dict() ) استخراج کنید.
  3. جایگزینی تماس های ثبت با 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

این به طور معمول تمام چیزی است که لازم است. متاسفانه یک مشکل اساسی وجود دارد.

(احتمالا) یک صف (فشار) جدید ایجاد کنید

در ماژول 7، استفاده از taskqueue App Engine را به برنامه ماژول 1 موجود اضافه کردیم. یکی از مزایای کلیدی داشتن وظایف فشار به عنوان یک ویژگی قدیمی App Engine این است که یک صف "پیش فرض" به طور خودکار ایجاد می شود. زمانی که آن برنامه به Cloud Tasks در ماژول 8 منتقل شد، آن صف پیش‌فرض از قبل وجود داشت، بنابراین ما هنوز نیازی به نگرانی در مورد آن نداشتیم. اینجا در ماژول 9 تغییر می کند.

یکی از جنبه‌های مهمی که باید در نظر گرفت این است که برنامه جدید App Engine دیگر از خدمات App Engine استفاده نمی‌کند و به این ترتیب، دیگر نمی‌توانید فرض کنید که App Engine به طور خودکار یک صف کار را در یک محصول دیگر (وظایف ابری) ایجاد می‌کند. همانطور که نوشته شده است، ایجاد یک کار در 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

تابع Cloud Tasks create_queue() به نام مسیر کامل صف به جز نام صف نیاز دارد. برای سادگی، متغیر دیگری 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 عمدتاً از ماژول 8 دست نخورده است. آخرین قطعه کدی که باید به آن نگاه کنید، کنترل کننده وظایف است.

به روز رسانی (فشار) کنترل کننده کار

در Task handler، trim() ، کد NDB Cloud برای بازدیدهای قدیمی‌تر از قدیمی‌ترین مورد نمایش داده شده درخواست می‌کند. از یک پرس و جو فقط کلید برای سرعت بخشیدن به کارها استفاده می کند - اگر فقط به شناسه های بازدید نیاز دارید، چرا همه داده ها را واکشی کنید؟ هنگامی که همه شناسه‌های بازدید را دارید، همه آنها را به صورت دسته‌ای با تابع 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

هیچ تغییری در root() handler برنامه اصلی وجود ندارد.

پورت به پایتون 3

این برنامه نمونه برای اجرا در پایتون 2 و 3 طراحی شده است. هر گونه تغییر اختصاصی پایتون 3 قبلاً در بخش های مربوطه این آموزش پوشش داده شده است. هیچ مرحله اضافی و کتابخانه های سازگاری مورد نیاز نیست.

به روز رسانی Cloud Tasks

نسخه نهایی کتابخانه سرویس گیرنده Cloud Tasks که از Python 2 پشتیبانی می کند 1.5.0 است. در زمان نگارش این مقاله، آخرین نسخه کتابخانه کلاینت برای پایتون 3 کاملاً با آن نسخه سازگار است، بنابراین نیازی به به روز رسانی بیشتر نیست.

به روز رسانی قالب HTML

در فایل قالب HTML، templates/index.html نیز نیازی به تغییر نیست، بنابراین این همه تغییرات لازم برای رسیدن به برنامه ماژول 9 را تکمیل می کند.

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

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

پس از تکمیل به‌روزرسانی‌های کد، عمدتاً پورت پایتون 3، برنامه خود را با gcloud app deploy اجرا کنید. خروجی باید با برنامه های ماژول های 7 و 8 برنامه یکسان باشد به جز اینکه دسترسی پایگاه داده را به کتابخانه سرویس گیرنده Cloud Datastore منتقل کرده اید و به Python 3 ارتقا داده اید:

ماژول 7 برنامه visitme

این مرحله Codelab را کامل می کند. ما از شما دعوت می کنیم کد خود را با آنچه در پوشه ماژول 9 است مقایسه کنید. تبریک می گویم!

تمیز کردن

ژنرال

اگر فعلاً کارتان تمام شده است، توصیه می‌کنیم برنامه 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 ".

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

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

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

  • Cloud Tasks دارای یک لایه رایگان است. برای جزئیات بیشتر به صفحه قیمت آن مراجعه کنید.
  • سرویس App Engine Datastore توسط Cloud Datastore (Cloud Firestore در حالت Datastore) ارائه می شود که دارای یک ردیف رایگان نیز می باشد. برای اطلاعات بیشتر به صفحه قیمت آن مراجعه کنید.

مراحل بعدی

با این کار، انتقال ما از وظایف فشاری App Engine Task Queue به Cloud Tasks به پایان می رسد. انتقال اختیاری از Cloud NDB به Cloud Datastore نیز به تنهایی (بدون Task Queue یا Cloud Tasks) در ماژول 3 پوشش داده شده است. علاوه بر ماژول 3، ماژول‌های مهاجرت دیگری نیز وجود دارد که بر دور شدن از سرویس‌های همراه قدیمی App Engine تمرکز می‌کنند، عبارتند از:

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. منابع اضافی

مسائل/بازخورد Codelabs

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

منابع مهاجرت

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

Codelab

پایتون 2

پایتون 3

ماژول 8

کد

(n/a)

ماژول 9

(n/a)

کد

منابع آنلاین

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

موتور برنامه

Cloud NDB

Cloud Datastore

وظایف ابری

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

مجوز

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