۱. مرور کلی
مجموعه آزمایشگاههای کد Serverless Migration Station (آموزشهای عملی و خودآموز) و ویدیوهای مرتبط با آن ، با هدف کمک به توسعهدهندگان Google Cloud serverless برای مدرنسازی برنامههایشان، با راهنمایی آنها در طول یک یا چند مهاجرت، و در درجه اول دور شدن از سرویسهای قدیمی، ارائه میشوند. انجام این کار، برنامههای شما را قابل حملتر میکند و گزینهها و انعطافپذیری بیشتری به شما میدهد و شما را قادر میسازد تا با طیف وسیعتری از محصولات Cloud ادغام شده و به آنها دسترسی داشته باشید و به راحتی به نسخههای جدیدتر زبان ارتقا دهید. در حالی که در ابتدا بر روی اولین کاربران Cloud، در درجه اول توسعهدهندگان App Engine (محیط استاندارد)، تمرکز دارد، این مجموعه به اندازه کافی گسترده است که شامل سایر پلتفرمهای serverless مانند Cloud Functions و Cloud Run یا در صورت لزوم، هر جای دیگری نیز میشود.
هدف از این آزمایشگاه کد، انتقال برنامه نمونه ماژول ۸ به پایتون ۳ و همچنین تغییر دسترسی Datastore (Cloud Firestore در حالت Datastore) از استفاده از Cloud NDB به کتابخانه کلاینت Cloud Datastore بومی و ارتقاء به آخرین نسخه کتابخانه کلاینت Cloud Tasks است.
ما استفاده از صف وظایف (Task Queue) را برای وظایف push در ماژول ۷ اضافه کردیم، سپس این کاربرد را در ماژول ۸ به Cloud Tasks منتقل کردیم. در ماژول ۹، به پایتون ۳ و Cloud Datastore ادامه میدهیم. کسانی که از صفهای وظایف (Task Queues) برای وظایف pull استفاده میکنند، به Cloud Pub/Sub مهاجرت میکنند و باید به ماژولهای ۱۸-۱۹ مراجعه کنند.
یاد خواهید گرفت که چگونه
- انتقال برنامه نمونه ماژول ۸ به پایتون ۳
- دسترسی به Datastore را از Cloud NDB به کتابخانههای کلاینت Cloud Datastore تغییر دهید
- به آخرین نسخه کتابخانه کلاینت Cloud Tasks ارتقا دهید
آنچه نیاز دارید
- یک پروژه پلتفرم ابری گوگل با یک حساب پرداخت فعال GCP
- مهارتهای پایه پایتون
- آشنایی کامل با دستورات رایج لینوکس
- دانش پایه در توسعه و استقرار برنامههای App Engine
- یک برنامهی ماژول ۸ App Engine که کار میکند: کد آزمایشگاه ماژول ۸ (توصیه میشود) را تکمیل کنید یا برنامهی ماژول ۸ را از مخزن کپی کنید
نظرسنجی
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را با پایتون چگونه ارزیابی میکنید؟
تجربه خود را در استفاده از خدمات ابری گوگل چگونه ارزیابی میکنید؟
۲. پیشینه
ماژول 7 نحوه استفاده از App Engine Task Queue push tasks را در برنامههای Python 2 Flask App Engine نشان میدهد. در ماژول 8 ، آن برنامه را از Task Queue به Cloud Tasks منتقل میکنید. در اینجا در ماژول 9 ، این سفر را ادامه میدهید و آن برنامه را به Python 3 منتقل میکنید و همچنین دسترسی Datastore را از استفاده از Cloud NDB به کتابخانه کلاینت Cloud Datastore بومی تغییر میدهید.
از آنجایی که Cloud NDB هم برای پایتون ۲ و هم برای پایتون ۳ کار میکند، برای کاربران App Engine که برنامههای خود را از پایتون ۲ به ۳ منتقل میکنند، کافی است. انتقال اضافی کتابخانههای کلاینت به Cloud Datastore کاملاً اختیاری است و تنها یک دلیل برای در نظر گرفتن آن وجود دارد: شما برنامههایی غیر از App Engine (و/یا برنامههای Python 3 App Engine) دارید که از قبل از کتابخانه کلاینت Cloud Datastore استفاده میکنند و میخواهید پایگاه کد خود را برای دسترسی به Datastore تنها با یک کتابخانه کلاینت تجمیع کنید. Cloud NDB به طور خاص برای توسعهدهندگان Python 2 App Engine به عنوان ابزاری برای انتقال به پایتون ۳ ایجاد شده است، بنابراین اگر از قبل کدی با استفاده از کتابخانه کلاینت Cloud Datastore ندارید، نیازی به در نظر گرفتن این انتقال ندارید.
در نهایت، توسعه کتابخانه کلاینت Cloud Tasks فقط در پایتون ۳ ادامه دارد، بنابراین ما در حال "مهاجرت" از یکی از نسخههای نهایی پایتون ۲ به پایتون ۳ همعصر آن هستیم. خوشبختانه، هیچ تغییر اساسی نسبت به پایتون ۲ وجود ندارد، به این معنی که در اینجا نیازی به انجام کار دیگری ندارید.
این آموزش شامل مراحل زیر است:
- راهاندازی/پیشپردازش
- پیکربندی را بهروزرسانی کنید
- اصلاح کد برنامه
۳. تنظیمات/پیشپردازش
این بخش توضیح میدهد که چگونه:
- پروژه ابری خود را راهاندازی کنید
- دریافت برنامه نمونه پایه
- (دوباره)استقرار و اعتبارسنجی برنامه پایه
این مراحل تضمین میکنند که شما با کدی کار میکنید که به درستی کار میکند و برای انتقال به سرویسهای ابری آماده است.
۱. پروژه راهاندازی
اگر آزمایشگاه کد ماژول ۸ را تکمیل کردهاید، از همان پروژه (و کد) دوباره استفاده کنید. روش دیگر، ایجاد یک پروژه کاملاً جدید یا استفاده مجدد از یک پروژه موجود دیگر است. مطمئن شوید که پروژه دارای یک حساب صورتحساب فعال و یک برنامه App Engine فعال است. شناسه پروژه خود را پیدا کنید زیرا در طول این آزمایشگاه کد به آن نیاز دارید و هر زمان که با متغیر PROJECT_ID مواجه شدید، از آن استفاده کنید.
۲. نمونه برنامه پایه را دریافت کنید
یکی از پیشنیازها، یک برنامهی ماژول ۸ App Engine است که کار کند: کدلب ماژول ۸ (توصیه میشود) را تکمیل کنید یا برنامهی ماژول ۸ را از مخزن کپی کنید. چه از کد خودتان استفاده کنید و چه از کد ما، کد ماژول ۸ جایی است که ما شروع میکنیم ("شروع"). این کدلب شما را در طول مهاجرت راهنمایی میکند و با کدی که شبیه کد موجود در پوشهی مخزن ماژول ۹ است ("پایان")، به پایان میرسد.
- شروع: مخزن ماژول ۸
- پایان: مخزن ماژول ۹
- کل مخزن (کلون کردن یا دانلود فایل زیپ)
صرف نظر از اینکه از کدام برنامه ماژول ۷ استفاده میکنید، پوشه باید مانند زیر باشد، احتمالاً شامل یک پوشه lib نیز خواهد بود:
$ ls README.md appengine_config.py requirements.txt app.yaml main.py templates
۳. (دوباره) استقرار و اعتبارسنجی برنامه پایه
برای نصب برنامه ماژول ۸ مراحل زیر را انجام دهید:
- اگر پوشه
libوجود دارد، آن را حذف کنید وpip install -t lib -r requirements.txtرا برای پر کردن مجددlibاجرا کنید. اگر پایتون ۲ و ۳ را روی دستگاه توسعه خود نصب دارید، ممکن است لازم باشد ازpip2استفاده کنید. - مطمئن شوید که ابزار خط فرمان
gcloudرا نصب و راهاندازی اولیه کردهاید و نحوهی استفاده از آن را بررسی کردهاید. - (اختیاری) اگر نمیخواهید
PROJECT_IDبا هر دستورgcloudوارد کنید، پروژه Cloud خود را باgcloud config set projectPROJECT_IDتنظیم کنید. - برنامه نمونه را با
gcloud app deployمستقر کنید - تأیید کنید که برنامه طبق انتظار و بدون مشکل اجرا میشود. اگر ماژول ۸ codelab را تکمیل کرده باشید، برنامه بازدیدکنندگان برتر را به همراه جدیدترین بازدیدها (در زیر نشان داده شده است) نمایش میدهد. در پایین، نشانهای از وظایف قدیمیتر که حذف خواهند شد، وجود دارد.

۴. بهروزرسانی پیکربندی
الزامات.txt
فایل requirements.txt جدید تقریباً مشابه فایل ماژول ۸ است، تنها با یک تغییر بزرگ: google-cloud-ndb را با google-cloud-datastore جایگزین کنید. این تغییر را ایجاد کنید تا فایل requirements.txt شما به این شکل باشد:
flask
google-cloud-datastore
google-cloud-tasks
این فایل requirements.txt هیچ شماره نسخهای ندارد، به این معنی که آخرین نسخهها انتخاب شدهاند. در صورت بروز هرگونه ناسازگاری، استفاده از شماره نسخهها برای قفل کردن نسخههای کاری برای یک برنامه، یک روش استاندارد است.
برنامه.yaml
نسل دوم App Engine runtime از کتابخانههای داخلی شخص ثالث مانند 2.x پشتیبانی نمیکند و همچنین از کپی کردن کتابخانههای غیر داخلی نیز پشتیبانی نمیکند. تنها الزام برای بستههای شخص ثالث، فهرست کردن آنها در requirements.txt است. در نتیجه، کل بخش libraries از app.yaml قابل حذف است.
بهروزرسانی دیگر این است که زمان اجرای پایتون ۳ نیاز به استفاده از چارچوبهای وب دارد که مسیریابی خود را انجام میدهند. در نتیجه، همه کنترلکنندههای اسکریپت باید به auto تغییر داده شوند. با این حال، از آنجایی که همه مسیرها باید به auto تغییر داده شوند و هیچ فایل استاتیکی از این برنامه نمونه ارائه نمیشود، داشتن هیچ کنترلکنندهای بیربط است، بنابراین کل بخش handlers را نیز حذف کنید.
تنها چیزی که در app.yaml لازم است، تنظیم زمان اجرا روی یک نسخه پشتیبانی شده از پایتون ۳، مثلاً ۳.۱۰، است. این تغییر را ایجاد کنید تا app.yaml جدید و مختصر شده فقط همین یک خط باشد:
runtime: python310
appengine_config.py و lib را حذف کنید
نسل بعدی زمانهای اجرای App Engine، استفاده از بستههای شخص ثالث را اصلاح میکند:
- کتابخانههای داخلی، کتابخانههایی هستند که توسط گوگل بررسی و در سرورهای App Engine در دسترس قرار گرفتهاند، احتمالاً به این دلیل که حاوی کد C/C++ هستند که توسعهدهندگان اجازه ندارند آن را در فضای ابری مستقر کنند - این کتابخانهها دیگر در زمانهای اجرای نسل دوم در دسترس نیستند.
- کپی کردن کتابخانههای غیر داخلی (که گاهی اوقات "فروشی" یا "خود-بستهبندی" نامیده میشوند) دیگر در زمانهای اجرای نسل دوم مورد نیاز نیست. در عوض، آنها باید در
requirements.txtفهرست شوند، جایی که سیستم ساخت به طور خودکار آنها را از طرف شما در زمان استقرار نصب میکند.
در نتیجهی این تغییرات در مدیریت بستههای شخص ثالث، نه فایل appengine_config.py و نه پوشهی lib مورد نیاز نیستند، بنابراین آنها را حذف کنید. در زمانهای اجرای نسل دوم، App Engine به طور خودکار بستههای شخص ثالث ذکر شده در requirements.txt را نصب میکند. خلاصه:
- کتابخانههای خود-بستهبندیشده یا کپیشده از طرف شخص ثالث ممنوع است؛ آنها را در
requirements.txtفهرست کنید. - بدون
pip installدر پوشهlib، به این معنی که دوره پوشهlibوجود ندارد - عدم فهرستبندی کتابخانههای داخلی شخص ثالث (بنابراین بخش
librariesوجود ندارد) درapp.yaml؛ فهرست آنها درrequirements.txt - عدم وجود کتابخانههای شخص ثالث برای ارجاع از برنامه شما به این معنی است که فایل
appengine_config.pyوجود ندارد.
تنها الزام توسعهدهنده، فهرست کردن تمام کتابخانههای شخص ثالث مورد نظر در requirements.txt است.
۵. بهروزرسانی فایلهای برنامه
فقط یک فایل برنامه، main.py ، وجود دارد، بنابراین تمام تغییرات در این بخش فقط بر آن فایل تأثیر میگذارند. در زیر یک تصویر "diffs" در مورد تغییرات کلی که باید برای بازسازی کد موجود در برنامه جدید ایجاد شود، آورده شده است. انتظار نمیرود خوانندگان کد را خط به خط بخوانند، زیرا هدف آن صرفاً دریافت یک نمای کلی تصویری از آنچه در این بازسازی مورد نیاز است، میباشد (اما در صورت تمایل میتوانید آن را در یک برگه جدید باز کنید یا دانلود کرده و بزرگنمایی کنید).

بهروزرسانی واردات و مقداردهی اولیه
بخش import در main.py برای ماژول ۸ از 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()
ثبت وقایع در نسل دوم زمانهای اجرا مانند پایتون ۳ سادهسازی و بهبود یافته است:
- برای تجربه جامع ثبت وقایع، از Cloud Logging استفاده کنید
- برای گزارشگیری ساده، فقط کافیست از طریق
print()بهstdout(یاstderr) ارسال کنید. - نیازی به استفاده از ماژول
loggingپایتون نیست (پس آن را حذف کنید)
به این ترتیب، فایل import مربوط به 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()
مهاجرت به فروشگاه داده ابری
حالا وقت آن رسیده که استفاده از کتابخانه کلاینت 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) جدید ایجاد کنید
در ماژول ۷، ما استفاده از taskqueue App Engine را به برنامه موجود در ماژول ۱ اضافه کردیم. یکی از مزایای کلیدی داشتن وظایف push به عنوان یک ویژگی قدیمی App Engine این است که یک صف "پیشفرض" به طور خودکار ایجاد میشود. وقتی آن برنامه در ماژول ۸ به Cloud Tasks منتقل شد، آن صف پیشفرض از قبل وجود داشت، بنابراین ما هنوز نیازی به نگرانی در مورد آن نداشتیم. این مورد در ماژول ۹ تغییر میکند.
یکی از جنبههای حیاتی که باید در نظر گرفته شود این است که برنامه جدید 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 تقریباً از ماژول ۸ دست نخورده باقی مانده است. آخرین قطعه کدی که باید بررسی شود، کنترل کننده وظیفه است.
بهروزرسانی (push) کنترلکنندهی وظیفه
در تابع 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، اصلاح سبکهای پرسوجو، حذف استفاده از context manager آن و تغییر فراخوانیهای ثبت وقایع به 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() ایجاد نشده است.
پورت کردن به پایتون ۳
این برنامه نمونه برای اجرا روی هر دو نسخه پایتون ۲ و ۳ طراحی شده است. هرگونه تغییر خاص پایتون ۳ قبلاً در بخشهای مربوطه این آموزش پوشش داده شده است. هیچ مرحله اضافی یا کتابخانه سازگاری لازم نیست.
بهروزرسانی وظایف ابری
نسخه نهایی کتابخانه کلاینت Cloud Tasks که از پایتون ۲ پشتیبانی میکند، ۱.۵.۰ است. در زمان نگارش این مطلب، آخرین نسخه کتابخانه کلاینت برای پایتون ۳ کاملاً با آن نسخه سازگار است، بنابراین نیازی به بهروزرسانی بیشتر نیست.
بهروزرسانی قالب HTML
هیچ تغییری در فایل قالب HTML، templates/index.html ، نیز لازم نیست، بنابراین این تمام تغییرات لازم برای رسیدن به برنامه ماژول ۹ را جمعبندی میکند.
۶. خلاصه/پاکسازی
استقرار و تأیید برنامه
پس از اتمام بهروزرسانیهای کد، عمدتاً پورت به پایتون ۳، برنامه خود را با gcloud app deploy مستقر کنید. خروجی باید مشابه برنامههای ماژولهای ۷ و ۸ باشد، با این تفاوت که دسترسی به پایگاه داده را به کتابخانه کلاینت Cloud Datastore منتقل کرده و به پایتون ۳ ارتقا دادهاید:

این مرحله codelab را تکمیل میکند. از شما دعوت میکنیم کد خود را با آنچه در پوشه Module 9 است مقایسه کنید. تبریک میگوییم!
تمیز کردن
عمومی
اگر فعلاً کارتان تمام است، توصیه میکنیم برنامه App Engine خود را غیرفعال کنید تا از پرداخت هزینه جلوگیری شود. با این حال، اگر میخواهید بیشتر آزمایش یا تجربه کنید، پلتفرم App Engine سهمیه رایگان دارد و بنابراین تا زمانی که از آن سطح استفاده تجاوز نکنید، نباید هزینهای از شما دریافت شود. این هزینه برای محاسبات است، اما ممکن است برای سرویسهای مربوطه 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/images -
console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com - لینکهای ذخیرهسازی بالا به
PROJECT_IDو *LOC*ation شما بستگی دارند، برای مثال، اگر برنامه شما در ایالات متحده میزبانی میشود، "us" خواهد بود.
از طرف دیگر، اگر قصد ندارید با این برنامه یا سایر آزمایشگاههای کد مهاجرت مرتبط ادامه دهید و میخواهید همه چیز را به طور کامل حذف کنید، پروژه خود را ببندید .
مخصوص این آزمایشگاه کد
سرویسهای ذکر شده در زیر مختص این codelab هستند. برای اطلاعات بیشتر به مستندات هر محصول مراجعه کنید:
- 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 NDB به Cloud NDB
- ماژول 3 : مهاجرت از Cloud NDB به Cloud Datastore
- ماژولهای ۱۲-۱۳ : مهاجرت از App Engine Memcache به Cloud Memorystore
- ماژولهای ۱۵-۱۶ : مهاجرت از App Engine Blobstore به Cloud Storage
- ماژولهای ۱۸-۱۹ : صف وظایف موتور برنامه (وظایف را بکشید) به Cloud Pub/Sub
App Engine دیگر تنها پلتفرم بدون سرور در Google Cloud نیست. اگر یک برنامه کوچک App Engine یا برنامهای با قابلیتهای محدود دارید و میخواهید آن را به یک میکروسرویس مستقل تبدیل کنید، یا میخواهید یک برنامه یکپارچه را به چندین مؤلفه قابل استفاده مجدد تقسیم کنید، اینها دلایل خوبی برای در نظر گرفتن انتقال به Cloud Functions هستند. اگر کانتینرسازی به بخشی از گردش کار توسعه برنامه شما تبدیل شده است، به خصوص اگر شامل یک خط لوله CI/CD (ادغام مداوم/تحویل مداوم یا استقرار) باشد، مهاجرت به Cloud Run را در نظر بگیرید. این سناریوها توسط ماژولهای زیر پوشش داده میشوند:
- مهاجرت از موتور برنامه به توابع ابری: به ماژول 11 مراجعه کنید
- مهاجرت از App Engine به Cloud Run: برای کانتینرایز کردن برنامه خود با Docker به ماژول ۴ و برای انجام این کار بدون کانتینرها، دانش Docker یا
Dockerfileها به ماژول ۵ مراجعه کنید.
تغییر به یک پلتفرم بدون سرور دیگر اختیاری است و توصیه میکنیم قبل از ایجاد هرگونه تغییر، بهترین گزینهها را برای برنامهها و موارد استفاده خود در نظر بگیرید.
صرف نظر از اینکه کدام ماژول مهاجرت را در مرحله بعد در نظر بگیرید، تمام محتوای Serverless Migration Station (آزمایشگاههای کد، ویدیوها، کد منبع [در صورت وجود]) در مخزن متنباز آن قابل دسترسی است. README این مخزن همچنین راهنماییهایی در مورد اینکه کدام مهاجرتها را باید در نظر گرفت و هرگونه «ترتیب» مربوط به ماژولهای مهاجرت ارائه میدهد.
۷. منابع اضافی
مشکلات/بازخوردهای Codelabs
اگر در این آزمایشگاه کد مشکلی پیدا کردید، لطفاً قبل از ثبت، ابتدا مشکل خود را جستجو کنید. لینکهای جستجو و ایجاد مشکلات جدید:
منابع مهاجرت
لینکهای پوشههای مخزن ماژول ۸ (START) و ماژول ۹ (FINISH) را میتوانید در جدول زیر پیدا کنید. همچنین میتوانید از مخزن تمام مهاجرتهای Codelab مربوط به App Engine که میتوانید آنها را کلون کنید یا یک فایل ZIP دانلود کنید، به آنها دسترسی داشته باشید.
کدلب | پایتون ۲ | پایتون ۳ |
(نامشخص) | ||
ماژول ۹ | (نامشخص) |
منابع آنلاین
در زیر منابع آنلاینی وجود دارد که ممکن است برای این آموزش مرتبط باشند:
موتور برنامه
- مستندات موتور برنامه
- موتور برنامه پایتون ۲ (محیط استاندارد) در زمان اجرا
- موتور برنامه پایتون ۳ (محیط استاندارد) در زمان اجرا
- تفاوتهای بین زمانهای اجرای موتور برنامه پایتون ۲ و ۳ (محیط استاندارد)
- راهنمای مهاجرت موتور برنامه پایتون ۲ به ۳ (محیط استاندارد)
- اطلاعات قیمتگذاری و سهمیهبندی موتور برنامه
ابر NDB
فروشگاه داده ابری
وظایف ابری
سایر اطلاعات ابری
- پایتون در پلتفرم ابری گوگل
- کتابخانههای کلاینت پایتون گوگل کلود
- سطح «همیشه رایگان» گوگل کلود
- کیت توسعه نرمافزار گوگل کلود (ابزار خط فرمان
gcloud) - تمام مستندات گوگل کلود
مجوز
این اثر تحت مجوز عمومی Creative Commons Attribution 2.0 منتشر شده است.