۱. مرور کلی
مجموعه آزمایشگاههای کد Serverless Migration Station (آموزشهای عملی و خودآموز) و ویدیوهای مرتبط با آن ، با هدف کمک به توسعهدهندگان Google Cloud serverless برای مدرنسازی برنامههایشان، با راهنمایی آنها در طول یک یا چند مهاجرت، و در درجه اول دور شدن از سرویسهای قدیمی، ارائه میشوند. انجام این کار، برنامههای شما را قابل حملتر میکند و گزینهها و انعطافپذیری بیشتری به شما میدهد و شما را قادر میسازد تا با طیف وسیعتری از محصولات Cloud ادغام شده و به آنها دسترسی داشته باشید و به راحتی به نسخههای جدیدتر زبان ارتقا دهید. در حالی که در ابتدا بر روی اولین کاربران Cloud، در درجه اول توسعهدهندگان App Engine (محیط استاندارد)، تمرکز دارد، این مجموعه به اندازه کافی گسترده است که شامل سایر پلتفرمهای serverless مانند Cloud Functions و Cloud Run یا در صورت لزوم، هر جای دیگری نیز میشود.
این آزمایشگاه کد ماژول ۱۵ توضیح میدهد که چگونه میتوان استفاده blobstore اپ انجین را به برنامه نمونه از ماژول ۰ اضافه کرد. سپس شما آماده خواهید بود تا آن استفاده را در ماژول ۱۶ به فضای ذخیرهسازی ابری منتقل کنید .
یاد خواهید گرفت که چگونه
- استفاده از API/کتابخانهی App Engine Blobstore را اضافه کنید
- ذخیره آپلودهای کاربر در سرویس
blobstore - برای مرحله بعدی مهاجرت به فضای ذخیرهسازی ابری آماده شوید
آنچه نیاز دارید
- یک پروژه پلتفرم ابری گوگل با یک حساب پرداخت فعال GCP
- مهارتهای پایه پایتون
- آشنایی کامل با دستورات رایج لینوکس
- دانش پایه در توسعه و استقرار برنامههای App Engine
- یک برنامهی ماژول ۰ موتور برنامه که کار میکند (از مخزن دریافت کنید)
نظرسنجی
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را با پایتون چگونه ارزیابی میکنید؟
تجربه خود را در استفاده از خدمات ابری گوگل چگونه ارزیابی میکنید؟
۲. پیشینه
برای مهاجرت از API اپ انجین Blobstore، نحوهی استفاده از آن را به برنامهی پایهی اپ انجین ndb موجود از ماژول ۰ اضافه کنید. برنامهی نمونه، ده بازدید اخیر کاربر را نمایش میدهد. ما برنامه را طوری تغییر میدهیم که از کاربر نهایی بخواهد یک فایل (یک فایل) مربوط به «بازدید» خود را آپلود کند. اگر کاربر مایل به انجام این کار نباشد، گزینهی «رد شدن» وجود دارد. صرف نظر از تصمیم کاربر، صفحهی بعدی همان خروجی برنامهی ماژول ۰ (و بسیاری از ماژولهای دیگر در این مجموعه) را ارائه میدهد. با پیادهسازی این ادغام اپ انجین blobstore ، میتوانیم آن را در آزمایشگاه کد بعدی (ماژول ۱۶) به فضای ذخیرهسازی ابری منتقل کنیم.
App Engine دسترسی به سیستمهای قالببندی Django و Jinja2 را فراهم میکند و چیزی که این مثال را متفاوت میکند (علاوه بر اضافه کردن دسترسی Blobstore) این است که در ماژول 15 از Django در ماژول 0 به Jinja2 تغییر میکند. یک گام کلیدی در مدرنسازی برنامههای App Engine، مهاجرت چارچوبهای وب از webapp2 به Flask است. دومی از Jinja2 به عنوان سیستم قالببندی پیشفرض خود استفاده میکند، بنابراین ما با پیادهسازی Jinja2 در حالی که برای دسترسی Blobstore روی webapp2 باقی میمانیم، حرکت در این مسیر را آغاز میکنیم. از آنجایی که Flask به طور پیشفرض از Jinja2 استفاده میکند، این بدان معناست که در ماژول 16 نیازی به تغییر قالب نخواهد بود.
۳. تنظیمات/پیشپردازش
قبل از اینکه به بخش اصلی آموزش برسیم، پروژه خود را راهاندازی کنید، کد را دریافت کنید و برنامه پایه را برای شروع با کد کاری مستقر کنید.
۱. پروژه راهاندازی
اگر قبلاً برنامه ماژول ۰ را مستقر کردهاید، توصیه میکنیم از همان پروژه (و کد) دوباره استفاده کنید. همچنین میتوانید یک پروژه کاملاً جدید ایجاد کنید یا از یک پروژه موجود دیگر دوباره استفاده کنید. مطمئن شوید که پروژه دارای یک حساب صورتحساب فعال است و App Engine فعال است.
۲. نمونه برنامه پایه را دریافت کنید
یکی از پیشنیازهای این آزمایشگاه کد، داشتن یک نمونه برنامه ماژول ۰ است که کار کند. اگر آن را ندارید، میتوانید آن را از پوشه "START" ماژول ۰ (لینک زیر) دریافت کنید. این آزمایشگاه کد، شما را در هر مرحله راهنمایی میکند و در پایان، کدی مشابه آنچه در پوشه "FINISH" ماژول ۱۵ وجود دارد، ارائه میدهد.
- شروع: پوشه ماژول ۰ (پایتون ۲)
- پایان: پوشه ماژول ۱۵ (پایتون ۲)
- کل مخزن (برای کلون کردن یا دانلود فایل زیپ )
دایرکتوری فایلهای شروع ماژول ۰ باید به این شکل باشد:
$ ls README.md index.html app.yaml main.py
۳. (دوباره) استقرار برنامه پایه
مراحل مقدماتی باقی مانده برای اجرا:
- با ابزار خط فرمان
gcloudدوباره آشنا شوید - برنامه نمونه را با استفاده از
gcloud app deployدوباره مستقر کنید - تأیید کنید که برنامه بدون مشکل در App Engine اجرا میشود.
زمانی که این مراحل را با موفقیت انجام دادید و دیدید که برنامه وب شما کار میکند (با خروجی مشابه زیر)، آمادهاید تا از قابلیت ذخیرهسازی موقت (caching) به برنامه خود اضافه کنید.

۴. بهروزرسانی فایلهای پیکربندی
برنامه.yaml
هیچ تغییر اساسی در پیکربندی برنامه ایجاد نشده است، با این حال همانطور که قبلاً ذکر شد، ما از قالببندی جنگو (پیشفرض) به Jinja2 منتقل میشویم، بنابراین برای تغییر، کاربران باید آخرین نسخه Jinja2 موجود در سرورهای App Engine را مشخص کنند و شما این کار را با اضافه کردن آن به بخش کتابخانههای شخص ثالث داخلی app.yaml انجام میدهید.
قبل از:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
فایل app.yaml خود را با اضافه کردن یک بخش جدید libraries مانند آنچه در اینجا میبینید، ویرایش کنید:
بعد از:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
هیچ فایل پیکربندی دیگری نیاز به بهروزرسانی ندارد، بنابراین بیایید به سراغ فایلهای برنامه برویم.
۵. فایلهای برنامه را تغییر دهید
واردات و پشتیبانی از Jinja2
اولین مجموعه تغییرات برای main.py شامل اضافه شدن استفاده از API Blobstore و جایگزینی قالببندی Django با Jinja2 است. در اینجا مواردی که تغییر میکنند را مشاهده میکنید:
- هدف ماژول
osایجاد یک نام مسیر فایل به یک الگوی جنگو است. از آنجایی که ما در حال انتقال به Jinja2 هستیم که این کار را انجام میدهد، استفاده ازosو همچنین رندرکننده الگوی جنگو،google.appengine.ext.webapp.template، دیگر مورد نیاز نیستند، بنابراین آنها حذف میشوند. - API مربوط به Blobstore را وارد کنید:
google.appengine.ext.blobstore - هندلرهای Blobstore موجود در چارچوب اصلی
webappرا وارد کنید - آنها درwebapp2در دسترس نیستند:google.appengine.ext.webapp.blobstore_handlers - پشتیبانی Jinja2 را از بسته
webapp2_extrasوارد کنید
قبل از:
import os
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
تغییرات لیست بالا را با جایگزینی بخش import فعلی در main.py با قطعه کد زیر پیادهسازی کنید.
بعد از:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
پس از ایمپورتها، کد تکراری برای پشتیبانی از استفاده از Jinja2، همانطور که در مستندات webapp2_extras تعریف شده است، اضافه کنید. قطعه کد زیر، کلاس استاندارد مدیریت درخواست webapp2 را با قابلیت Jinja2 در بر میگیرد، بنابراین این بلوک کد را درست پس از ایمپورتها به main.py اضافه کنید:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
پشتیبانی Blobstore را اضافه کنید
برخلاف سایر مهاجرتهای این مجموعه که در آنها عملکرد یا خروجی برنامه نمونه را بدون تغییر (زیاد) در تجربه کاربری، یکسان (یا تقریباً یکسان) نگه میداریم، این مثال، انحراف اساسیتری از روال معمول دارد. به جای اینکه بلافاصله یک بازدید جدید ثبت شود و سپس ده بازدید اخیر نمایش داده شود، برنامه را بهروزرسانی میکنیم تا از کاربر یک فایل مصنوعی برای ثبت بازدید خود درخواست کند. سپس کاربران نهایی میتوانند فایل مربوطه را آپلود کنند یا با انتخاب گزینه «رد شدن» هیچ چیزی آپلود نکنند. پس از اتمام این مرحله، صفحه «آخرین بازدیدها» نمایش داده میشود.
این تغییر به برنامه ما اجازه میدهد تا از سرویس Blobstore برای ذخیره (و احتمالاً رندر بعدی) آن تصویر یا نوع فایل دیگر در صفحه جدیدترین بازدیدها استفاده کند.
بهروزرسانی مدل داده و پیادهسازی کاربرد آن
ما در حال ذخیره دادههای بیشتر هستیم، به طور خاص مدل داده را برای ذخیره شناسه (به نام " BlobKey ") فایل آپلود شده در Blobstore بهروزرسانی میکنیم و یک مرجع برای ذخیره آن در store_visit() اضافه میکنیم. از آنجایی که این دادههای اضافی به همراه هر چیز دیگری هنگام جستجو بازگردانده میشوند، fetch_visits() ثابت میماند.
در اینجا قبل و بعد از این بهروزرسانیها با file_blob و ndb.BlobKeyProperty آمده است:
قبل از:
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'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
بعد از:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
در اینجا تصویری از تغییراتی که تاکنون ایجاد شده است را مشاهده میکنید:

پشتیبانی از آپلود فایل
مهمترین تغییر در عملکرد، پشتیبانی از آپلود فایل است، چه از طریق درخواست فایل از کاربر، پشتیبانی از ویژگی «رد شدن» یا رندر کردن فایلی مربوط به یک بازدید. همه اینها بخشی از تصویر است. اینها تغییراتی هستند که برای پشتیبانی از آپلود فایل مورد نیاز هستند:
- درخواست
GETکه کنترلکنندهی اصلی است، دیگر آخرین بازدیدها را برای نمایش دریافت نمیکند. در عوض، از کاربر میخواهد که یک فایل را آپلود کند. - وقتی کاربر نهایی فایلی را برای آپلود ارسال میکند یا از آن فرآیند صرف نظر میکند، یک
POSTاز فرم، کنترل را بهUploadHandlerجدید که ازgoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandlerمشتق شده است، منتقل میکند. - متد
POSTمربوط بهUploadHandlerعمل آپلود را انجام میدهد، تابعstore_visit()را برای ثبت بازدید فراخوانی میکند و یک ریدایرکت HTTP 307 را برای ارسال کاربر به "/" فعال میکند، جایی که... - متد
POSTکنترلکنندهی اصلی، (از طریقfetch_visits()) درخواستهایی برای آخرین بازدیدها ارسال میکند و آنها را نمایش میدهد. اگر کاربر گزینهی «رد شدن» را انتخاب کند، هیچ فایلی آپلود نمیشود، اما بازدید همچنان ثبت شده و به دنبال آن همان تغییر مسیر (ریدایرکت) انجام میشود. - نمایش آخرین بازدیدها شامل یک فیلد جدید است که به کاربر نمایش داده میشود، که اگر فایل آپلودی موجود باشد، به صورت «مشاهده» و در غیر این صورت به صورت «هیچ فایلی» نمایش داده میشود. این تغییرات در قالب HTML به همراه فرم آپلود اعمال میشوند (به زودی در این مورد بیشتر توضیح داده خواهد شد).
- اگر کاربر نهایی برای هر بازدیدی که حاوی ویدیوی آپلود شده است، روی لینک «مشاهده» کلیک کند، یک درخواست
GETبه یکViewBlobHandlerجدید، مشتق شده ازgoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler، ارسال میکند که یا در صورت پشتیبانی مرورگر، فایل را رندر میکند، در غیر این صورت درخواست دانلود میدهد، یا در صورت عدم یافتن، خطای HTTP 404 را برمیگرداند. - علاوه بر جفت کلاسهای جدید هندلر و همچنین یک جفت مسیر جدید برای ارسال ترافیک به آنها، هندلر اصلی به یک متد
POSTجدید برای دریافت ریدایرکت 307 که در بالا توضیح داده شد، نیاز دارد.
قبل از این بهروزرسانیها، برنامه ماژول ۰ فقط یک هندلر اصلی با متد GET و یک مسیر واحد داشت:
قبل از:
class MainHandler(webapp2.RequestHandler):
'main application (GET) handler'
def get(self):
store_visit(self.request.remote_addr, self.request.user_agent)
visits = fetch_visits(10)
tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(tmpl, {'visits': visits}))
app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
با پیادهسازی این بهروزرسانیها، اکنون سه هندلر وجود دارد: ۱) هندلر آپلود با متد POST ، ۲) یک هندلر دانلود "view blob" با متد GET ، و ۳) هندلر اصلی با متدهای GET و POST . این تغییرات را اعمال کنید تا بقیه برنامه شما اکنون مانند تصویر زیر باشد.
بعد از:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
چندین فراخوانی کلید در این کدی که اضافه کردیم وجود دارد:
- در
MainHandler.get، فراخوانی برایblobstore.create_upload_urlوجود دارد. این فراخوانی، URL را از طریقPOSTتولید میکند و کنترلکننده آپلود را برای ارسال فایل به Blobstore فراخوانی میکند. - در
UploadHandler.post، فراخوانی برایblobstore_handlers.BlobstoreUploadHandler.get_uploadsوجود دارد. این جادوی واقعی است که فایل را در Blobstore قرار میدهد و یک شناسه منحصر به فرد و پایدار برای آن فایل، یعنیBlobKey، برمیگرداند. - در
ViewBlobHandler.get، فراخوانیblobstore_handlers.BlobstoreDownloadHandler.sendبه همراهBlobKeyیک فایل، منجر به واکشی فایل و ارسال آن به مرورگر کاربر نهایی میشود.
این فراخوانیها نشاندهندهی بخش عمدهی دسترسی به ویژگیهای اضافه شده به برنامه هستند. در اینجا یک نمایش تصویری از این مجموعهی دوم و نهایی تغییرات در main.py آورده شده است:

قالب HTML را بهروزرسانی کنید
برخی از بهروزرسانیهای برنامه اصلی، رابط کاربری (UI) برنامه را تحت تأثیر قرار میدهند، بنابراین تغییرات مربوطه در قالب وب مورد نیاز است، در واقع دو مورد:
- یک فرم آپلود فایل با ۳ عنصر ورودی مورد نیاز است: یک فایل و یک جفت دکمه ارسال برای آپلود فایل و رد کردن آن.
- خروجی آخرین بازدیدها را با اضافه کردن پیوند «مشاهده» برای بازدیدهایی که فایل مربوطه آپلود شده است یا در غیر این صورت «هیچکدام» بهروزرسانی کنید.
قبل از:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
</body>
</html>
تغییرات لیست بالا را طوری پیادهسازی کنید که شامل الگوی بهروزرسانیشده باشد:
بعد از:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
{% if upload_url %}
<h3>Welcome... upload a file? (optional)</h3>
<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><p></p>
<input type="submit"> <input type="submit" value="Skip">
</form>
{% else %}
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }}
<i><code>
{% if visit.file_blob %}
(<a href="/view/{{ visit.file_blob }}" target="_blank">view</a>)
{% else %}
(none)
{% endif %}
</code></i>
from {{ visit.visitor }}
</li>
{% endfor %}
</ul>
{% endif %}
</body>
</html>
این تصویر بهروزرسانیهای مورد نیاز برای index.html را نشان میدهد:

یک تغییر نهایی این است که Jinja2 قالبهای خود را در پوشه templates ترجیح میدهد، بنابراین آن پوشه را ایجاد کنید و index.html را به داخل آن منتقل کنید. با این حرکت نهایی، اکنون تمام تغییرات لازم برای افزودن استفاده از Blobstore به برنامه نمونه Module 0 انجام شده است.
(اختیاری) "بهبود" فضای ذخیرهسازی ابری
ذخیرهسازی Blobstore در نهایت به خود Cloud Storage تبدیل شد. این بدان معناست که آپلودهای Blobstore در کنسول Cloud، به ویژه مرورگر Cloud Storage، قابل مشاهده هستند. سوال این است که کجا. پاسخ، مخزن ذخیرهسازی ابری پیشفرض برنامه App Engine شماست. نام آن، نام دامنه کامل برنامه App Engine شما، PROJECT_ID .appspot.com ، است. این خیلی راحت است زیرا همه شناسههای پروژه منحصر به فرد هستند، درست است؟
بهروزرسانیهای انجامشده در برنامهی نمونه، فایلهای آپلود شده را در آن سطل قرار میدهند، اما توسعهدهندگان میتوانند مکان خاصتری را انتخاب کنند. سطل پیشفرض از طریق google.appengine.api.app_identity.get_default_gcs_bucket_name() به صورت برنامهنویسی قابل دسترسی است و اگر میخواهید به این مقدار دسترسی داشته باشید، مثلاً برای استفاده به عنوان پیشوند برای سازماندهی فایلهای آپلود شده، نیاز به وارد کردن جدید دارد. به عنوان مثال، مرتبسازی بر اساس نوع فایل:

برای پیادهسازی چیزی شبیه به این برای تصاویر، به عنوان مثال، کدی مانند این به همراه کدی خواهید داشت که انواع فایلها را بررسی میکند تا نام سطل مورد نظر را انتخاب کند:
ROOT_BUCKET = app_identity.get_default_gcs_bucket_name()
IMAGE_BUCKET = '%s/%s' % (ROOT_BUCKET, 'images')
همچنین میتوانید تصاویر آپلود شده را با استفاده از ابزاری مانند ماژول imghdr کتابخانه استاندارد پایتون، برای تأیید نوع تصویر، اعتبارسنجی کنید. در نهایت، احتمالاً میخواهید اندازه فایلهای آپلود شده را در صورت وجود عوامل مخرب محدود کنید .
بیایید فرض کنیم همه کارها انجام شده است. چگونه میتوانیم برنامه خود را بهروزرسانی کنیم تا از مشخص کردن محل ذخیره فایلهای آپلود شده پشتیبانی کند؟ نکته کلیدی این است که فراخوانی blobstore.create_upload_url در MainHandler.get را تغییر دهیم تا با اضافه کردن پارامتر gs_bucket_name به این شکل، مکان مورد نظر در Cloud Storage برای آپلود مشخص شود:
blobstore.create_upload_url('/upload', gs_bucket_name=IMAGE_BUCKET))
از آنجایی که اگر میخواهید مشخص کنید آپلودها کجا بروند، این یک بهروزرسانی اختیاری است، بنابراین بخشی از فایل main.py در مخزن نیست. در عوض، جایگزینی به نام main-gcs.py برای بررسی شما در مخزن موجود است. به جای استفاده از یک "پوشه" جداگانه برای سطل، کد موجود در main-gcs.py ، آپلودها را در سطل "ریشه" ( PROJECT_ID .appspot.com ) درست مانند main.py ذخیره میکند، اما چارچوبی را که اگر بخواهید نمونه را به چیزی بیشتر، همانطور که در این بخش اشاره شد، استخراج کنید، نیاز دارید، فراهم میکند. در زیر تصویری از "تفاوتها" بین main.py و main-gcs.py آمده است.

۶. خلاصه/پاکسازی
این بخش، این آزمایشگاه کد را با استقرار برنامه، تأیید عملکرد آن طبق برنامه و در هر خروجی منعکسشده، به پایان میرساند. پس از اعتبارسنجی برنامه، مراحل پاکسازی را انجام داده و مراحل بعدی را در نظر بگیرید.
استقرار و تأیید برنامه
برنامه خود را با استفاده از gcloud app deploy دوباره مستقر کنید و تأیید کنید که برنامه همانطور که تبلیغ شده کار میکند، و از نظر تجربه کاربری (UX) با برنامه Module 0 متفاوت است. اکنون دو صفحه مختلف در برنامه شما وجود دارد که اولین آنها فرم آپلود فایل بازدید است:
از آنجا، کاربران نهایی یا فایلی را آپلود میکنند و روی «ارسال» کلیک میکنند یا روی «رد شدن» کلیک میکنند تا چیزی آپلود نشود. در هر دو حالت، نتیجه آخرین صفحه بازدید است که اکنون با پیوندهای «مشاهده» یا «هیچ» بین مهرهای زمانی بازدید و اطلاعات بازدیدکننده تکمیل شده است:

تبریک میگویم که این آزمایشگاه کدنویسی را با اضافه کردن استفاده از App Engine Blobstore به برنامه نمونه ماژول 0 به پایان رساندید. اکنون کد شما باید با آنچه در پوشه FINISH (ماژول 15) است مطابقت داشته باشد. فایل جایگزین main-gcs.py نیز در آن پوشه موجود است.
تمیز کردن
عمومی
اگر فعلاً کارتان تمام است، توصیه میکنیم برنامه 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 هستند. برای اطلاعات بیشتر به مستندات هر محصول مراجعه کنید:
- سرویس App Engine Blobstore در بخش سهمیهها و محدودیتهای دادههای ذخیرهشده قرار میگیرد، بنابراین آن را به همراه صفحه قیمتگذاری سرویسهای قدیمی همراه آن بررسی کنید.
- سرویس App Engine Datastore توسط Cloud Datastore (Cloud Firestore در حالت Datastore) ارائه میشود که یک نسخه رایگان نیز دارد؛ برای اطلاعات بیشتر به صفحه قیمتگذاری آن مراجعه کنید.
مراحل بعدی
مهاجرت منطقی بعدی که باید در نظر گرفته شود، در ماژول ۱۶ پوشش داده شده است و به توسعهدهندگان نشان میدهد که چگونه از سرویس App Engine Blobstore به استفاده از کتابخانه کلاینت Cloud Storage مهاجرت کنند. مزایای ارتقا شامل دسترسی به ویژگیهای بیشتر Cloud Storage، آشنایی با یک کتابخانه کلاینت است که برای برنامههای خارج از App Engine، چه در Google Cloud، چه در سایر Cloudها یا حتی در محل کار، کار میکند. اگر احساس نمیکنید که به تمام ویژگیهای موجود در Cloud Storage نیاز دارید یا نگران تأثیرات آن بر هزینه هستید، میتوانید در App Engine Blobstore بمانید.
فراتر از ماژول ۱۶، مجموعهای کامل از مهاجرتهای ممکن دیگر مانند Cloud NDB و Cloud Datastore، Cloud Tasks یا Cloud Memorystore وجود دارد. همچنین مهاجرتهای بین محصولی به Cloud Run و Cloud Functions نیز وجود دارد. مخزن مهاجرت شامل تمام نمونههای کد است، شما را به تمام آزمایشگاههای کد و ویدیوهای موجود پیوند میدهد و همچنین راهنماییهایی در مورد اینکه کدام مهاجرتها را باید در نظر بگیرید و هرگونه "ترتیب" مربوط به مهاجرتها ارائه میدهد.
۷. منابع اضافی
مشکلات/بازخوردهای Codelab
اگر در این آزمایشگاه کد مشکلی پیدا کردید، لطفاً قبل از ثبت، ابتدا مشکل خود را جستجو کنید. لینکهای جستجو و ایجاد مشکلات جدید:
منابع مهاجرت
لینکهای پوشههای مخزن ماژول ۰ (START) و ماژول ۱۵ (FINISH) را میتوانید در جدول زیر پیدا کنید. همچنین میتوانید از مخزن تمام مهاجرتهای Codelab مربوط به App Engine که میتوانید آنها را کلون کنید یا یک فایل ZIP دانلود کنید، به آنها دسترسی داشته باشید.
کدلب | پایتون ۲ | پایتون ۳ |
ماژول 0 | ناموجود | |
ماژول ۱۵ (این آزمایشگاه کد) | ناموجود |
منابع آنلاین
در زیر منابع آنلاینی وجود دارد که ممکن است برای این آموزش مرتبط باشند:
موتور برنامه
- سرویس اپ انجین بلاباستور
- سهمیهها و محدودیتهای دادههای ذخیرهشده در موتور برنامه
- مستندات موتور برنامه
- موتور برنامه پایتون ۲ (محیط استاندارد) در زمان اجرا
- استفاده از کتابخانههای داخلی App Engine در Python 2 App Engine
- اطلاعات قیمتگذاری و سهمیهبندی موتور برنامه
- راهاندازی پلتفرم نسل دوم App Engine (۲۰۱۸)
- مقایسه پلتفرمهای نسل اول و دوم
- پشتیبانی بلندمدت از رانتایمهای قدیمی
- مخزن نمونههای مهاجرت مستندات
- مخزن نمونههای مهاجرت ارائه شده توسط جامعه
گوگل کلود
- پایتون در پلتفرم ابری گوگل
- کتابخانههای کلاینت پایتون گوگل کلود
- سطح «همیشه رایگان» گوگل کلود
- کیت توسعه نرمافزار گوگل کلود (ابزار خط فرمان gcloud)
- تمام مستندات گوگل کلود
پایتون
- سیستمهای قالببندی جنگو و جینجا۲
- چارچوب وب
webapp2 - مستندات
webapp2 - پیوندهای
webapp2_extras - مستندات
webapp2_extrasدر Jinja2
ویدیوها
- ایستگاه مهاجرت بدون سرور
- سفرهای اکتشافی بدون سرور
- مشترک شدن در فناوری ابری گوگل
- مشترک شدن در توسعهدهندگان گوگل
مجوز
این اثر تحت مجوز عمومی Creative Commons Attribution 2.0 منتشر شده است.