ماژول 6: مهاجرت از Cloud Datastore به Cloud Firestore

۱. مرور کلی

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

کاربران App Engine که به Datastore با کتابخانه‌های کلاینت Cloud NDB یا Cloud Datastore دسترسی دارند، مشکلی ندارند و نیازی به مهاجرت بیشتر ندارند. با این حال، Cloud Firestore جدیدترین، مقیاس‌پذیرترین، با دسترسی بالا و Datastore NoSQL را با ویژگی‌های پایگاه داده بلادرنگ Firebase ارائه می‌دهد.

اگر توسعه‌دهنده‌ای هستید که احساس می‌کنید باید از Firestore استفاده کنید تا از ویژگی‌های آن بهره‌مند شوید یا حداقل علاقه کافی برای بررسی پیامدهای این مهاجرت دارید، در جای درستی هستید. این آموزش به شما می‌آموزد که چگونه یک برنامه App Engine را با استفاده از Cloud Datastore به Cloud Firestore منتقل کنید.

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

  • تفاوت‌های بین Datastore و Firestore را تشخیص دهید
  • مهاجرت از Cloud Datastore به Cloud Firestore

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

نظرسنجی

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

فقط آن را بخوانید آن را بخوانید و تمرین‌ها را انجام دهید

۲. پیشینه

فروشگاه داده‌ی App Engine در سال ۲۰۱۳ به محصول مستقلی با نام Google Cloud Datastore تبدیل شد و اکنون برای توسعه‌دهندگان خارج از App Engine نیز قابل دسترسی است. سال بعد، Firebase توسط گوگل خریداری شد. در آن زمان، Firebase به خاطر پایگاه داده‌ی بلادرنگ خود شناخته می‌شد.

در طول چند سال بعد، تیم‌های Firebase و Cloud Datastore روی ادغام برخی از ویژگی‌های Firebase در Datastore کار کردند. در نتیجه، در سال ۲۰۱۷، نسل بعدی Cloud Datastore منتشر شد . برای انعکاس برخی از ویژگی‌های Firebase، نام آن به Cloud Firestore تغییر یافت.

Cloud Firestore به مکانیزم ذخیره‌سازی NoSQL پیش‌فرض برای پروژه‌های Google Cloud تبدیل شد. برنامه‌های جدید می‌توانند به صورت بومی از Cloud Firestore استفاده کنند، در حالی که پایگاه‌های داده Datastore موجود به Firestore تبدیل شده‌اند و اکنون به عنوان "Firestore در حالت Datastore" عمل می‌کنند تا سازگاری با عملیات Datastore حفظ شود. در نتیجه، برنامه‌ها فقط می‌توانند Cloud Firestore را در یکی از این حالت‌ها اجرا کنند و پس از تنظیم، قابل تغییر نیستند.

در حال حاضر وقتی کاربران پروژه‌های جدیدی ایجاد می‌کنند و یک راه‌حل NoSQL را انتخاب می‌کنند، از آنها خواسته می‌شود که Firestore را در حالت Datastore یا Firestore را در حالت native انتخاب کنند. هنگامی که کاربران موجودیت‌های Datastore را اضافه می‌کنند، نمی‌توانند به Firestore تغییر دهند و به همین ترتیب، هنگامی که حالت native Firestore انتخاب می‌شود، دیگر نمی‌توانند به Datastore (یا بهتر بگوییم، Firestore در حالت Datastore) برگردند. برای جزئیات بیشتر ، صفحه انتخاب بین Cloud Firestore در حالت Datastore یا حالت native Firestore را در مستندات مطالعه کنید. برای انتقال یک برنامه به Firestore، باید یک پروژه جدید ایجاد شود، Datastore صادر شود و سپس به Firestore وارد شود. هدف از این آموزش، ارائه ایده‌ای از تفاوت‌های بین استفاده از Cloud Datastore و Cloud Firestore به توسعه‌دهندگان است.

این مهاجرت، مهاجرتی نیست که ما از کاربران انتظار انجام آن را داشته باشیم ، به همین دلیل است که مهاجرت اختیاری است. در حالی که مزایای آشکاری برای استفاده بومی از Cloud Firestore مانند احراز هویت کلاینت، ادغام قوانین Firebase و البته پایگاه داده بلادرنگ Firebase وجود دارد، مراحل مهاجرت "نامناسب" هستند:

  • شما باید از پروژه‌ای متفاوت از پروژه برنامه فعلی خود استفاده کنید.
  • پروژه‌ای که در آن یک برنامه موجودیت‌های Datastore اضافه کرده است، نمی‌تواند در حالت بومی به Firestore تغییر یابد.
  • به طور مشابه، پروژه‌ای که در حالت بومی، Firestore را انتخاب کرده است، نمی‌تواند در حالت Datastore به Firestore بازگردد.
  • هیچ ابزار مهاجرتی وجود ندارد که بتواند داده‌ها را از یک پروژه به پروژه دیگر منتقل کند.
  • برخی از ویژگی‌های مهم Datastore، از جمله فضاهای نام و توان عملیاتی بالاتر (بیش از 10 هزار در ثانیه)، در Firestore در دسترس نیستند .
  • ابزارهای صادرات و واردات سناریوهای "ابتدایی" و "همه یا هیچ" هستند.
    • اگر برنامه شما دارای موجودیت‌های Datastore زیادی باشد، ممکن است ساعت‌ها طول بکشد تا داده‌ها را export و سپس به Firestore وارد کند.
    • در این مدت، برنامه/سرویس شما قادر به نوشتن/به‌روزرسانی داده‌ها نخواهد بود.
    • فعالیت‌های مهاجرت جزو مصرف عادی محسوب می‌شوند؛ می‌توانید برای به حداقل رساندن هزینه‌ها، آن‌ها را (در صورت امکان بین سهمیه‌های روزانه) پخش کنید.
    • از آنجا که سرویس جدید شما در یک پروژه متفاوت اجرا می‌شود، برای انتشار به‌روزرسانی‌های DNS به یک پنجره نیاز دارید.
  • Datastore و Firestore مدل‌های داده مشابه اما متفاوتی دارند، بنابراین مهاجرت نیاز به به‌روزرسانی نحوه عملکرد برنامه/سرویس دارد.
    • کوئری‌های اجداد از Datastore اکنون کوئری‌های Firestore Collection هستند (پیش‌فرض).
    • کوئری‌های نوع گسترده از Datastore، کوئری‌های گروه Firestore Collection هستند.
    • شاخص‌ها و نحوه‌ی مدیریت آنها متفاوت است و غیره.

با این اوصاف، اگر برنامه‌ی نسبتاً سرراستی برای مهاجرت دارید، آماده‌ی شبیه‌سازی چنین مهاجرتی هستید، یا صرفاً اینجا هستید تا در مورد Datastore در مقابل Firestore اطلاعات کسب کنید، لطفاً ادامه دهید!

کاربران پایتون ۲: این آزمایشگاه کد مهاجرت اختیاری فقط در پایتون ۳ ارائه شده است، با این حال از آنجایی که Cloud Firestore از نسخه ۲.x نیز پشتیبانی می‌کند، کاربران می‌توانند تفاوت‌های استفاده را درون‌یابی کنند. یک مثال این است که رکوردهای Firestore از رشته‌های یونیکد (به جای رشته‌های بایتی) استفاده می‌کنند، بنابراین یک نشانگر u'' برای رشته‌های پایتون ۲ مورد نیاز است، به این معنی که یک تابع store_visit() نسخه ۲.x به این شکل خواهد بود:

def store_visit(remote_addr, user_agent):
    doc_ref = fs_client.collection(u'Visit')
    doc_ref.add({
        u'timestamp': datetime.now(),
        u'visitor': u'{}: {}'.format(remote_addr, user_agent),
    })

به غیر از این، کتابخانه کلاینت نیز باید به طور مشابه عمل کند. تنها مسئله دیگری که باید در نظر گرفته شود این است که کتابخانه Cloud Firestore نسخه ۲.x تا جایی که به توسعه مربوط می‌شود، "متوقف" شده است، بنابراین ویژگی‌های بیشتر/جدیدتر فقط در کتابخانه کلاینت Firestore نسخه ۳.x در دسترس خواهند بود.

با ادامه این مهاجرت، مراحل اصلی این آموزش به شرح زیر است:

  1. راه‌اندازی/پیش‌پردازش
  2. کتابخانه Cloud Firestore را اضافه کنید
  3. به‌روزرسانی فایل‌های برنامه

۳. تنظیمات/پیش‌پردازش

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

۱. پروژه راه‌اندازی

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

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

یکی از پیش‌نیازهای این آزمایشگاه کد، داشتن یک برنامه نمونه ماژول ۳ است که کار کند. اگر آن را ندارید، قبل از ادامه کار، آموزش ماژول ۳ (لینک بالا) را کامل کنید. در غیر این صورت، اگر از قبل با محتوای آن آشنا هستید، می‌توانید با دریافت کد ماژول ۳ زیر شروع کنید.

چه از کد خودتان استفاده کنید و چه از کد ما، کد ماژول ۳ جایی است که ما شروع خواهیم کرد. این آزمایشگاه کد ماژول ۶ شما را در هر مرحله راهنمایی می‌کند و پس از اتمام، باید شبیه کد در نقطه پایان باشد. (این آموزش فقط برای پایتون ۳ در دسترس است.)

دایرکتوری فایل‌های ماژول ۳ (مال شما یا مال ما) باید به این شکل باشد:

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

۳. (دوباره) استقرار ماژول ۳ برنامه

مراحل مقدماتی باقی مانده برای اجرا:

  1. دوباره با ابزار خط فرمان gcloud آشنا شوید (در صورت نیاز)
  2. کد ماژول ۳ را (در صورت نیاز) در App Engine (دوباره) مستقر کنید.

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

پیش‌نیازهای پایتون ۲

  • مطمئن شوید که app.yaml (هنوز) به بسته‌های همراه شخص ثالث اشاره می‌کند: grpcio و setuptools .
  • مطمئن شوید که appengine_config.py همچنان pkg_resources و google.appengine.ext.vendor برای ارجاع برنامه به منابع شخص ثالث استفاده می‌کند.
  • در بخش بعدی که requirements.txt را به‌روزرسانی می‌کند، باید google-cloud-firestore==1.9.0 استفاده کنید، زیرا این نسخه نهایی سازگار با نسخه ۲.x کتابخانه کلاینت پایتون Firestore است.
    • اگر requirements.txt شما ورودی‌ای برای google-cloud-core دارد، آن را به همین صورت رها کنید.
    • lib حذف کرده و با pip install -t lib -r requirements.txt دوباره نصب کنید.

۴. به‌روزرسانی فایل‌های پیکربندی (افزودن کتابخانه Cloud Firestore)

فراتر از راه‌اندازی، مراحل بعدی مورد نیاز، به‌روزرسانی پیکربندی و به دنبال آن فایل‌های برنامه است. برای مورد اول، تنها تغییر پیکربندی، تعویض جزئی بسته در فایل requirements.txt شما است، بنابراین بیایید اکنون این کار را انجام دهیم.

خط google-cloud-datastore را در requirements.txt با google-cloud-firestore جایگزین کنید تا به این شکل درآید:

Flask==1.1.2
google-cloud-firestore==2.0.2

توصیه می‌کنیم از آخرین نسخه‌های هر کتابخانه استفاده کنید؛ شماره نسخه‌های بالا آخرین شماره‌ها در زمان نگارش این مطلب هستند. کد موجود در پوشه مخزن FINISH مرتباً به‌روزرسانی می‌شود و ممکن است نسخه جدیدتری داشته باشد.

هیچ تغییر پیکربندی دیگری وجود ندارد، بنابراین app.yaml و templates/index.html به همان شکل قبلی باقی می‌مانند.

۵. به‌روزرسانی فایل‌های برنامه

فقط یک فایل برنامه، main.py ، وجود دارد، بنابراین تمام تغییرات در این بخش فقط روی آن فایل تأثیر می‌گذارد.

۱. واردات

تغییر import پکیج، یک تغییر جزئی از datastore به firestore است:

  • قبل از:
from google.cloud import datastore
  • بعد از:
from google.cloud import firestore

2. Firestore access

پس از راه‌اندازی اولیه Flask، کلاینت Firestore خود را ایجاد کنید. تغییری مشابه بالا ایجاد کنید، اما برای راه‌اندازی کلاینت:

  • قبل از:
app = Flask(__name__)
ds_client = datastore.Client()
  • بعد از:
app = Flask(__name__)
fs_client = firestore.Client()

با انجام مهاجرت از Cloud NDB به Cloud Datastore، شما کار سنگین رسیدن به Cloud Firestore را انجام داده‌اید. با Datastore، رکوردهای داده را به شکل Entityهایی که از Propertyهای مشترک تشکیل شده‌اند، ایجاد می‌کنید و آنها را بر اساس Keys گروه‌بندی می‌کنید . رکوردهای داده در Firestore اسنادی هستند که از جفت‌های کلید-مقدار تشکیل شده‌اند و در Collections گروه‌بندی می‌شوند . مهاجرت از Datastore مستلزم آن است که شما در مورد این تفاوت‌ها فکر کنید زیرا آنها هنگام ایجاد رکوردهای داده و همچنین پرس و جو برای آنها، خود را نشان می‌دهند. نتایج شما ممکن است بسته به پیچیدگی کد Datastore شما متفاوت باشد.

برای Datastore، شما پرس‌وجوها را بر اساس نوع Entity به همراه معیارهای فیلتر و مرتب‌سازی انجام می‌دهید. برای Firestore، پرس‌وجو از داده‌ها مشابه است. بیایید به یک مثال سریع، با فرض این مقادیر پرس‌وجو، کلاینت‌ها (به ترتیب ds_client یا fs_client ) و importها، نگاهی بیندازیم:

from datetime import datetime
from firestore.Query import DESCENDING

OCT1 = datetime(2020, 10, 1)
LIMIT = 10

برای Datastore، بیایید ده مورد از جدیدترین موجودیت‌های Visit جدیدتر از ۱ اکتبر ۲۰۲۰ را به ترتیب نزولی جستجو کنیم:

query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)

همین کار را برای Firestore، از مجموعه Visit ، انجام می‌دهیم:

query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()

کوئری نمونه برنامه ساده‌تر است (بدون عبارت "WHERE"). به عنوان یک بررسی، کد Cloud Datastore در اینجا آمده است:

  • قبل از:
def store_visit(remote_addr, user_agent):
    entity = datastore.Entity(key=ds_client.key('Visit'))
    entity.update({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })
    ds_client.put(entity)

def fetch_visits(limit):
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    return query.fetch(limit=limit)

با مهاجرت به Firestore، خواهید دید که اسناد جدیدی مشابه entityها ایجاد می‌شوند و کوئری‌ها همانطور که قبلاً نشان داده شد، کار می‌کنند.

  • بعد از:
def store_visit(remote_addr, user_agent):
    doc_ref = fs_client.collection('Visit')
    doc_ref.add({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })

def fetch_visits(limit):
    visits_ref = fs_client.collection('Visit')
    visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
            direction=firestore.Query.DESCENDING).limit(limit).stream())
    return visits

تابع اصلی root() همانند فایل الگوی index.html باقی می‌ماند. تغییرات خود را دوباره بررسی کنید، ذخیره کنید، پیاده‌سازی کنید و تأیید کنید.

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

استقرار برنامه

برنامه خود را با استفاده از gcloud app deploy دوباره مستقر کنید و تأیید کنید که برنامه کار می‌کند. اکنون کد شما باید با آنچه در مخزن ماژول ۶ (یا نسخه ۲.x در صورت تمایل) وجود دارد، مطابقت داشته باشد.

اگر بدون انجام هیچ یک از آزمایش‌های کد قبلی وارد این مجموعه شده باشید، خود برنامه تغییری نمی‌کند؛ تمام بازدیدها از صفحه وب اصلی ( / ) را ثبت می‌کند و پس از بازدید کافی از سایت، به این شکل درمی‌آید:

اپلیکیشن ویزیت می

تبریک بابت تکمیل این انتقال اختیاری ماژول ۶. این احتمالاً یکی از، اگر نگوییم آخرین، انتقال‌هایی است که می‌توانید در مورد ذخیره‌سازی داده‌های App Engine انجام دهید. یک انتقال جایگزین که می‌توانید در نظر بگیرید، کانتینری کردن برنامه‌تان برای Cloud Run است، اگر قبلاً این کار را نکرده‌اید (به ماژول‌های ۴ و ۵، codelabs که در زیر لینک شده‌اند مراجعه کنید).

اختیاری: تمیز کردن

در مورد پاکسازی برای جلوگیری از پرداخت هزینه تا زمانی که آماده انتقال به آزمایشگاه کد مهاجرت بعدی باشید، چطور؟ به عنوان توسعه‌دهندگان فعلی، احتمالاً از قبل از اطلاعات قیمت‌گذاری App Engine مطلع هستید.

اختیاری: غیرفعال کردن برنامه

اگر هنوز آماده رفتن به آموزش بعدی نیستید، برنامه خود را غیرفعال کنید تا از پرداخت هزینه جلوگیری شود. وقتی آماده رفتن به آزمایشگاه کد بعدی شدید، می‌توانید دوباره آن را فعال کنید. در حالی که برنامه شما غیرفعال است، هیچ ترافیکی دریافت نمی‌کند که هزینه‌ای داشته باشد، با این حال مورد دیگری که ممکن است برای آن هزینه دریافت کنید، استفاده از Firestore شما در صورت تجاوز از سهمیه رایگان است، بنابراین به اندازه‌ای حذف کنید که زیر آن محدودیت قرار گیرد.

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

مراحل بعدی

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

  • ماژول 7: صف‌های وظیفه Push Engine App (در صورت استفاده از صف‌های وظیفه [push] الزامی است)
    • وظایف ارسالی صف taskqueue موتور برنامه را به ماژول ۱ برنامه اضافه می‌کند.
    • کاربران را برای مهاجرت به وظایف ابری در ماژول ۸ آماده می‌کند.
  • ماژول 4: مهاجرت به Cloud Run با Docker
    • برنامه خود را برای اجرا در Cloud Run با Docker کانتینریزه کنید
    • این مهاجرت به شما امکان می‌دهد تا در پایتون ۲ بمانید.
  • ماژول 5: مهاجرت به Cloud Run با Cloud Buildpacks
    • با استفاده از Cloud Buildpacks، برنامه خود را برای اجرا در Cloud Run کانتینرایز کنید
    • لازم نیست چیزی در مورد داکر، کانتینرها یا Dockerfile بدانید.
    • مستلزم آن است که برنامه شما قبلاً به پایتون ۳ مهاجرت کرده باشد (Buildpacks از پایتون ۲ پشتیبانی نمی‌کند)

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

مشکلات/بازخورد ماژول مهاجرت موتور برنامه در codelabs

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

منابع مهاجرت

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

کدلب

پایتون ۲

پایتون ۳

ماژول ۳

( کد )

کد

ماژول ۶

(نامشخص)

کد

منابع موتور برنامه

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