1. Tổng quan
Loạt lớp học lập trình Serverless Migration Station (hướng dẫn thực hành, tự học) và các video có liên quan nhằm giúp các nhà phát triển không máy chủ của Google Cloud hiện đại hoá ứng dụng của họ bằng cách hướng dẫn họ thực hiện một hoặc nhiều quá trình di chuyển, chủ yếu là chuyển khỏi các dịch vụ cũ. Việc này giúp ứng dụng của bạn dễ di chuyển hơn, đồng thời mang đến cho bạn nhiều lựa chọn và tính linh hoạt hơn, cho phép bạn tích hợp và truy cập vào nhiều sản phẩm Cloud hơn, cũng như dễ dàng nâng cấp lên các bản phát hành ngôn ngữ mới hơn. Mặc dù ban đầu tập trung vào những người dùng Cloud sớm nhất, chủ yếu là các nhà phát triển App Engine (môi trường tiêu chuẩn), nhưng loạt bài này đủ rộng để bao gồm các nền tảng không máy chủ khác như Cloud Functions và Cloud Run hoặc các nền tảng khác nếu có.
Lớp học lập trình Mô-đun 15 này giải thích cách thêm cách sử dụng blobstore của App Engine vào ứng dụng mẫu từ Mô-đun 0. Sau đó, bạn sẽ sẵn sàng di chuyển dữ liệu sử dụng đó sang Cloud Storage trong Học phần 16.
Bạn sẽ tìm hiểu cách
- Thêm cách sử dụng API/thư viện App Engine Blobstore
- Lưu trữ nội dung tải lên của người dùng vào dịch vụ
blobstore - Chuẩn bị cho bước tiếp theo để di chuyển sang Cloud Storage
Bạn cần có
- Một dự án Google Cloud Platform có tài khoản thanh toán GCP đang hoạt động
- Kỹ năng Python cơ bản
- Kiến thức thực tế về các lệnh Linux phổ biến
- Kiến thức cơ bản về cách phát triển và triển khai ứng dụng App Engine
- Một ứng dụng App Engine Mô-đun 0 đang hoạt động (lấy từ kho lưu trữ)
Bản khảo sát
Bạn sẽ sử dụng hướng dẫn này như thế nào?
Bạn đánh giá thế nào về trải nghiệm của mình với Python?
Bạn đánh giá thế nào về trải nghiệm sử dụng các dịch vụ của Google Cloud?
2. Thông tin cơ bản
Để di chuyển từ API Blobstore của App Engine, hãy thêm cách sử dụng API này vào ứng dụng ndb App Engine cơ sở hiện có trong Mô-đun 0. Ứng dụng mẫu hiển thị 10 lượt truy cập gần đây nhất cho người dùng. Chúng tôi đang sửa đổi ứng dụng để nhắc người dùng cuối tải một cấu phần phần mềm (tệp) lên tương ứng với "lượt truy cập" của họ. Nếu người dùng không muốn làm như vậy, họ có thể chọn "bỏ qua". Bất kể quyết định của người dùng là gì, trang tiếp theo sẽ hiển thị kết quả giống như ứng dụng trong Mô-đun 0 (và nhiều mô-đun khác trong loạt bài này). Sau khi triển khai tính năng tích hợp blobstore của App Engine, chúng ta có thể di chuyển tính năng này sang Cloud Storage trong lớp học lập trình tiếp theo (Mô-đun 16).
App Engine cung cấp quyền truy cập vào hệ thống tạo mẫu Django và Jinja2. Một điểm khác biệt của ví dụ này (ngoài việc thêm quyền truy cập vào Blobstore) là chuyển từ việc sử dụng Django trong Mô-đun 0 sang Jinja2 trong Mô-đun 15. Một bước quan trọng trong việc hiện đại hoá ứng dụng App Engine là di chuyển khung web từ webapp2 sang Flask. Python 3 sử dụng Jinja2 làm hệ thống tạo mẫu mặc định, vì vậy, chúng tôi bắt đầu chuyển sang hướng đó bằng cách triển khai Jinja2 trong khi vẫn sử dụng webapp2 để truy cập Blobstore. Vì Flask sử dụng Jinja2 theo mặc định, nên bạn không cần thay đổi mẫu trong Học phần 16.
3. Thiết lập/Chuẩn bị
Trước khi chuyển sang phần chính của hướng dẫn, hãy thiết lập dự án, lấy mã và triển khai ứng dụng cơ sở để bắt đầu với mã hoạt động.
1. Thiết lập dự án
Nếu đã triển khai ứng dụng của Mô-đun 0, bạn nên sử dụng lại cùng một dự án (và mã). Ngoài ra, bạn có thể tạo một dự án hoàn toàn mới hoặc sử dụng lại một dự án hiện có khác. Đảm bảo dự án có tài khoản thanh toán đang hoạt động và App Engine được bật.
2. Tải ứng dụng mẫu cơ sở
Một trong những điều kiện tiên quyết của lớp học lập trình này là bạn phải có một ứng dụng mẫu đang hoạt động của Mô-đun 0. Nếu chưa có, bạn có thể lấy ứng dụng này từ thư mục "START" (BẮT ĐẦU) của Mô-đun 0 (đường liên kết bên dưới). Lớp học lập trình này sẽ hướng dẫn bạn từng bước, kết thúc bằng mã tương tự như mã trong thư mục "FINISH" (HOÀN THÀNH) của Mô-đun 15.
- BẮT ĐẦU: Thư mục Mô-đun 0 (Python 2)
- KẾT THÚC: Thư mục Mô-đun 15 (Python 2)
- Toàn bộ kho lưu trữ (để sao chép hoặc tải tệp ZIP xuống)
Thư mục của các tệp START trong Học phần 0 sẽ có dạng như sau:
$ ls README.md index.html app.yaml main.py
3. Triển khai (lại) ứng dụng cơ sở
Các bước chuẩn bị còn lại mà bạn cần thực hiện ngay:
- Làm quen lại với công cụ dòng lệnh
gcloud - Triển khai lại ứng dụng mẫu bằng
gcloud app deploy - Xác nhận ứng dụng chạy trên App Engine mà không gặp vấn đề
Sau khi thực hiện thành công các bước đó và thấy ứng dụng web của mình hoạt động (với kết quả tương tự như bên dưới), bạn đã sẵn sàng thêm tính năng lưu vào bộ nhớ đệm vào ứng dụng của mình.

4. Cập nhật tệp cấu hình
app.yaml
Không có thay đổi quan trọng nào đối với cấu hình ứng dụng, tuy nhiên, như đã đề cập trước đó, chúng tôi sẽ chuyển từ mẫu Django (mặc định) sang Jinja2. Vì vậy, để chuyển đổi, người dùng nên chỉ định phiên bản mới nhất của Jinja2 hiện có trên máy chủ App Engine và bạn thực hiện việc này bằng cách thêm phiên bản đó vào phần thư viện tích hợp sẵn của bên thứ ba trong app.yaml.
TRƯỚC:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Chỉnh sửa tệp app.yaml bằng cách thêm một phần libraries mới như bạn thấy ở đây:
SAU:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
Không cần cập nhật tệp cấu hình nào khác, vì vậy, hãy chuyển sang tệp ứng dụng.
5. Sửa đổi tệp ứng dụng
Hỗ trợ nhập và Jinja2
Tập hợp thay đổi đầu tiên cho main.py bao gồm việc thêm cách sử dụng Blobstore API và thay thế mẫu Django bằng Jinja2. Sau đây là những thay đổi:
- Mục đích của mô-đun
oslà tạo tên đường dẫn tệp cho mẫu Django. Vì chúng ta đang chuyển sang Jinja2 (nơi xử lý việc này), nên không cần sử dụngoscũng như trình kết xuất mẫu Djangogoogle.appengine.ext.webapp.templatenữa, vì vậy, chúng sẽ bị xoá. - Nhập Blobstore API:
google.appengine.ext.blobstore - Nhập trình xử lý Blobstore có trong khung
webappban đầu – các trình xử lý này không có trongwebapp2:google.appengine.ext.webapp.blobstore_handlers - Nhập tính năng hỗ trợ Jinja2 từ gói
webapp2_extras
TRƯỚC:
import os
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
Triển khai các thay đổi trong danh sách trên bằng cách thay thế phần nhập hiện tại trong main.py bằng đoạn mã dưới đây.
SAU:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Sau khi nhập, hãy thêm một số mã nguyên mẫu để hỗ trợ việc sử dụng Jinja2 như được xác định trong tài liệu về webapp2_extras. Đoạn mã sau đây gói lớp trình xử lý yêu cầu webapp2 tiêu chuẩn bằng chức năng Jinja2, vì vậy, hãy thêm khối mã này vào main.py ngay sau lệnh nhập:
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))
Thêm tính năng hỗ trợ Blobstore
Không giống như các hoạt động di chuyển khác trong loạt bài này, nơi chúng tôi giữ nguyên chức năng hoặc kết quả của ứng dụng mẫu (hoặc gần như giống nhau) mà không thay đổi (nhiều) đối với trải nghiệm người dùng, ví dụ này có sự khác biệt rõ rệt so với thông thường. Thay vì đăng ký ngay một lượt truy cập mới rồi hiển thị 10 lượt truy cập gần đây nhất, chúng ta sẽ cập nhật ứng dụng để yêu cầu người dùng cung cấp một cấu phần phần mềm tệp để đăng ký lượt truy cập của họ. Sau đó, người dùng cuối có thể tải tệp tương ứng lên hoặc chọn "Bỏ qua" để không tải tệp nào lên. Sau khi hoàn tất bước này, trang "lượt truy cập gần đây nhất" sẽ xuất hiện.
Thay đổi này cho phép ứng dụng của chúng ta sử dụng dịch vụ Blobstore để lưu trữ (và có thể hiển thị sau này) hình ảnh đó hoặc loại tệp khác trên trang lượt truy cập gần đây nhất.
Cập nhật mô hình dữ liệu và triển khai việc sử dụng mô hình đó
Chúng tôi đang lưu trữ thêm dữ liệu, cụ thể là cập nhật mô hình dữ liệu để lưu trữ mã nhận dạng (gọi là "BlobKey") của tệp được tải lên Blobstore và thêm một tệp đối chiếu để lưu tệp đó trong store_visit(). Vì dữ liệu bổ sung này được trả về cùng với mọi dữ liệu khác khi truy vấn, nên fetch_visits() vẫn giữ nguyên.
Sau đây là hình ảnh trước và sau khi áp dụng những điểm cập nhật này, trong đó có file_blob, một ndb.BlobKeyProperty:
TRƯỚC:
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)
SAU:
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)
Sau đây là hình ảnh minh hoạ những thay đổi đã được thực hiện cho đến nay:

Hỗ trợ tải tệp lên
Thay đổi quan trọng nhất về chức năng là hỗ trợ tải tệp lên, cho dù là nhắc người dùng tải tệp lên, hỗ trợ tính năng "bỏ qua" hay hiển thị tệp tương ứng với một lượt truy cập. Tất cả đều là một phần của bức tranh. Sau đây là những thay đổi cần thiết để hỗ trợ việc tải tệp lên:
- Yêu cầu của trình xử lý chính
GETkhông còn tìm nạp các lượt truy cập gần đây nhất để hiển thị. Thay vào đó, ứng dụng sẽ nhắc người dùng tải lên. - Khi người dùng cuối gửi tệp để tải lên hoặc bỏ qua quy trình đó,
POSTtừ biểu mẫu sẽ chuyển quyền kiểm soát sangUploadHandlermới, bắt nguồn từgoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler. - Phương thức
POSTcủaUploadHandlerthực hiện việc tải lên, gọistore_visit()để đăng ký lượt truy cập và kích hoạt lệnh chuyển hướng HTTP 307 để đưa người dùng trở lại "/", nơi... - Phương thức
POSTcủa trình xử lý chính truy vấn (thông quafetch_visits()) và hiển thị các lượt truy cập gần đây nhất. Nếu người dùng chọn "bỏ qua", thì không có tệp nào được tải lên, nhưng lượt truy cập vẫn được đăng ký, sau đó là cùng một lệnh chuyển hướng. - Màn hình hiển thị các lượt truy cập gần đây nhất có một trường mới hiển thị cho người dùng, đó là "xem" có siêu liên kết nếu có tệp tải lên hoặc "không có" nếu không có tệp tải lên. Những thay đổi này được thực hiện trong mẫu HTML cùng với việc bổ sung biểu mẫu tải lên (sẽ sớm có thêm thông tin về biểu mẫu này).
- Nếu người dùng cuối nhấp vào đường liên kết "xem" cho bất kỳ lượt truy cập nào có video đã tải lên, thì thao tác này sẽ gửi một yêu cầu
GETđến mộtViewBlobHandlermới, bắt nguồn từgoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler, hiển thị tệp nếu là hình ảnh (trong trình duyệt nếu được hỗ trợ), nhắc tải xuống nếu không phải hình ảnh hoặc trả về lỗi HTTP 404 nếu không tìm thấy. - Ngoài cặp lớp trình xử lý mới cũng như cặp tuyến mới để gửi lưu lượng truy cập đến các lớp đó, trình xử lý chính cần có một phương thức
POSTmới để nhận lệnh chuyển hướng 307 được mô tả ở trên.
Trước khi cập nhật, ứng dụng Mô-đun 0 chỉ có một trình xử lý chính với phương thức GET và một tuyến duy nhất:
TRƯỚC:
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)
Sau khi triển khai các bản cập nhật đó, giờ đây sẽ có 3 trình xử lý: 1) trình xử lý tải lên bằng phương thức POST, 2) trình xử lý tải xuống "view blob" bằng phương thức GET và 3) trình xử lý chính bằng phương thức GET và POST. Thực hiện những thay đổi này để phần còn lại của ứng dụng trông giống như bên dưới.
SAU:
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)
Có một số lệnh gọi chính trong đoạn mã mà chúng ta vừa thêm:
- Trong
MainHandler.get, có một lệnh gọi đếnblobstore.create_upload_url. Lệnh gọi này tạo URL mà biểu mẫuPOSTđến, gọi trình xử lý tải lên để gửi tệp đến Blobstore. - Trong
UploadHandler.post, có một lệnh gọi đếnblobstore_handlers.BlobstoreUploadHandler.get_uploads. Đây là điều kỳ diệu thực sự giúp đưa tệp vào Blobstore và trả về một mã nhận dạng duy nhất và cố định cho tệp đó, tức làBlobKey. - Trong
ViewBlobHandler.get, việc gọiblobstore_handlers.BlobstoreDownloadHandler.sendbằngBlobKeycủa tệp sẽ dẫn đến việc tìm nạp tệp và chuyển tiếp tệp đó đến trình duyệt của người dùng cuối
Những lệnh gọi này đại diện cho phần lớn quyền truy cập vào các tính năng được thêm vào ứng dụng. Sau đây là hình ảnh minh hoạ cho nhóm thay đổi thứ hai và cũng là nhóm thay đổi cuối cùng đối với main.py:

Cập nhật mẫu HTML
Một số nội dung cập nhật cho ứng dụng chính ảnh hưởng đến giao diện người dùng (UI) của ứng dụng, vì vậy, bạn cần thực hiện các thay đổi tương ứng trong mẫu web, cụ thể là hai thay đổi:
- Bạn cần có một biểu mẫu tải tệp lên với 3 phần tử nhập: một tệp và một cặp nút gửi để tải tệp lên và bỏ qua.
- Cập nhật kết quả của các lượt truy cập gần đây nhất bằng cách thêm đường liên kết "xem" cho các lượt truy cập có tệp tải lên tương ứng hoặc "không có" nếu không có tệp tải lên.
TRƯỚC:
<!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>
Triển khai các thay đổi trong danh sách ở trên để tạo mẫu mới:
SAU:
<!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>
Hình ảnh này minh hoạ những nội dung cập nhật bắt buộc đối với index.html:

Thay đổi cuối cùng là Jinja2 ưu tiên các mẫu trong thư mục templates, vì vậy, hãy tạo thư mục đó và di chuyển index.html vào trong thư mục đó. Với bước cuối cùng này, bạn đã hoàn tất mọi thay đổi cần thiết để thêm việc sử dụng Blobstore vào ứng dụng mẫu của Mô-đun 0.
(không bắt buộc) "Cải tiến" Cloud Storage
Bộ nhớ Blobstore cuối cùng đã phát triển thành Cloud Storage. Điều này có nghĩa là các tệp tải lên Blobstore sẽ xuất hiện trong Cloud Console, cụ thể là trình duyệt Cloud Storage. Câu hỏi là ở đâu. Câu trả lời là bộ chứa Cloud Storage mặc định của ứng dụng App Engine. Tên của bộ chứa này là tên miền đầy đủ của ứng dụng App Engine, PROJECT_ID.appspot.com. Điều này rất thuận tiện vì tất cả mã dự án đều là duy nhất, đúng không?
Nội dung cập nhật cho ứng dụng mẫu sẽ thả các tệp đã tải lên vào bộ chứa đó, nhưng nhà phát triển có thể chọn một vị trí cụ thể hơn. Bạn có thể truy cập vào bộ chứa mặc định theo phương thức lập trình thông qua google.appengine.api.app_identity.get_default_gcs_bucket_name(). Bạn cần nhập một giá trị mới nếu muốn truy cập vào giá trị này, chẳng hạn như để sử dụng làm tiền tố cho việc sắp xếp các tệp đã tải lên. Ví dụ: sắp xếp theo loại tệp:

Ví dụ: để triển khai một tính năng tương tự cho hình ảnh, bạn sẽ có mã như sau cùng với một số mã kiểm tra loại tệp để chọn tên bộ chứa mong muốn:
ROOT_BUCKET = app_identity.get_default_gcs_bucket_name()
IMAGE_BUCKET = '%s/%s' % (ROOT_BUCKET, 'images')
Bạn cũng sẽ xác thực hình ảnh đã tải lên bằng một công cụ như mô-đun imghdr của Thư viện chuẩn Python để xác nhận loại hình ảnh. Cuối cùng, bạn có thể muốn giới hạn kích thước của tệp tải lên để đề phòng các đối tượng xấu.
Giả sử bạn đã thực hiện tất cả những việc đó. Làm cách nào để cập nhật ứng dụng nhằm hỗ trợ việc chỉ định nơi lưu trữ tệp đã tải lên? Mấu chốt là điều chỉnh lệnh gọi đến blobstore.create_upload_url trong MainHandler.get để chỉ định vị trí mong muốn trong Cloud Storage cho tệp tải lên bằng cách thêm tham số gs_bucket_name như sau:
blobstore.create_upload_url('/upload', gs_bucket_name=IMAGE_BUCKET))
Vì đây là bản cập nhật không bắt buộc nếu bạn muốn chỉ định nơi tải lên, nên bản cập nhật này không nằm trong tệp main.py trong kho lưu trữ. Thay vào đó, bạn có thể xem xét một giải pháp thay thế có tên là main-gcs.py trong kho lưu trữ. Thay vì sử dụng một "thư mục" bộ chứa riêng biệt, mã trong main-gcs.py sẽ lưu trữ các tệp tải lên trong bộ chứa "gốc" (PROJECT_ID.appspot.com) giống như main.py nhưng cung cấp cấu trúc cần thiết nếu bạn muốn phát triển mẫu thành một thứ gì đó khác như được gợi ý trong phần này. Dưới đây là hình minh hoạ về "sự khác biệt" giữa main.py và main-gcs.py.

6. Tóm tắt/Dọn dẹp
Phần này kết thúc lớp học lập trình này bằng cách triển khai ứng dụng, xác minh ứng dụng hoạt động như dự kiến và trong mọi kết quả được phản ánh. Sau khi xác thực ứng dụng, hãy thực hiện mọi bước dọn dẹp và cân nhắc các bước tiếp theo.
Triển khai và xác minh ứng dụng
Triển khai lại ứng dụng bằng gcloud app deploy và xác nhận ứng dụng hoạt động như quảng cáo, khác với trải nghiệm người dùng (UX) của ứng dụng Mô-đun 0. Hiện có hai màn hình khác nhau trong ứng dụng của bạn, màn hình đầu tiên là lời nhắc biểu mẫu tải tệp lên:
Tại đây, người dùng cuối có thể tải tệp lên rồi nhấp vào "Gửi" hoặc nhấp vào "Bỏ qua" để không tải tệp nào lên. Trong cả hai trường hợp, kết quả là màn hình lượt truy cập gần đây nhất, hiện được bổ sung các đường liên kết "xem" hoặc "không có" giữa dấu thời gian của lượt truy cập và thông tin khách truy cập:

Chúc mừng bạn đã hoàn thành lớp học lập trình này về việc thêm Blobstore của App Engine vào ứng dụng mẫu của Mô-đun 0. Mã của bạn hiện đã khớp với mã trong thư mục FINISH (Mô-đun 15). main-gcs.py thay thế cũng có trong thư mục đó.
Dọn dẹp
Giải pháp chung
Nếu đã hoàn tất, bạn nên tắt ứng dụng App Engine để tránh phát sinh phí. Tuy nhiên, nếu bạn muốn thử nghiệm thêm, nền tảng App Engine có hạn mức miễn phí và miễn là bạn không vượt quá hạn mức sử dụng đó, bạn sẽ không bị tính phí. Đó là chi phí cho tài nguyên điện toán, nhưng cũng có thể có phí cho các dịch vụ App Engine có liên quan, vì vậy, hãy xem trang giá của App Engine để biết thêm thông tin. Nếu quá trình di chuyển này liên quan đến các dịch vụ khác của Cloud, thì các dịch vụ đó sẽ được tính phí riêng. Trong cả hai trường hợp, nếu có, hãy xem phần "Cụ thể cho lớp học lập trình này" bên dưới.
Để minh bạch hoàn toàn, việc triển khai lên một nền tảng điện toán không máy chủ của Google Cloud như App Engine sẽ phát sinh chi phí xây dựng và lưu trữ nhỏ. Cloud Build có hạn mức miễn phí riêng, tương tự như Cloud Storage. Việc lưu trữ hình ảnh đó sẽ sử dụng một phần hạn mức. Tuy nhiên, bạn có thể sống ở một khu vực không có hạn mức miễn phí như vậy, vì vậy, hãy lưu ý đến mức sử dụng bộ nhớ của bạn để giảm thiểu chi phí tiềm ẩn. Các "thư mục" cụ thể trên Cloud Storage mà bạn nên xem xét bao gồm:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Các đường liên kết đến bộ nhớ ở trên phụ thuộc vào
PROJECT_IDvà *LOC*ation của bạn, ví dụ: "us" nếu ứng dụng của bạn được lưu trữ ở Hoa Kỳ.
Mặt khác, nếu bạn không tiếp tục với ứng dụng này hoặc các lớp học lập trình di chuyển có liên quan khác và muốn xoá hoàn toàn mọi thứ, hãy tắt dự án của bạn.
Dành riêng cho lớp học lập trình này
Các dịch vụ được liệt kê dưới đây chỉ dành riêng cho lớp học lập trình này. Hãy tham khảo tài liệu của từng sản phẩm để biết thêm thông tin:
- Dịch vụ Blobstore của App Engine thuộc phạm vi hạn mức và giới hạn của Dữ liệu được lưu trữ, vì vậy, hãy xem xét cả trang giá cho các dịch vụ cũ đi kèm.
- Dịch vụ App Engine Datastore do Cloud Datastore (Cloud Firestore ở chế độ Datastore) cung cấp và cũng có một cấp miễn phí; hãy xem trang giá của dịch vụ này để biết thêm thông tin.
Các bước tiếp theo
Quá trình di chuyển hợp lý tiếp theo cần xem xét được đề cập trong Mô-đun 16, hướng dẫn nhà phát triển cách di chuyển từ dịch vụ Blobstore của App Engine sang sử dụng thư viện ứng dụng Cloud Storage. Lợi ích của việc nâng cấp bao gồm việc có thể sử dụng nhiều tính năng hơn của Cloud Storage, làm quen với thư viện ứng dụng hoạt động cho các ứng dụng bên ngoài App Engine, cho dù là trong Google Cloud, các đám mây khác hay thậm chí là tại chỗ. Nếu cảm thấy không cần tất cả các tính năng của Cloud Storage hoặc lo ngại về ảnh hưởng của dịch vụ này đối với chi phí, bạn có thể tiếp tục sử dụng App Engine Blobstore.
Ngoài Mô-đun 16, còn có một loạt các hoạt động di chuyển khác có thể thực hiện, chẳng hạn như Cloud NDB và Cloud Datastore, Cloud Tasks hoặc Cloud Memorystore. Ngoài ra, còn có các hoạt động di chuyển giữa các sản phẩm sang Cloud Run và Cloud Functions. Kho lưu trữ di chuyển có tất cả mã mẫu, liên kết bạn đến tất cả lớp học lập trình và video hiện có, đồng thời cung cấp hướng dẫn về những hoạt động di chuyển cần xem xét và mọi "thứ tự" di chuyển có liên quan.
7. Tài nguyên khác
Vấn đề/ý kiến phản hồi về lớp học lập trình
Nếu bạn phát hiện thấy vấn đề nào trong lớp học lập trình này, vui lòng tìm kiếm vấn đề đó trước khi gửi báo cáo. Đường liên kết để tìm kiếm và tạo vấn đề mới:
Tài nguyên di chuyển
Bạn có thể tìm thấy đường liên kết đến các thư mục kho lưu trữ cho Mô-đun 0 (BẮT ĐẦU) và Mô-đun 15 (KẾT THÚC) trong bảng dưới đây. Bạn cũng có thể truy cập vào các tệp này từ kho lưu trữ cho tất cả các hoạt động di chuyển trong lớp học lập trình App Engine. Bạn có thể sao chép hoặc tải tệp ZIP xuống.
Lớp học lập trình | Python 2 | Python 3 |
Mô-đun 0 | Không có | |
Mô-đun 15 (lớp học lập trình này) | Không có |
Tài nguyên trực tuyến
Dưới đây là các tài nguyên trực tuyến có thể liên quan đến hướng dẫn này:
App Engine
- Dịch vụ Blobstore của App Engine
- Hạn mức và giới hạn về dữ liệu được lưu trữ trên App Engine
- Tài liệu về App Engine
- Thời gian chạy của App Engine Python 2 (môi trường tiêu chuẩn)
- Sử dụng thư viện tích hợp sẵn của App Engine trên App Engine Python 2
- Thông tin về giá và hạn mức của App Engine
- Ra mắt nền tảng App Engine thế hệ thứ hai (2018)
- So sánh nền tảng thế hệ thứ nhất và thế hệ thứ hai
- Hỗ trợ dài hạn cho môi trường thời gian chạy cũ
- Kho lưu trữ mẫu di chuyển tài liệu
- Kho lưu trữ mẫu di chuyển do cộng đồng đóng góp
Google Cloud
- Python trên Google Cloud Platform
- Thư viện ứng dụng Python của Google Cloud
- Cấp "Luôn miễn phí" của Google Cloud
- Google Cloud SDK (công cụ dòng lệnh gcloud)
- Tất cả tài liệu về Google Cloud
Python
- Hệ thống tạo mẫu Django và Jinja2
- Khung web
webapp2 - Tài liệu
webapp2 webapp2_extrasđường liên kết- Tài liệu về Jinja2
webapp2_extras
Video
- Serverless Migration Station
- Serverless Expeditions
- Đăng ký kênh Google Cloud Tech
- Đăng ký kênh Google Developers
Giấy phép
Tác phẩm này được cấp phép theo Giấy phép Ghi công theo Creative Commons 2.0 Chung.