انتقال وظایف کششی از App Engine Task Queue به Cloud Pub/Sub (ماژول 19)

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

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

هدف از این کد لبه این است که به توسعه دهندگان Python 2 App Engine نشان دهد که چگونه از App Engine Task Queue به Cloud Pub/Sub مهاجرت کنند. همچنین یک انتقال ضمنی از App Engine NDB به Cloud NDB برای دسترسی به Datastore (که عمدتاً در ماژول 2 پوشش داده شده است) و همچنین ارتقاء به Python 3 وجود دارد.

در ماژول 18، یاد می گیرید که چگونه استفاده از وظایف کششی را در برنامه خود اضافه کنید. در این ماژول، برنامه ماژول 18 تمام شده را می گیرید و آن استفاده را به Cloud Pub/Sub منتقل می کنید. کسانی که از Task Queues برای وظایف فشاری استفاده می‌کنند، در عوض به Cloud Tasks مهاجرت می‌کنند و در عوض باید به ماژول‌های 7-9 مراجعه کنند.

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

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

نظرسنجی

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

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

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

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

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

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

2. پس زمینه

App Engine Task Queue از وظایف فشاری و کششی پشتیبانی می کند. برای بهبود قابلیت حمل برنامه، Google Cloud مهاجرت از سرویس‌های همراه قدیمی مانند Task Queue به سایر سرویس‌های مستقل Cloud یا مشابه شخص ثالث را توصیه می‌کند.

ماژول های مهاجرت 7-9 مهاجرت وظیفه فشاری را پوشش می دهند در حالی که ماژول های 18-19 بر مهاجرت وظیفه کششی تمرکز دارند. در حالی که Cloud Tasks با وظایف فشاری Task Queue بیشتر مطابقت دارد، Pub/Sub آن‌قدر نزدیک به وظایف کششی Task Queue نیست.

Pub/Sub دارای ویژگی های بیشتری نسبت به قابلیت کشش ارائه شده توسط Task Queue است. به عنوان مثال، Pub/Sub همچنین دارای قابلیت فشار است، با این حال وظایف Cloud بیشتر شبیه وظایف فشاری Task Queue است، بنابراین Pub/Sub push توسط هیچ یک از ماژول‌های مهاجرت پوشش داده نمی‌شود . این آزمایشگاه کد ماژول 19 تغییر مکانیسم صف را از صف‌های کششی Task Queue به Pub/Sub و همچنین انتقال از App Engine NDB به Cloud NDB برای دسترسی به Datastore را نشان می‌دهد و انتقال ماژول 2 را تکرار می‌کند.

در حالی که کد ماژول 18 به عنوان یک برنامه نمونه Python 2 "تبلیغ می شود"، منبع خود با Python 2 و 3 سازگار است، و حتی پس از مهاجرت به Cloud Pub/Sub (و Cloud NDB) در اینجا در ماژول 19 به همین شکل باقی می ماند.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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 کد ماژول 18 را تکمیل کرده باشید، برنامه بازدیدکنندگان برتر را به همراه آخرین بازدیدها نمایش می دهد (تصویر زیر). اگر نه، ممکن است تعداد بازدیدکنندگانی برای نمایش وجود نداشته باشد.

b667551dcbab1a09.png

قبل از انتقال برنامه نمونه ماژول 18، ابتدا باید سرویس‌های Cloud را که برنامه اصلاح‌شده استفاده می‌کند، فعال کنید.

4. سرویس‌ها/APIهای جدید Google Cloud را فعال کنید

برنامه قدیمی از خدمات همراه App Engine استفاده می‌کرد که نیازی به راه‌اندازی اضافی ندارند، اما سرویس‌های Cloud مستقل این کار را انجام می‌دهند، و برنامه به‌روزرسانی شده از Cloud Pub/Sub و Cloud Datastore (از طریق کتابخانه سرویس گیرنده Cloud NDB) استفاده می‌کند. App Engine و هر دو Cloud API دارای سهمیه‌های ردیف «همیشه رایگان» هستند، و تا زمانی که زیر این محدودیت‌ها بمانید، برای تکمیل این آموزش نباید هزینه‌ای متحمل شوید. بسته به اولویت شما، APIهای Cloud را می توان از طریق کنسول Cloud یا از خط فرمان فعال کرد.

از کنسول Cloud

به صفحه کتابخانه مدیر API (برای پروژه صحیح) در Cloud Console بروید و Cloud Datastore و Cloud Pub/Sub API را با استفاده از نوار جستجو در وسط صفحه جستجو کنید:

c7a740304e9d35b.png

برای هر API جداگانه روی دکمه فعال کردن کلیک کنید—ممکن است اطلاعات صورتحساب از شما خواسته شود. برای مثال، این صفحه Cloud Pub/Sub API Library است:

1b6c0a2a73124f6b.jpeg

از خط فرمان

در حالی که از نظر بصری آموزنده API های کنسول را فعال می کند، برخی خط فرمان را ترجیح می دهند. gcloud services enable pubsub.googleapis.com datastore.googleapis.com برای فعال کردن هر دو API به طور همزمان صادر کنید:

$ gcloud services enable pubsub.googleapis.com datastore.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

ممکن است اطلاعات صورتحساب از شما خواسته شود. اگر می‌خواهید سایر APIهای Cloud را فعال کنید و می‌خواهید بدانید URI آنها چیست، می‌توانید آنها را در پایین صفحه کتابخانه هر API پیدا کنید. به عنوان مثال، pubsub.googleapis.com به عنوان "نام سرویس" در پایین صفحه Pub/Sub درست در بالا مشاهده کنید.

پس از تکمیل مراحل، پروژه شما قادر به دسترسی به APIها خواهد بود. اکنون زمان به روز رسانی برنامه برای استفاده از آن API ها است.

4. منابع Pub/Sub را ایجاد کنید

خلاصه کردن ترتیب توالی گردش کار Task Queue از ماژول 18:

  1. ماژول 18 از فایل queue.yaml برای ایجاد یک صف کشی به نام pullq استفاده کرد.
  2. این برنامه وظایفی را به صف کشش اضافه می کند تا بازدیدکنندگان را ردیابی کند.
  3. وظایف در نهایت توسط یک کارگر پردازش می شود و برای مدت زمان محدودی (یک ساعت) اجاره داده می شود.
  4. کارها برای محاسبه تعداد بازدیدکنندگان اخیر اجرا می شوند.
  5. پس از اتمام کارها از صف حذف می شوند.

شما می خواهید یک گردش کار مشابه را با Pub/Sub تکرار کنید. بخش بعدی اصطلاحات پایه Pub/Sub را با سه روش مختلف برای ایجاد منابع Pub/Sub ضروری معرفی می‌کند.

صف کار موتور برنامه (کشش) در مقابل اصطلاحات Cloud Pub/Sub

تغییر به Pub/Sub نیازمند تعدیل جزئی در واژگان شماست. در زیر دسته بندی های اولیه به همراه عبارات مربوطه از هر دو محصول فهرست شده است. همچنین راهنمای مهاجرت را که دارای مقایسه‌های مشابه است، مرور کنید.

  • ساختار داده در صف: با Task Queue، داده ها به صف های کششی می روند. با Pub/Sub، داده ها وارد موضوعات می شوند.
  • واحدهای داده در صف: کارهای کششی با Task Queue پیام هایی با Pub/Sub نامیده می شوند.
  • پردازشگرهای داده: با Task Queue، کارگران به وظایف کششی دسترسی دارند. با Pub/Sub، برای دریافت پیام ها به اشتراک/مشترک نیاز دارید
  • استخراج داده: اجاره یک کار کششی مانند کشیدن پیام از یک موضوع (از طریق اشتراک) است.
  • پاکسازی/تکمیل: حذف یک کار Task Queue از یک صف کشش پس از اتمام کار، مشابه تایید یک پیام Pub/Sub است.

اگرچه محصول صف تغییر می کند، گردش کار نسبتا مشابه باقی می ماند:

  1. این برنامه به جای صف کشیدن، از موضوعی به نام pullq استفاده می کند.
  2. برنامه به جای اضافه کردن کارها به صف کشش، پیام هایی را به یک موضوع ارسال می کند ( pullq ).
  3. به جای اینکه یک کارگر وظایف را از صف کشش اجاره کند، مشترکی به نام worker پیام‌ها را از موضوع pullq می‌کشد .
  4. این برنامه بارهای پیام را پردازش می کند و تعداد بازدیدکنندگان را در Datastore افزایش می دهد.
  5. برنامه به جای حذف وظایف از صف کشش، پیام های پردازش شده را تأیید می کند .

با Task Queue، راه اندازی شامل ایجاد صف کشش است. با Pub/Sub، راه‌اندازی نیاز به ایجاد یک موضوع و اشتراک دارد. در ماژول 18، queue.yaml خارج از اجرای برنامه پردازش کردیم. اکنون همین کار باید با Pub/Sub انجام شود.

سه گزینه برای ایجاد موضوعات و اشتراک وجود دارد:

  1. از کنسول Cloud
  2. از خط فرمان یا
  3. از کد (اسکریپت کوتاه پایتون)

یکی از گزینه های زیر را انتخاب کنید و دستورالعمل های مربوطه را برای ایجاد منابع Pub/Sub دنبال کنید.

از کنسول Cloud

برای ایجاد موضوع از Cloud Console، مراحل زیر را دنبال کنید:

  1. به صفحه Pub/Sub Topics کنسول Cloud بروید.
  2. روی ایجاد موضوع در بالا کلیک کنید. یک پنجره محاوره ای جدید باز می شود (تصویر زیر را ببینید)
  3. در قسمت شناسه موضوع ، pullq وارد کنید.
  4. همه گزینه‌های علامت‌گذاری شده را بردارید و کلید رمزگذاری مدیریت‌شده توسط Google را انتخاب کنید.
  5. روی دکمه ایجاد موضوع کلیک کنید.

گفتگوی ایجاد موضوع به این صورت است:

a05cfdbf64571ceb.png

اکنون که یک موضوع دارید، یک اشتراک برای آن موضوع باید ایجاد شود:

  1. به صفحه اشتراک‌های Pub/Sub Console Cloud بروید.
  2. روی ایجاد اشتراک در بالا کلیک کنید (تصویر زیر را ببینید).
  3. worker در قسمت شناسه اشتراک وارد کنید.
  4. pullq از منوی کشویی Select a Cloud Pub/Sub انتخاب کنید و به «نام مسیر کاملاً واجد شرایط» آن اشاره کنید، به عنوان مثال، projects/PROJECT_ID/topics/pullq
  5. برای نوع تحویل ، Pull را انتخاب کنید.
  6. همه گزینه های دیگر را همانطور که هست رها کنید و روی دکمه Create کلیک کنید.

صفحه ایجاد اشتراک به این صورت است:

c5444375c20b0618.jpeg

همچنین می‌توانید از صفحه موضوعات یک اشتراک ایجاد کنید—این «میانبر» ممکن است برای کمک به مرتبط کردن موضوعات با اشتراک‌ها برای شما مفید باشد. برای کسب اطلاعات بیشتر درباره ایجاد اشتراک، به مستندات مراجعه کنید.

از خط فرمان

کاربران Pub/Sub می توانند با دستورات gcloud pubsub topics create TOPIC_ID و gcloud pubsub subscriptions create به ترتیب SUBSCRIPTION_ID --topic= TOPIC_ID ایجاد می کنند، موضوع و اشتراک ایجاد کنند. اجرای این موارد با TOPIC_ID pullq و SUBSCRIPTION_ID worker ، خروجی زیر را برای پروژه PROJECT_ID به همراه دارد:

$ gcloud pubsub topics create pullq
Created topic [projects/PROJECT_ID/topics/pullq].

$ gcloud pubsub subscriptions create worker --topic=pullq
Created subscription [projects/PROJECT_ID/subscriptions/worker].

همچنین این صفحه را در اسناد شروع سریع ببینید. استفاده از خط فرمان ممکن است گردش کار را در جایی که موضوعات و اشتراک ها به طور منظم ایجاد می شوند، ساده کند، و چنین دستوراتی را می توان در اسکریپت های پوسته برای این منظور استفاده کرد.

از کد (اسکریپت کوتاه پایتون)

راه دیگر برای خودکارسازی ایجاد موضوعات و اشتراک ها، استفاده از Pub/Sub API در کد منبع است. در زیر کد اسکریپت maker.py در پوشه Repo Module 19 آمده است.

from __future__ import print_function
import google.auth
from google.api_core import exceptions
from google.cloud import pubsub

_, PROJECT_ID = google.auth.default()
TOPIC = 'pullq'
SBSCR = 'worker'
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)

def make_top():
    try:
        top = ppc_client.create_topic(name=TOP_PATH)
        print('Created topic %r (%s)' % (TOPIC, top.name))
    except exceptions.AlreadyExists:
        print('Topic %r already exists at %r' % (TOPIC, TOP_PATH))

def make_sub():
    try:
        sub = psc_client.create_subscription(name=SUB_PATH, topic=TOP_PATH)
        print('Subscription created %r (%s)' % (SBSCR, sub.name))
    except exceptions.AlreadyExists:
        print('Subscription %r already exists at %r' % (SBSCR, SUB_PATH))
    try:
        psc_client.close()
    except AttributeError:  # special Py2 handler for grpcio<1.12.0
        pass

make_top()
make_sub()

اجرای این اسکریپت منجر به خروجی مورد انتظار می شود (به شرطی که خطایی وجود نداشته باشد):

$ python3 maker.py
Created topic 'pullq' (projects/PROJECT_ID/topics/pullq)
Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)

فراخوانی API برای ایجاد منابع از قبل موجود منجر به یک استثنا google.api_core.exceptions.AlreadyExists می شود.AlreadyExists که توسط کتابخانه سرویس گیرنده پرتاب شده است، که به خوبی توسط اسکریپت مدیریت می شود:

$ python3 maker.py
Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq'
Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'

اگر تازه وارد Pub/Sub هستید، برای اطلاعات بیشتر به مقاله سفید معماری Pub/Sub مراجعه کنید.

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

به‌روزرسانی‌های پیکربندی شامل تغییر فایل‌های پیکربندی مختلف و همچنین ایجاد صف‌های کششی معادل App Engine اما در اکوسیستم Cloud Pub/Sub است.

حذف queue.yaml

ما به طور کامل از Task Queue دور می شویم، بنابراین queue.yaml حذف کنید زیرا Pub/Sub از این فایل استفاده نمی کند. به جای ایجاد یک صف کشش ، یک موضوع Pub/Subاشتراک ) ایجاد خواهید کرد.

الزامات. txt

هر دو google-cloud-ndb و google-cloud-pubsub را به requirements.txt اضافه کنید تا به flask از ماژول 18 بپیوندید. ماژول 19 به روز شده شما requirements.txt اکنون باید به این شکل باشد:

flask
google-cloud-ndb
google-cloud-pubsub

این فایل requirements.txt هیچ شماره نسخه ای ندارد، یعنی آخرین نسخه ها انتخاب شده اند. در صورت بروز هرگونه ناسازگاری، از رویه استاندارد استفاده از شماره نسخه برای قفل کردن نسخه های کاری یک برنامه پیروی کنید.

app.yaml

تغییرات در app.yaml بسته به اینکه با پایتون 2 بمانید یا به پایتون 3 ارتقا دهید متفاوت است.

پایتون 2

به روز رسانی بالا به requirements.txt استفاده از کتابخانه های سرویس گیرنده Google Cloud را اضافه می کند. اینها به پشتیبانی اضافی از App Engine نیاز دارند، یعنی چند کتابخانه داخلی ، setuptools و grpcio . استفاده از کتابخانه‌های داخلی به بخش libraries در app.yaml و شماره‌های نسخه کتابخانه یا «جدیدترین» برای آخرین نسخه‌های موجود در سرورهای App Engine نیاز دارد. Module 18 app.yaml هنوز یکی از این بخش‌ها را ندارد:

قبل از:

runtime: python27
threadsafe: yes
api_version: 1

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

یک بخش libraries را به app.yaml به همراه ورودی‌هایی برای setuptools و grpcio اضافه کنید و آخرین نسخه‌های آنها را انتخاب کنید. همچنین یک ورودی runtime برای Python 3 اضافه کنید، که همراه با نسخه فعلی 3.x، به عنوان مثال، 3.10، در زمان نوشتن این نظر توضیح داده شده است. با این تغییرات، app.yaml اکنون به شکل زیر است:

بعد از:

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

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

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

پایتون 3

برای کاربران Python 3 و app.yaml ، همه چیز در مورد حذف چیزها است. در این بخش، بخش handlers ، دستورات threadsafe و api_version را حذف می‌کنید و بخش libraries ایجاد نمی‌کنید.

زمان‌های اجرا نسل دوم کتابخانه‌های شخص ثالث داخلی را ارائه نمی‌کنند، بنابراین به بخش libraries در app.yaml نیازی نیست . علاوه بر این، کپی کردن (که گاهی اوقات به عنوان فروشنده یا خود بسته‌بندی شناخته می‌شود) بسته‌های شخص ثالث غیر داخلی دیگر مورد نیاز نیست. شما فقط باید کتابخانه های شخص ثالثی را که برنامه شما از آنها استفاده می کند در requirements.txt فهرست کنید.

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

در نهایت، نه دستورالعمل threadsafe و نه api_version در پایتون 3 استفاده نمی شود، بنابراین آن ها را نیز حذف کنید. نکته اصلی این است که شما باید تمام بخش‌های app.yaml را حذف کنید تا فقط دستور runtime باقی بماند و یک نسخه مدرن از Python 3 را مشخص کنید، به عنوان مثال، 3.10. app.yaml قبل و بعد از این به‌روزرسانی‌ها چگونه است:

قبل از:

runtime: python27
threadsafe: yes
api_version: 1

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

بعد از:

runtime: python310

برای کسانی که آماده نیستند همه چیز را از app.yaml خود برای Python 3 حذف کنند، ما یک فایل جایگزین app3.yaml در پوشه Repo Module 19 ارائه کرده ایم. اگر می‌خواهید به جای آن برای استقرار استفاده کنید، حتماً این نام فایل را به انتهای دستور خود اضافه کنید: gcloud app deploy app3.yaml (در غیر این صورت، برنامه شما را به‌طور پیش‌فرض با فایل app.yaml پایتون 2 اجرا می‌کند. بدون تغییر باقی مانده است).

appengine_config.py

اگر در حال ارتقا به پایتون 3 هستید، نیازی به appengine_config.py نیست، پس آن را حذف کنید. دلیل اینکه لازم نیست این است که پشتیبانی از کتابخانه شخص ثالث فقط مستلزم مشخص کردن آنها در requirements.txt است. کاربران پایتون 2، ادامه مطلب را بخوانید.

ماژول 18 appengine_config.py دارای کد مناسب برای پشتیبانی از کتابخانه های شخص ثالث است، به عنوان مثال، Flask و کتابخانه های سرویس گیرنده Cloud که به تازگی به requirements.txt اضافه شده اند:

قبل از:

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

با این حال، این کد به تنهایی برای پشتیبانی از کتابخانه های داخلی که به تازگی اضافه شده اند ( setuptools ، grpcio ) کافی نیست. چند خط دیگر مورد نیاز است، بنابراین 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)

جزئیات بیشتر در مورد تغییرات مورد نیاز برای پشتیبانی از کتابخانه‌های سرویس گیرنده Cloud را می‌توانید در اسناد سرویس‌های همراه انتقال پیدا کنید.

سایر به روز رسانی های پیکربندی

اگر پوشه lib دارید، آن را حذف کنید. اگر کاربر پایتون 2 هستید، پوشه lib را با صدور دستور زیر پر کنید:

pip install -t lib -r requirements.txt  # or pip2

اگر هر دو پایتون 2 و 3 را روی سیستم توسعه خود نصب کرده اید، ممکن است لازم باشد به جای pip از pip2 استفاده کنید.

6. کد برنامه را تغییر دهید

این بخش به‌روزرسانی‌های فایل برنامه اصلی، main.py را ارائه می‌کند، که جایگزین استفاده از صف‌های کششی App Engine Task Queue با Cloud Pub/Sub می‌شود. هیچ تغییری در قالب وب، templates/index.html وجود ندارد. هر دو برنامه باید یکسان عمل کنند و داده های یکسانی را نمایش دهند.

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

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

  1. برای واردات، App Engine NDB و Task Queue را با Cloud NDB و Pub/Sub جایگزین کنید.
  2. pullq از یک نام QUEUE به یک نام TOPIC تغییر نام دهید.
  3. با کارهای کششی، کارگر آنها را برای یک ساعت اجاره می‌کند، اما با Pub/Sub، وقفه‌ها بر اساس هر پیام اندازه‌گیری می‌شوند، بنابراین ثابت HOUR را حذف کنید.
  4. APIهای Cloud نیاز به استفاده از یک کلاینت API دارند، بنابراین آن‌ها را برای Cloud NDB و Cloud Pub/Sub آغاز کنید، که دومی برای موضوعات و اشتراک‌ها مشتریانی را ارائه می‌کند.
  5. Pub/Sub به شناسه پروژه Cloud نیاز دارد، بنابراین آن را وارد کنید و از google.auth.default() دریافت کنید.
  6. Pub/Sub به «نام مسیرهای کاملاً واجد شرایط» برای موضوعات و اشتراک‌ها نیاز دارد، بنابراین آن‌هایی را با استفاده از توابع راحت *_path() ایجاد کنید.

در زیر وارد کردن و مقداردهی اولیه از ماژول 18 به دنبال نحوه عملکرد بخش ها پس از اجرای تغییرات بالا آمده است، در حالی که اکثر کدهای جدید منابع مختلف Pub/Sub هستند:

قبل از:

from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb

HOUR = 3600
LIMIT = 10
TASKS = 1000
QNAME = 'pullq'
QUEUE = taskqueue.Queue(QNAME)
app = Flask(__name__)

بعد از:

from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, pubsub

LIMIT = 10
TASKS = 1000
TOPIC = 'pullq'
SBSCR = 'worker'

app = Flask(__name__)
ds_client  = ndb.Client()
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
_, PROJECT_ID = google.auth.default()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)

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

مدل داده Visit تغییر نمی کند. دسترسی به Datastore مستلزم استفاده صریح از مدیر زمینه کلاینت Cloud NDB API، ds_client.context() . در کد، این بدان معناست که تماس‌های Datastore را هم در store_visit() و هم fetch_visits() داخل پایتون with بلوک‌ها قرار می‌دهید. این به روز رسانی مشابه آنچه در ماژول 2 پوشش داده شده است.

مرتبط ترین تغییر برای Pub/Sub جایگزینی صف کشیدن یک وظیفه کششی Task Queue با انتشار یک پیام Pub/Sub به موضوع pullq است. در زیر کد قبل و بعد از انجام این به روز رسانی ها آمده است:

قبل از:

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 in Datastore and queue request to bump visitor count'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
    QUEUE.add(taskqueue.Task(payload=remote_addr, method='PULL'))

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)

def store_visit(remote_addr, user_agent):
    'create new Visit in Datastore and queue request to bump visitor count'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
    ppc_client.publish(TOP_PATH, remote_addr.encode('utf-8'))

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

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

مدل داده‌های VisitorCount تغییر نمی‌کند و fetch_counts() را انجام می‌دهد به جز برای قرار دادن پرس و جو Datastore خود در داخل یک with ، همانطور که در زیر نشان داده شده است:

قبل از:

class VisitorCount(ndb.Model):
    visitor = ndb.StringProperty(repeated=False, required=True)
    counter = ndb.IntegerProperty()

def fetch_counts(limit):
    'get top visitors'
    return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)

بعد از:

class VisitorCount(ndb.Model):
    visitor = ndb.StringProperty(repeated=False, required=True)
    counter = ndb.IntegerProperty()

def fetch_counts(limit):
    'get top visitors'
    with ds_client.context():
        return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)

کد کارگر را به روز کنید

کد کارگر تا جایی که NDB را با Cloud NDB و Task Queue را با Pub/Sub جایگزین می‌کند، به‌روزرسانی می‌شود، اما گردش کار آن یکسان باقی می‌ماند.

  1. تماس‌های Datastore را در مدیر زمینه Cloud NDB with بلوک قرار دهید.
  2. پاکسازی Task Queue شامل حذف تمام وظایف از صف کش می شود. با Pub/Sub، «شناسه‌های تأیید» در acks جمع‌آوری می‌شوند و سپس در پایان حذف/تأیید می‌شوند.
  3. وظایف کششی Task Queue به روشی مشابه که پیام‌های Pub/Sub کشیده می‌شوند اجاره داده می‌شوند. در حالی که حذف وظایف کششی با خود اشیاء وظیفه انجام می شود، پیام های Pub/Sub از طریق شناسه های تأیید آنها حذف می شوند.
  4. بارهای پیام Pub/Sub به بایت نیاز دارند (نه رشته های پایتون)، بنابراین هنگام انتشار و کشیدن پیام ها از یک موضوع، به ترتیب مقداری رمزگذاری و رمزگشایی UTF-8 وجود دارد.

با اجرای تغییراتی که توضیح داده شد، log_visitors() را با کد به روز شده زیر جایگزین کنید:

قبل از:

@app.route('/log')
def log_visitors():
    'worker processes recent visitor counts and updates them in Datastore'
    # tally recent visitor counts from queue then delete those tasks
    tallies = {}
    tasks = QUEUE.lease_tasks(HOUR, TASKS)
    for task in tasks:
        visitor = task.payload
        tallies[visitor] = tallies.get(visitor, 0) + 1
    if tasks:
        QUEUE.delete_tasks(tasks)

    # increment those counts in Datastore and return
    for visitor in tallies:
        counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
        if not counter:
            counter = VisitorCount(visitor=visitor, counter=0)
            counter.put()
        counter.counter += tallies[visitor]
        counter.put()
    return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
            len(tasks), len(tallies))

بعد از:

@app.route('/log')
def log_visitors():
    'worker processes recent visitor counts and updates them in Datastore'
    # tally recent visitor counts from queue then delete those tasks
    tallies = {}
    acks = set()
    rsp = psc_client.pull(subscription=SUB_PATH, max_messages=TASKS)
    msgs = rsp.received_messages
    for rcvd_msg in msgs:
        acks.add(rcvd_msg.ack_id)
        visitor = rcvd_msg.message.data.decode('utf-8')
        tallies[visitor] = tallies.get(visitor, 0) + 1
    if acks:
        psc_client.acknowledge(subscription=SUB_PATH, ack_ids=acks)
    try:
        psc_client.close()
    except AttributeError:  # special handler for grpcio<1.12.0
        pass

    # increment those counts in Datastore and return
    if tallies:
        with ds_client.context():
            for visitor in tallies:
                counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
                if not counter:
                    counter = VisitorCount(visitor=visitor, counter=0)
                    counter.put()
                counter.counter += tallies[visitor]
                counter.put()
    return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
            len(msgs), len(tallies))

هیچ تغییری در root() handler برنامه اصلی وجود ندارد. در فایل قالب HTML، templates/index.html نیز نیازی به تغییر نیست، بنابراین تمام به‌روزرسانی‌های لازم را جمع‌بندی می‌کند. برای ورود به برنامه جدید ماژول 19 با استفاده از Cloud Pub/Sub تبریک می گویم!

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

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

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

مطمئن شوید که قبلاً موضوع pullq و اشتراک worker را ایجاد کرده اید. اگر این کار تکمیل شده است و نمونه برنامه شما آماده است، برنامه خود را با gcloud app deploy اجرا کنید. خروجی باید با برنامه ماژول 18 یکسان باشد، به جز اینکه شما با موفقیت کل مکانیسم صف بندی زیرین را جایگزین کرده اید:

b667551dcbab1a09.png

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

می‌توانید این کار را با یک سرویس App Engine Backend، یک کار cron ، مرور به /log یا صدور یک درخواست HTTP خط فرمان اجرا کنید. در اینجا یک نمونه اجرا و فراخوانی کد کارگر با curl آمده است ( PROJECT_ID خود را جایگزین کنید):

$ curl https://PROJECT_ID.appspot.com/log
DONE (with 1 task[s] logging 1 visitor[s])

سپس تعداد به روز شده در بازدید بعدی وب سایت منعکس خواهد شد. همین!

تمیز کردن

ژنرال

اگر فعلاً کارتان تمام شده است، توصیه می‌کنیم برنامه 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 Pub/Sub دارای یک ردیف رایگان هستند. استفاده کلی خود را تعیین کنید تا ایده بهتری از پیامدهای هزینه بدست آورید و برای جزئیات بیشتر به صفحه قیمت آن مراجعه کنید.
  • سرویس App Engine Datastore توسط Cloud Datastore (Cloud Firestore در حالت Datastore) ارائه می شود که دارای یک ردیف رایگان نیز می باشد. برای اطلاعات بیشتر به صفحه قیمت آن مراجعه کنید.

مراحل بعدی

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

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 مخزن همچنین راهنمایی هایی را ارائه می دهد که کدام مهاجرت ها باید در نظر گرفته شود و هر "ترتیب" مربوط به ماژول های مهاجرت.

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

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

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

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

منابع مهاجرت

پیوندهای پوشه‌های مخزن برای ماژول 18 (START) و ماژول 19 (FINISH) را می‌توانید در جدول زیر پیدا کنید.

Codelab

پایتون 2

پایتون 3

ماژول 18

کد

(n/a)

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

کد

(همانند Python 2 به جز اینکه از app3.yaml استفاده کنید مگر اینکه app.yaml را همانطور که در بالا به‌روزرسانی کرده‌اید)

مراجع آنلاین

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

صف وظایف موتور برنامه

Cloud Pub/Sub

App Engine NDB و Cloud NDB (Datastore)

پلت فرم App Engine

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

ویدیوها

مجوز

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