Cách sử dụng blobstore của App Engine (Mô-đun 15)

1. Tổng quan

Loạt lớp học lập trình về Trạm di chuyển không máy chủ (hướng dẫn thực hành theo tiến độ riêng) và video có liên quan nhằm giúp các nhà phát triển Google Cloud không máy chủ không hiện đại hoá các ứ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à ngừng sử dụng 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à độ 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 của Cloud hơn, đồng thời dễ dàng nâng cấp lên 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 FunctionsCloud Run hoặc ở những nơi khác nếu có.

Lớp học lập trình của Mô-đun 15 này giải thích cách thêm mức sử dụng App Engine blobstore vào ứng dụng mẫu trong Mô-đun 0. Sau đó, bạn có thể di chuyển mức sử dụng đó sang Cloud Storage trong Mô-đun 16.

Bạn sẽ tìm hiểu cách

  • Thêm việc sử dụng API/thư viện App Engine Blobstore
  • Lưu trữ nội dung người dùng tải lên dịch vụ blobstore
  • Chuẩn bị cho bước tiếp theo để di chuyển sang Cloud Storage

Bạn cần có

Khảo sát

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ có thể đọc Đọc và hoàn thành bài tập

Bạn đánh giá thế nào về trải nghiệm sử dụng Python?

Người mới tập Trung cấp Thành thạo

Bạn đánh giá thế nào về trải nghiệm sử dụng các dịch vụ của Google Cloud?

Người mới tập Trung cấp Thành thạo

2. Thông tin khái quát

Để 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ó từ Mô-đun 0. Ứng dụng mẫu hiển thị 10 lượt truy cập gần đây nhất của 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 lên (một tệp) 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, sẽ có một nút "bỏ qua" . Bất kể người dùng quyết định là gì, trang tiếp theo đều hiển thị cùng một kết quả như ứng dụng từ 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 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 các hệ thống tạo mẫu DjangoJinja2, và một điều làm cho ví dụ này trở nên khác biệt (ngoài việc thêm quyền truy cập Blobstore) là nó chuyển từ sử dụng Django trong Mô-đun 0 sang Jinja2 ở đây trong Mô-đun 15. Một bước quan trọng trong việc hiện đại hoá các ứng dụng trên App Engine là di chuyển các khung web từ webapp2 sang Flask. Phần sau sử dụng Jinja2 làm hệ thống tạo mẫu mặc định, vì vậy chúng ta bắt đầu đi theo hướng đó bằng cách triển khai Jinja2 trong khi vẫn giữ nguyên webapp2 để truy cập vào Blobstore. Vì Flask sử dụng Jinja2 theo mặc định, nên điều này có nghĩa là bạn không cần phải thay đổi mẫu trong Mô-đun 16.

3. Thiết lập/Chuẩn bị

Trước khi chúng ta chuyển sang phần chính của hướng dẫn này, hãy thiết lập dự án, lấy mã và triển khai ứng dụng cơ sở để bắt đầu làm việc với mã.

1. Thiết lập dự án

Nếu đã triển khai ứng dụng 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 này có một tài khoản thanh toán đang hoạt động và đã bật App Engine.

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à phải có một ứng dụng mẫu Mô-đun 0 hoạt động được. Nếu chưa có, bạn có thể lấy từ Mô-đun 0 "BẮT ĐẦU" thư mục (đườ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 qua từng bước, kết thúc bằng mã tương tự như trong Mô-đun 15 " hướng dẫn hoàn thiện" .

Thư mục của các tệp KHỞI ĐỘNG Mô-đun 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 để thực hiện ngay:

  1. Làm quen lại bằng công cụ dòng lệnh gcloud
  2. Triển khai lại ứng dụng mẫu bằng gcloud app deploy
  3. Xác nhận rằng ứng dụng chạy trên App Engine mà không gặp vấn đề nào

Sau khi thực thi thành công các bước đó và thấy ứng dụng web của bạn hoạt động (với kết quả tương tự như bên dưới), bạn đã sẵn sàng thêm chức năng lưu vào bộ nhớ đệm cho ứng dụng của mình.

a7a9d2b80d706a2b.png

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 ta sẽ chuyển từ phương thức tạo mẫu Django (mặc định) sang Jinja2, vì vậy để chuyển đổi, người dùng phải chỉ định phiên bản Jinja2 mới nhất có sẵn trên các máy chủ App Engine và bạn thực hiện bằng cách thêm vào phần thư viện bên thứ 3 tích hợp sẵn trong app.yaml.

TRƯỚC KHI:

runtime: python27
threadsafe: yes
api_version: 1

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

Chỉnh sửa tệp app.yaml của bạn bằng cách thêm phần libraries mới như bạn thấy ở đây:

SAU KHI:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: jinja2
  version: latest

Không có tệp cấu hình nào khác cần cập nhật, vì vậy, hãy chuyển sang các tệp ứng dụng.

5. Sửa đổi tệp ứng dụng

Hỗ trợ tính năng nhập và Jinja2

Tập hợp các thay đổi đầu tiên cho main.py bao gồm việc thêm việc sử dụng API Blobstore và thay thế việc tạo mẫu Django bằng Jinja2. Sau đây là nội dung thay đổi:

  1. Mục đích của mô-đun os là tạo tên đường dẫn tệp cho mẫu Django. Vì chúng ta đang chuyển sang Jinja2 để xử lý vấn đề này nên việc sử dụng os cũng như trình kết xuất mẫu Django google.appengine.ext.webapp.template không còn cần thiết nữa, do đó sẽ bị xoá.
  2. Nhập API Blobstore: google.appengine.ext.blobstore
  3. Nhập các trình xử lý Blobstore có trong khung webapp ban đầu — các trình xử lý này không có trong webapp2: google.appengine.ext.webapp.blobstore_handlers
  4. Nhập hỗ trợ Jinja2 từ gói webapp2_extras

TRƯỚC KHI:

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 KHI:

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ư định nghĩa trong tài liệu về webapp2_extras. Đoạn mã sau đây bao bọc lớp trình xử lý yêu cầu webapp2 tiêu chuẩn với 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ư những quá trình di chuyển khác trong loạt bài này, trong đó chúng ta giữ nguyên chức năng hoặc đầu ra 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 đi ngược lại quy chuẩn. 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 tôi sẽ cập nhật ứng dụng để yêu cầu người dùng cung cấp 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 lên bất kỳ nội dung nào. Khi bước này hoàn tất, "lượt truy cập gần đây nhất" sẽ được hiển thị.

Thay đổi này cho phép ứng dụng của chúng tôi 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 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 (được gọi là "BlobKey") của tệp đã tải lên Blobstore và thêm một tệp tham chiếu để lưu mã đó vào store_visit(). Vì dữ liệu bổ sung này được trả về cùng với mọi nội dung khác khi truy vấn, nên fetch_visits() sẽ không thay đổi.

Dưới đây là hình ảnh trước và sau của các bản cập nhật này có file_blob, một ndb.BlobKeyProperty:

TRƯỚC KHI:

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 KHI:

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)

Dưới đây là hình ảnh minh hoạ những thay đổi đã được thực hiện từ trước đến nay:

2270783776759f7f.png.

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ù nhắc người dùng về tệp hay hỗ trợ thao tác "bỏ qua" hoặc hiển thị một 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ợ tải tệp lên:

  1. Yêu cầu GET của trình xử lý chính không còn tìm nạp các lượt truy cập gần đây nhất để hiển thị nữa. Thay vào đó, nó nhắc người dùng tải lên.
  2. Khi người dùng cuối gửi một tệp để tải lên hoặc bỏ qua quy trình đó, POST từ biểu mẫu sẽ chuyển quyền kiểm soát sang UploadHandler mới, bắt nguồn từ google.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler.
  3. Phương thức POST của UploadHandler sẽ thực hiện quá trình tải lên, gọi store_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 quay lại "/", trong đó...
  4. Các phương thức POST của trình xử lý chính truy vấn (thông qua fetch_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", không có tệp nào được tải lên, nhưng lượt truy cập vẫn được ghi lại theo sau là cùng một lệnh chuyển hướng.
  5. Các lượt truy cập gần đây nhất được hiển thị bao gồm một trường mới được hiển thị cho người dùng, hoặc là "chế độ 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. Những thay đổi này được thực hiện trong mẫu HTML cùng với việc thêm biểu mẫu tải lên (thông tin chi tiết sẽ sớm được cung cấp).
  6. Nếu người dùng cuối nhấp vào nút "xem" cho bất kỳ lượt truy cập nào có video đã tải lên, công cụ này sẽ gửi yêu cầu GET đến ViewBlobHandler mới, bắt nguồn từ google.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler. Việc này hiển thị tệp nếu có hình ảnh (trong trình duyệt nếu được hỗ trợ), nhắc tải xuống nếu không có hoặc trả về lỗi HTTP 404 nếu không tìm thấy.
  7. Ngoài cặp lớp trình xử lý mới cũng như một cặp tuyến mới để gửi lưu lượng truy cập đến chúng, trình xử lý chính cần một phương thức POST mới để nhận lệnh chuyển hướng 307 được mô tả ở trên.

Trước những bản cập nhật này, ứ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 KHI:

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 đó, hiện có 3 trình xử lý: 1) trình xử lý tải lên có phương thức POST, 2) "view blob" (xem blob) trình xử lý tải xuống có phương thức GET và 3) trình xử lý chính với các phương thức GETPOST. Hãy thực hiện những thay đổi này để phần còn lại của ứng dụng giờ đây sẽ có dạng như dưới đây.

SAU KHI:

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 mã này mà chúng ta vừa thêm:

  • Trong MainHandler.get, có một lệnh gọi đến blobstore.create_upload_url. Lệnh gọi này sẽ tạo URL cho biểu mẫu POST, 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 đến blobstore_handlers.BlobstoreUploadHandler.get_uploads. Đây là phép màu thực sự khi đưa tệp vào Blobstore và trả về một mã nhận dạng duy nhất và lâu dài cho tệp đó, BlobKey của tệp.
  • Trong ViewBlobHandler.get, việc gọi blobstore_handlers.BlobstoreDownloadHandler.send bằng BlobKey của một tệp sẽ dẫn đến việc tìm nạp và chuyển tiếp tệp đó đến trình duyệt của người dùng cuối

Các cuộc gọi này thể hiện 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. Dưới đây là hình ảnh minh hoạ cho loạt thay đổi thứ hai và cũng là cuối cùng này đối với main.py:

da2960525ac1b90d.png

Cập nhật mẫu HTML

Một số bản cập nhật đối với ứ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, mẫu web cần có 2 thay đổi tương ứng, trên thực tế là:

  1. Biểu mẫu tải tệp lên bắt buộc phải có 3 phần tử đầu vào: tệp và cặp nút gửi để tải tệp lên và bỏ qua tương ứng.
  2. Cập nhật dữ liệu về số lượt truy cập gần đây nhất bằng cách thêm một "chế độ xem" liên kết cho các lượt truy cập có tải lên tệp tương ứng hoặc "không có" nếu không.

TRƯỚC KHI:

<!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 để bao gồm mẫu đã cập nhật:

SAU KHI:

<!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 dưới đây minh hoạ các nội dung cập nhật cần thiết cho index.html:

8583e975f25aa9e7.pngs

Một thay đổi cuối cùng là Jinja2 ưu tiên các mẫu của mình trong thư mục templates, vì vậy hãy tạo thư mục đó và di chuyển index.html vào bên trong. Với bước cuối cùng này, bạn đã thực hiện tất cả các thay đổi cần thiết để thêm việc sử dụng Blobstore vào ứng dụng mẫu Mô-đun 0.

(không bắt buộc) "nâng cao" Cloud Storage

Bộ nhớ Blobstore sau cùng đã được phát triển thành Cloud Storage. Tức là những nội dung tải lên trên Blobstore sẽ xuất hiện trong Cloud Console, cụ thể là trên trình duyệt Cloud Storage. Câu hỏi là ở đâu. Câu trả lời chính là bộ chứa Cloud Storage mặc định cho ứng dụng App Engine của bạn. Tên này là tên miền đầy đủ của ứng dụng App Engine của bạn, PROJECT_ID.appspot.com. Việc này rất tiện lợi vì tất cả mã dự án đều là duy nhất, đúng không?

Các bản cập nhật đối với ứ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 vị trí cụ thể hơn. Bộ chứa mặc định có thể truy cập theo phương thức lập trình thông qua google.appengine.api.app_identity.get_default_gcs_bucket_name(), yêu cầu phải nhập dữ liệu mới nếu bạn muốn truy cập giá trị này, chẳng hạn như sử dụng làm tiền tố để sắp xếp các tệp được tải lên. Ví dụ: sắp xếp theo loại tệp:

f61f7a23a1518705.png

Ví dụ: để triển khai những thứ tương tự cho hình ảnh, bạn sẽ có mã như thế này 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 nên giới hạn kích thước của tệp tải lên để phòng trường hợp có đối tượng xấu.

Giả sử bạn đã làm xong mọi việc. Chúng ta 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ữ các tệp được tải lên? Bạn cần đ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 quá trình 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))

Do đâ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ệp tải lên sẽ đến, nên đây không phải là một phần của tệp main.py trong kho lưu trữ. Thay vào đó, một phương án thay thế có tên là main-gcs.py sẽ được cung cấp để bạn xem xét trong kho lưu trữ. Thay vì sử dụng một "thư mục" nhóm riêng biệt, mã trong main-gcs.py lưu trữ các tệp tải lên trong "gốc" bộ chứa (PROJECT_ID.appspot.com) giống như main.py nhưng cung cấp bộ khung cần thiết nếu bạn muốn lấy mẫu để tạo ra một nội dung cụ thể hơn như được gợi ý trong phần này. Dưới đây là hình minh hoạ các điểm "điểm khác biệt" từ main.py đến main-gcs.py.

256e1ea68241a501.pngS

6. Tóm tắt/Dọn dẹp

Phần này tóm tắt lớp học lập trình này bằng cách triển khai ứng dụng, xác minh rằng ứng dụng hoạt động như dự kiến và trong mọi đầu ra đượ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à xem xét 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 rằng ứng dụng hoạt động như quảng cáo, trải nghiệm người dùng (UX) khác với ứng dụng Mô-đun 0. Có hai màn hình khác nhau trong ứng dụng của bạn hiện tại, đầu tiên là lời nhắc truy cập vào biểu mẫu tải tệp lên:

f5b5f9f19d8ae978.pngTại đây, người dùng cuối tải tệp lên và nhấp vào "Gửi" hoặc nhấp vào "Bỏ qua" không tải lên bất kỳ nội dung nào. Trong cả hai trường hợp, kết quả vẫn là màn hình truy cập gần đây nhất, hiện được tăng cường bằng tính năng "xem" liên kết hoặc "không có" giữa dấu thời gian truy cập và thông tin về khách truy cập:

f5ac6b98ee8a34cb.png

Chúc mừng bạn đã hoàn thành lớp học lập trình này bằng cách thêm việc sử dụng App Engine Blobstore vào ứng dụng mẫu Module 0. Mã của bạn bây giờ sẽ khớp với nội dung trong thư mục chốt (HOÀN TẤT (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 bạn đã hoàn tất, chúng tôi khuyên bạn nên tắt ứng dụng App Engine để tránh phát sinh thanh toán. Tuy nhiên, nếu bạn muốn kiểm tra hoặc thử nghiệm thêm, nền tảng App Engine có hạn mức miễn phí, và bạn sẽ không bị tính phí, miễn là bạn không vượt quá cấp sử dụng đó. Đó là cho dịch vụ điện toán nhưng bạn cũng có thể bị tính phí cho các dịch vụ có liên quan của App Engine, vì vậy hãy xem trang giá của dịch vụ này để 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 trên Google Cloud, thì những 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 "Dành riêng cho lớp học lập trình này" phần dưới đây.

Để công bố đầy đủ thông tin, việc triển khai cho một nền tảng điện toán không máy chủ của Google Cloud như App Engine sẽ làm phát sinh chi phí bản dựng và bộ nhớ thấp. Cloud Build cũng 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 hết 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ó bậc miễn phí như vậy, vì vậy hãy chú ý đến mức sử dụng bộ nhớ của bạn để giảm thiểu chi phí tiềm ẩn. "Thư mục" cụ thể trên Cloud Storage bạn nên xem xét, bao gồm:

  • 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
  • Các đường liên kết lưu trữ ở trên phụ thuộc vào PROJECT_ID và hoạt động *LOC*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 định tiếp tục sử dụng ứng dụng này hoặc các lớp học lập trình di chuyển khác có liên quan và muốn xoá hoàn toàn mọi thứ, hãy ngừng 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 là những dịch vụ 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:

Các bước tiếp theo

Bước di chuyển logic tiếp theo cần cân nhắc sẽ được đề cập trong Mô-đun 16, hướng dẫn các nhà phát triển cách di chuyển từ dịch vụ App Engine Blobstore sang sử dụng thư viện ứng dụng Cloud Storage. Lợi ích khi nâng cấp bao gồm: có thể truy cập nhiều tính năng hơn của Cloud Storage, làm quen với thư viện ứng dụng dùng cho các ứng dụng bên ngoài App Engine, cho dù trong Google Cloud hay các đám mây khác hay thậm chí tại chỗ. Nếu bạn không cần tất cả các tính năng hiện có của Cloud Storage hoặc lo ngại về tác động của nó đến chi phí, bạn có thể tiếp tục sử dụng App Engine Blobstore.

Ngoài Mô-đun 16, còn có hàng loạt hoạt động di chuyển khác có thể thực hiện như Cloud NDB và Cloud Datastore, Cloud Tasks hoặc Cloud Memorystore. Ngoài ra, chúng tôi cũng sẽ di chuyển giữa nhiều sản phẩm sang Cloud Run và Cloud Functions. Kho lưu trữ di chuyển nêu bật mọi mã mẫu, cung cấp đường liên kết đến mọi 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à "thứ tự" có liên quan di chuyển.

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ày

Nếu bạn gặp vấn đề với lớp học lập trình này, vui lòng tìm vấn đề của bạn trước khi gửi. Đường liên kết để tìm kiếm và báo cáo vấn đề mới:

Tài nguyên di chuyển

Bạn có thể tìm thấy các đường liên kết đến các thư mục repo cho Mô-đun 0 (START) và Mô-đun 15 (Complete) trong bảng bên dưới. Bạn cũng có thể truy cập vào các tệp này qua kho lưu trữ dành cho mọi quá trình di chuyển trong lớp học lập trình App Engine. Tại đây, bạn có thể sao chép hoặc tải tệp ZIP xuống.

Codelab

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ể phù hợp với hướng dẫn này:

App Engine

Google Cloud

Python

Video

Giấy phép

Tác phẩm này được cấp phép theo Giấy phép chung Ghi nhận tác giả Creative Commons 2.0.