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 Functions và Cloud 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ó
- 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 hành về các lệnh Linux phổ biến
- Kiến thức cơ bản về việc 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ữ)
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 sử dụng 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 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 Django và Jinja2, 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" .
- START: Thư mục mô-đun 0 (Python 2)
- HOÀN TẤT: 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 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:
- Làm quen lại bằng 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 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.
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:
- 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ụngos
cũng như trình kết xuất mẫu Djangogoogle.appengine.ext.webapp.template
không còn cần thiết nữa, do đó sẽ bị xoá. - Nhập API Blobstore:
google.appengine.ext.blobstore
- 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ó trongwebapp2
:google.appengine.ext.webapp.blobstore_handlers
- 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:
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:
- 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. - 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 sangUploadHandler
mới, bắt nguồn từgoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler
. - Phương thức
POST
củaUploadHandler
sẽ thực hiện quá trình 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 quay lại "/", trong đó... - Các phương thức
POST
củ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", 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. - 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).
- 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
đếnViewBlobHandler
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. - 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 GET
và POST
. 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 đếnblobstore.create_upload_url
. Lệnh gọi này sẽ tạo URL cho biểu mẫuPOST
, 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à 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ọiblobstore_handlers.BlobstoreDownloadHandler.send
bằngBlobKey
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
:
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à:
- 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.
- 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
:
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:
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
.
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:
Tạ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:
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:
- Dịch vụ Blobstore của App Engine thuộc Hạn mức và giới hạn dữ liệu được lưu trữ, vì vậy, hãy xem lại điều đó cũng như trang giá cho các dịch vụ theo gói cũ.
- Dịch vụ App Engine Datastore do Cloud Datastore (Cloud Firestore ở chế độ Datastore) cung cấp, cũng có một bậc miễn phí; hãy xem trang giá của YouTube để 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
- Dịch vụ App Engine Blobstore
- Hạn mức và giới hạn 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 Python 2 App Engine (môi trường tiêu chuẩn)
- Sử dụng thư viện tích hợp sẵn App Engine trên Python 2 App Engine
- 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 đầu tiên và nền tảng 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 Google Cloud Python
- Google Cloud "Luôn miễn phí" cấp
- SDK Google Cloud (công cụ dòng lệnh gcloud)
- Tất cả tài liệu của Google Cloud
Python
- Các hệ thống tạo mẫu Django và Jinja2
- Khung web
webapp2
- Tài liệu
webapp2
- Đường liên kết
webapp2_extras
- Tài liệu về Jinja2
webapp2_extras
Video
- Trạm di chuyển không máy chủ
- Thám hiểm không máy chủ
- Đăng ký sử dụng Google Cloud Tech
- Đăng ký Google Developers
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.