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 theo tốc độ của riêng bạn) và các video liên quan nhằm giúp các nhà phát triển Google Cloud không máy chủ 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 quy trình di chuyển, chủ yếu là chuyển từ các dịch vụ cũ. Làm như vậy sẽ giúp ứng dụng của bạn dễ dàng di chuyển hơn, đồng thời mang đến cho bạn nhiều lựa chọn và sự 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 trên đám mây 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 ở những nơi khác nếu có thể.
Mục đích của lớp học lập trình này là hướng dẫn nhà phát triển App Engine Python 2 cách di chuyển từ các tác vụ kéo của Hàng đợi tác vụ App Engine sang Cloud Pub/Sub. Ngoài ra, còn có một quy trình di chuyển ngầm từ App Engine NDB sang Cloud NDB để truy cập vào Datastore (chủ yếu được đề cập trong Mô-đun 2) cũng như một quy trình nâng cấp lên Python 3.
Trong Mô-đun 18, bạn sẽ tìm hiểu cách thêm việc sử dụng các tác vụ lấy trong ứng dụng. Trong mô-đun này, bạn sẽ lấy ứng dụng đã hoàn thành trong Mô-đun 18 và di chuyển việc sử dụng đó sang Cloud Pub/Sub. Những người sử dụng Hàng đợi tác vụ cho các tác vụ đẩy sẽ di chuyển sang Cloud Tasks và nên tham khảo các Mô-đun 7-9.
Bạn sẽ tìm hiểu cách
- Thay thế việc sử dụng Hàng đợi tác vụ App Engine (kéo tác vụ) bằng Cloud Pub/Sub
- Thay thế việc sử dụng App Engine NDB bằng Cloud NDB (xem thêm Mô-đun 2)
- Chuyển ứng dụng sang Python 3
Bạn cần có
- Một dự án trên Google Cloud Platform có một tài khoản thanh toán GCP đang hoạt động
- Kỹ năng cơ bản về Python
- Có kiến thức cơ bản về các lệnh Linux thường dùng
- Kiến thức cơ bản về cách phát triển và triển khai các ứng dụng App Engine
- Một ứng dụng mẫu App Engine hoạt động của Mô-đun 18
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 khi sử dụng các dịch vụ của Google Cloud?
2. Thông tin khái quát
Hàng đợi tác vụ App Engine hỗ trợ cả tác vụ đẩy và kéo. Để cải thiện khả năng di chuyển ứng dụng, Google Cloud đề xuất bạn di chuyển từ các dịch vụ cũ đi kèm (chẳng hạn như Hàng đợi tác vụ) sang các dịch vụ tương đương độc lập trên Cloud hoặc của bên thứ ba.
- Người dùng Task Queue push task (tác vụ đẩy Hàng đợi tác vụ) nên di chuyển sang Cloud Tasks.
- Người dùng kéo tác vụ của Hàng đợi tác vụ nên di chuyển sang Cloud Pub/Sub.
Các mô-đun 7-9 đề cập đến việc di chuyển tác vụ đẩy, trong khi các mô-đun 18-19 tập trung vào việc di chuyển tác vụ kéo. Mặc dù Cloud Tasks phù hợp hơn với các tác vụ đẩy của Hàng đợi tác vụ, nhưng Pub/Sub không tương tự như các tác vụ kéo của Hàng đợi tác vụ.
Pub/Sub có nhiều tính năng hơn so với chức năng kéo do Hàng đợi tác vụ cung cấp. Ví dụ: Pub/Sub cũng có chức năng push, tuy nhiên Cloud Tasks giống với các tác vụ push của Hàng đợi tác vụ hơn, nên chức năng push của Pub/Sub không thuộc bất kỳ Mô-đun di chuyển nào. Lớp học lập trình Mô-đun 19 này minh hoạ việc chuyển cơ chế xếp hàng từ hàng đợi kéo Hàng đợi tác vụ sang Pub/Sub cũng như di chuyển từ App Engine NDB sang Cloud NDB để truy cập vào Datastore, lặp lại quá trình di chuyển Mô-đùn 2.
Mặc dù mã của Mô-đun 18 được "quảng cáo" là một ứng dụng mẫu Python 2, nhưng bản thân nguồn này tương thích với cả Python 2 và 3, đồng thời vẫn giữ nguyên như vậy ngay cả sau khi di chuyển sang Cloud Pub/Sub (và Cloud NDB) trong Mô-đun 19.
Hướng dẫn này có các bước sau:
- Thiết lập/Công việc chuẩn bị
- Cập nhật cấu hình
- Sửa đổi mã xử lý ứng dụng
3. Thiết lập/Công việc chuẩn bị
Phần này giải thích cách:
- Thiết lập dự án trên đám mây
- Tải ứng dụng mẫu cơ sở
- (Triển khai lại) và xác thực ứng dụng cơ sở
- Bật các dịch vụ/API mới của Google Cloud
Các bước này đảm bảo bạn bắt đầu bằng mã đang hoạt động và mã đó đã sẵn sàng để di chuyển sang các dịch vụ đám mây.
1. Thiết lập dự án
Nếu bạn đã hoàn thành lớp học lập trình Mô-đun 18, hãy dùng lại chính 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ó một tài khoản thanh toán đang hoạt động và một ứng dụng App Engine đã bật. Tìm mã dự án vì bạn cần có mã này trong lớp học lập trình này, hãy sử dụng mã dự án bất cứ khi nào bạn gặp biến PROJECT_ID.
2. Tải ứng dụng mẫu cơ sở
Một trong những điều kiện tiên quyết là ứng dụng App Engine hoạt động ở Mô-đun 18, vì vậy, hãy hoàn thành lớp học lập trình của ứng dụng đó (nên dùng; đường liên kết ở trên) hoặc sao chép mã Mô-đun 18 từ kho lưu trữ. Dù bạn dùng mã của mình hay mã của chúng tôi, đây là nơi chúng ta sẽ bắt đầu ("START"). Lớp học lập trình này sẽ hướng dẫn bạn quy trình di chuyển, kết thúc bằng mã tương tự như mã trong thư mục kho lưu trữ Mô-đun 19 ("FINISH").
- BẮT ĐẦU: Thư mục Mô-đun 18 (Python 2)
- HOÀN TẤT: Thư mục Mô-đun 19 (Python 2 và 3)
- Toàn bộ kho lưu trữ (để sao chép hoặc tải tệp ZIP xuống)
Bất kể bạn sử dụng ứng dụng Module 18 nào, thư mục sẽ có dạng như bên dưới, có thể có cả thư mục lib:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
3. (Triển khai lại) và xác thực ứng dụng cơ sở
Thực hiện các bước sau để triển khai ứng dụng Mô-đun 18:
- Xoá thư mục
lib(nếu có) rồi chạypip install -t lib -r requirements.txtđể điền lạilib. Bạn có thể cần dùngpip2nếu đã cài đặt cả Python 2 và 3 trên máy phát triển. - Đảm bảo bạn đã cài đặt và khởi chạy công cụ dòng lệnh
gcloud, đồng thời đã xem xét cách sử dụng công cụ này. - (không bắt buộc) Đặt dự án trên Đám mây bằng
gcloud config set projectPROJECT_IDnếu bạn không muốn nhậpPROJECT_IDcho mỗi lệnhgcloudmà bạn đưa ra. - Triển khai ứng dụng mẫu bằng
gcloud app deploy - Xác nhận rằng ứng dụng chạy như mong đợi mà không gặp vấn đề. Nếu bạn đã hoàn thành lớp học lập trình Mô-đun 18, thì ứng dụng sẽ hiển thị những khách truy cập hàng đầu cùng với những lượt truy cập gần đây nhất (minh hoạ bên dưới). Nếu không, có thể sẽ không có số lượt truy cập nào để hiển thị.

Trước khi di chuyển ứng dụng mẫu của Mô-đun 18, trước tiên, bạn phải bật các dịch vụ đám mây mà ứng dụng đã sửa đổi sẽ sử dụng.
4. Bật các dịch vụ/API mới của Google Cloud
Ứng dụng cũ sử dụng các dịch vụ đi kèm của App Engine mà không yêu cầu thiết lập bổ sung, nhưng các dịch vụ Cloud độc lập thì có, và ứng dụng đã cập nhật sẽ sử dụng cả Cloud Pub/Sub và Cloud Datastore (thông qua thư viện ứng dụng Cloud NDB). App Engine và cả hai API Cloud đều có hạn mức "Luôn miễn phí". Vì vậy, miễn là bạn không vượt quá những giới hạn đó, bạn sẽ không phải trả phí khi hoàn thành hướng dẫn này. Bạn có thể bật Cloud API từ Cloud Console hoặc từ dòng lệnh, tuỳ theo lựa chọn ưu tiên của bạn.
Trên Cloud Console
Chuyển đến trang Thư viện của Trình quản lý API (cho đúng dự án) trong Cloud Console, rồi tìm kiếm API Cloud Datastore và Cloud Pub/Sub bằng thanh tìm kiếm ở giữa trang:

Nhấp vào nút Bật cho từng API riêng biệt – bạn có thể được nhắc cung cấp thông tin thanh toán. Ví dụ: đây là trang Thư viện API Cloud Pub/Sub:

Từ dòng lệnh
Mặc dù việc bật API từ bảng điều khiển có thể cung cấp thông tin trực quan, nhưng một số người lại thích dòng lệnh. Phát lệnh gcloud services enable pubsub.googleapis.com datastore.googleapis.com để bật cả hai API cùng một lúc:
$ gcloud services enable pubsub.googleapis.com datastore.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Bạn có thể được nhắc nhập thông tin thanh toán. Nếu muốn bật các Cloud API khác và muốn biết URI của các API đó, bạn có thể tìm thấy chúng ở cuối trang thư viện của mỗi API. Ví dụ: hãy quan sát pubsub.googleapis.com là "Tên dịch vụ" ở cuối trang Pub/Sub ngay phía trên.
Sau khi hoàn tất các bước này, dự án của bạn sẽ có thể truy cập vào các API. Giờ là lúc cập nhật ứng dụng để sử dụng các API đó.
4. Tạo tài nguyên Pub/Sub
Tóm tắt thứ tự của quy trình công việc Hàng đợi tác vụ trong Mô-đun 18:
- Mô-đun 18 đã dùng tệp
queue.yamlđể tạo một hàng đợi kéo có tên làpullq. - Ứng dụng sẽ thêm các tác vụ vào hàng đợi kéo để theo dõi khách truy cập.
- Cuối cùng, các tác vụ sẽ được một worker xử lý trong một khoảng thời gian nhất định (1 giờ).
- Các tác vụ được thực thi để tính tổng số lượt truy cập gần đây.
- Các tác vụ sẽ bị xoá khỏi hàng đợi sau khi hoàn tất.
Bạn sẽ sao chép một quy trình tương tự bằng Pub/Sub. Phần tiếp theo giới thiệu thuật ngữ cơ bản về Pub/Sub, với 3 cách tạo tài nguyên Pub/Sub cần thiết.
Thuật ngữ Hàng đợi tác vụ App Engine (kéo) so với Cloud Pub/Sub
Để chuyển sang Pub/Sub, bạn cần điều chỉnh một chút về từ vựng. Dưới đây là các danh mục chính cùng với các thuật ngữ liên quan của cả hai sản phẩm. Ngoài ra, hãy xem hướng dẫn di chuyển có các nội dung so sánh tương tự.
- Cấu trúc dữ liệu xếp hàng: Với Hàng đợi tác vụ, dữ liệu sẽ đi vào hàng đợi kéo; với Pub/Sub, dữ liệu sẽ đi vào các chủ đề.
- Đơn vị dữ liệu trong hàng đợi: Tác vụ kéo bằng Hàng đợi tác vụ được gọi là thông báo bằng Pub/Sub.
- Trình xử lý dữ liệu: Với Hàng đợi tác vụ, worker truy cập vào các tác vụ kéo; với Pub/Sub, bạn cần có các thuê bao/người đăng ký để nhận tin nhắn
- Trích xuất dữ liệu: Cho thuê một tác vụ kéo cũng giống như kéo một thông báo từ một chủ đề (thông qua một thuê bao).
- Dọn dẹp/hoàn thành: Xoá một việc cần làm trong Hàng đợi tác vụ khỏi hàng đợi kéo khi bạn hoàn tất tương tự như việc xác nhận một thông báo Pub/Sub
Mặc dù có thay đổi về sản phẩm trong hàng đợi, nhưng quy trình vẫn tương đối giống nhau:
- Thay vì hàng đợi kéo, ứng dụng này sử dụng một chủ đề có tên là
pullq. - Thay vì thêm các việc cần làm vào hàng đợi kéo, ứng dụng sẽ gửi thông báo đến một chủ đề (
pullq). - Thay vì một worker thuê các tác vụ từ hàng đợi kéo, một subscriber có tên là
workersẽ kéo các thông báo từ chủ đềpullq. - Ứng dụng xử lý tải trọng thông báo, tăng số lượng khách truy cập trong Datastore.
- Thay vì xoá các tác vụ khỏi hàng đợi kéo, ứng dụng sẽ xác nhận các thông báo đã xử lý.
Với Hàng đợi tác vụ, quá trình thiết lập bao gồm việc tạo hàng đợi kéo. Với Pub/Sub, bạn cần tạo cả chủ đề và gói thuê bao để thiết lập. Trong Mô-đun 18, chúng ta đã xử lý queue.yaml bên ngoài quá trình thực thi ứng dụng; giờ đây, chúng ta phải làm điều tương tự với Pub/Sub.
Có 3 cách để tạo chủ đề và lượt đăng ký:
- Trên bảng điều khiển Cloud
- Từ dòng lệnh hoặc
- Từ mã (tập lệnh Python ngắn)
Chọn một trong các lựa chọn bên dưới và làm theo hướng dẫn tương ứng để tạo tài nguyên Pub/Sub.
Trên bảng điều khiển Cloud
Để tạo một chủ đề trên Cloud Console, hãy làm theo các bước sau:
- Chuyển đến trang Chủ đề Pub/Sub trên bảng điều khiển Cloud.
- Nhấp vào Tạo chủ đề ở trên cùng; một cửa sổ hộp thoại mới sẽ mở ra (xem hình bên dưới)
- Trong trường Topic ID (Mã nhận dạng chủ đề), hãy nhập
pullq. - Bỏ chọn tất cả các lựa chọn đã đánh dấu và chọn Khoá mã hoá do Google quản lý.
- Nhấp vào nút Tạo chủ đề.
Đây là giao diện của hộp thoại tạo chủ đề:

Bây giờ, bạn đã có một chủ đề, bạn phải tạo một gói thuê bao cho chủ đề đó:
- Chuyển đến trang Gói thuê bao Pub/Sub trên bảng điều khiển Cloud.
- Nhấp vào Tạo gói thuê bao ở trên cùng (xem hình ảnh bên dưới).
- Nhập
workervào trường Mã nhận dạng gói thuê bao. - Chọn
pullqtrong trình đơn thả xuống Chọn một chủ đề Cloud Pub/Sub, lưu ý đến "tên đường dẫn đủ điều kiện" của chủ đề đó, ví dụ:projects/PROJECT_ID/topics/pullq - Đối với Loại phân phối, hãy chọn Kéo.
- Giữ nguyên tất cả các lựa chọn khác rồi nhấp vào nút Tạo.
Đây là giao diện của màn hình tạo gói thuê bao:

Ngoài ra, bạn cũng có thể tạo một gói thuê bao trên trang Chủ đề. "Lối tắt" này có thể hữu ích cho bạn trong việc liên kết các chủ đề với gói thuê bao. Để tìm hiểu thêm về cách tạo gói thuê bao, hãy xem tài liệu này.
Từ dòng lệnh
Người dùng Pub/Sub có thể tạo chủ đề và gói thuê bao bằng các lệnh gcloud pubsub topics create TOPIC_ID và gcloud pubsub subscriptions create SUBSCRIPTION_ID --topic=TOPIC_ID, tương ứng. Việc thực thi các lệnh này với TOPIC_ID là pullq và SUBSCRIPTION_ID là worker sẽ dẫn đến kết quả sau cho dự án PROJECT_ID:
$ gcloud pubsub topics create pullq Created topic [projects/PROJECT_ID/topics/pullq]. $ gcloud pubsub subscriptions create worker --topic=pullq Created subscription [projects/PROJECT_ID/subscriptions/worker].
Ngoài ra, hãy xem trang này trong tài liệu Bắt đầu nhanh. Việc sử dụng dòng lệnh có thể đơn giản hoá quy trình làm việc khi các chủ đề và lượt đăng ký được tạo thường xuyên. Bạn có thể sử dụng các lệnh như vậy trong tập lệnh shell cho mục đích này.
Từ mã (tập lệnh Python ngắn)
Một cách khác để tự động hoá việc tạo chủ đề và gói thuê bao là sử dụng API Pub/Sub trong mã nguồn. Dưới đây là mã cho tập lệnh maker.py trong thư mục kho lưu trữ Mô-đun 19.
from __future__ import print_function
import google.auth
from google.api_core import exceptions
from google.cloud import pubsub
_, PROJECT_ID = google.auth.default()
TOPIC = 'pullq'
SBSCR = 'worker'
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
def make_top():
try:
top = ppc_client.create_topic(name=TOP_PATH)
print('Created topic %r (%s)' % (TOPIC, top.name))
except exceptions.AlreadyExists:
print('Topic %r already exists at %r' % (TOPIC, TOP_PATH))
def make_sub():
try:
sub = psc_client.create_subscription(name=SUB_PATH, topic=TOP_PATH)
print('Subscription created %r (%s)' % (SBSCR, sub.name))
except exceptions.AlreadyExists:
print('Subscription %r already exists at %r' % (SBSCR, SUB_PATH))
try:
psc_client.close()
except AttributeError: # special Py2 handler for grpcio<1.12.0
pass
make_top()
make_sub()
Việc thực thi tập lệnh này sẽ cho ra kết quả như mong đợi (miễn là không có lỗi):
$ python3 maker.py Created topic 'pullq' (projects/PROJECT_ID/topics/pullq) Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)
Việc gọi API để tạo các tài nguyên đã tồn tại sẽ dẫn đến một ngoại lệ google.api_core.exceptions.AlreadyExists do thư viện ứng dụng gửi, được tập lệnh xử lý một cách suôn sẻ:
$ python3 maker.py Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq' Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'
Nếu bạn mới sử dụng Pub/Sub, hãy xem Sách trắng về kiến trúc Pub/Sub để biết thêm thông tin chi tiết.
5. Cập nhật cấu hình
Các nội dung cập nhật trong cấu hình bao gồm cả việc thay đổi nhiều tệp cấu hình cũng như tạo nội dung tương đương với hàng đợi kéo của App Engine nhưng nằm trong hệ sinh thái Cloud Pub/Sub.
Xoá queue.yaml
Chúng tôi sẽ loại bỏ hoàn toàn Hàng đợi tác vụ, vì vậy, hãy xoá queue.yaml vì Pub/Sub không dùng tệp này. Thay vì tạo một hàng đợi kéo, bạn sẽ tạo một chủ đề Pub/Sub (và gói thuê bao).
requirements.txt
Nối cả google-cloud-ndb và google-cloud-pubsub vào requirements.txt để kết hợp flask từ Phụ lục 18. requirements.txt của Mô-đun 19 sau khi cập nhật sẽ có dạng như sau:
flask
google-cloud-ndb
google-cloud-pubsub
Tệp requirements.txt này không có số phiên bản, tức là các phiên bản mới nhất sẽ được chọn. Nếu có bất kỳ vấn đề không tương thích nào, hãy làm theo phương pháp tiêu chuẩn là sử dụng số phiên bản để khoá các phiên bản hoạt động cho một ứng dụng.
app.yaml
Những thay đổi đối với app.yaml sẽ khác nhau tuỳ thuộc vào việc bạn tiếp tục dùng Python 2 hay nâng cấp lên Python 3.
Python 2
Bản cập nhật trên cho requirements.txt bổ sung việc sử dụng thư viện ứng dụng Google Cloud. Những thư viện này cần có sự hỗ trợ bổ sung từ App Engine, cụ thể là một số thư viện tích hợp sẵn, setuptools và grpcio. Việc sử dụng các thư viện tích hợp sẵn yêu cầu phải có phần libraries trong app.yaml và số phiên bản thư viện hoặc "mới nhất" cho phiên bản mới nhất có trên máy chủ App Engine. Mô-đun 18 app.yaml chưa có một trong các phần đó:
TRƯỚC:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Thêm một phần libraries vào app.yaml cùng với các mục nhập cho cả setuptools và grpcio, chọn phiên bản mới nhất của chúng. Ngoài ra, hãy thêm một mục giữ chỗ runtime cho Python 3, được nhận xét cùng với bản phát hành 3.x hiện tại, ví dụ: 3.10, tại thời điểm viết bài này. Với những thay đổi này, app.yaml hiện sẽ có dạng như sau:
SAU:
#runtime: python310
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: setuptools
version: latest
- name: grpcio
version: latest
Python 3
Đối với người dùng Python 3 và app.yaml, tất cả đều là về việc xoá các thành phần. Trong phần này, bạn sẽ xoá phần handlers, các chỉ thị threadsafe và api_version, đồng thời không tạo phần libraries.
Các môi trường thời gian chạy thế hệ thứ hai không cung cấp các thư viện tích hợp sẵn của bên thứ ba, vì vậy, bạn không cần phần libraries trong app.yaml. Hơn nữa, bạn không cần phải sao chép (đôi khi còn gọi là cung cấp hoặc tự đóng gói) các gói không phải của bên thứ ba. Bạn chỉ cần liệt kê các thư viện của bên thứ ba mà ứng dụng của bạn sử dụng trong requirements.txt.
Phần handlers trong app.yaml dùng để chỉ định trình xử lý tệp tĩnh và ứng dụng (tập lệnh). Vì thời gian chạy Python 3 yêu cầu các khung web thực hiện định tuyến riêng, nên bạn phải thay đổi tất cả trình xử lý tập lệnh thành auto. Nếu ứng dụng của bạn (như Module 18) không phân phát các tệp tĩnh, thì tất cả các tuyến đường sẽ là auto, khiến chúng không liên quan. Do đó, bạn cũng không cần đến phần handlers, nên hãy xoá phần đó.
Cuối cùng, cả chỉ thị threadsafe và api_version đều không được dùng trong Python 3, vì vậy, hãy xoá cả hai chỉ thị này. Điểm mấu chốt là bạn nên xoá tất cả các phần của app.yaml để chỉ còn lại chỉ thị runtime, chỉ định một phiên bản Python 3 hiện đại, chẳng hạn như 3.10. Sau đây là giao diện của app.yaml trước và sau khi có những nội dung cập nhật này:
TRƯỚC:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
SAU:
runtime: python310
Đối với những người chưa sẵn sàng xoá mọi thứ khỏi app.yaml cho Python 3, chúng tôi đã cung cấp một tệp thay thế app3.yaml trong thư mục kho lưu trữ Mô-đun 19. Nếu bạn muốn sử dụng tệp này cho các hoạt động triển khai, hãy nhớ thêm tên tệp này vào cuối lệnh: gcloud app deploy app3.yaml (nếu không, tệp này sẽ mặc định và triển khai ứng dụng của bạn bằng tệp app.yaml Python 2 mà bạn không thay đổi).
appengine_config.py
Nếu đang nâng cấp lên Python 3, bạn không cần đến appengine_config.py nên có thể xoá thành phần hiển thị này. Lý do không cần thiết là vì tính năng hỗ trợ thư viện bên thứ ba chỉ yêu cầu bạn chỉ định các thư viện đó trong requirements.txt. Người dùng Python 2, hãy đọc tiếp.
appengine_config.py của Mô-đun 18 có mã phù hợp để hỗ trợ các thư viện bên thứ ba, ví dụ: Flask và các thư viện ứng dụng Cloud vừa được thêm vào requirements.txt:
TRƯỚC:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Tuy nhiên, chỉ mã này thôi là chưa đủ để hỗ trợ các thư viện tích hợp vừa được thêm (setuptools, grpcio). Bạn cần thêm một vài dòng nữa, vì vậy hãy cập nhật appengine_config.py để có dạng như sau:
SAU:
import pkg_resources
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)
Bạn có thể xem thêm thông tin chi tiết về những thay đổi cần thiết để hỗ trợ các thư viện ứng dụng Cloud trong tài liệu về việc di chuyển các dịch vụ đi kèm.
Các nội dung cập nhật khác về cấu hình
Nếu bạn có thư mục lib, hãy xoá thư mục đó. Nếu bạn là người dùng Python 2, hãy bổ sung thư mục lib bằng cách đưa ra lệnh sau:
pip install -t lib -r requirements.txt # or pip2
Nếu đã cài đặt cả Python 2 và 3 trên hệ thống phát triển, bạn có thể cần dùng pip2 thay vì pip.
6. Sửa đổi mã xử lý ứng dụng
Phần này có các nội dung cập nhật cho tệp ứng dụng chính, main.py, thay thế việc sử dụng hàng đợi kéo của Hàng đợi tác vụ App Engine bằng Cloud Pub/Sub. Không có thay đổi nào đối với mẫu trang web templates/index.html. Cả hai ứng dụng đều hoạt động giống hệt nhau và hiển thị cùng một dữ liệu.
Cập nhật các hoạt động nhập và khởi tạo
Có một số điểm cập nhật đối với hoạt động nhập và khởi tạo:
- Đối với các hoạt động nhập, hãy thay thế App Engine NDB và Hàng đợi tác vụ bằng Cloud NDB và Pub/Sub.
- Đổi tên
pullqtừ tênQUEUEthành tênTOPIC. - Với các tác vụ kéo, nhân viên thuê chúng trong một giờ, nhưng với Pub/Sub, thời gian chờ được đo lường trên cơ sở từng thông báo, vì vậy, hãy xoá hằng số
HOUR. - Cloud APIs yêu cầu sử dụng một ứng dụng khách API, vì vậy, hãy khởi tạo các API đó cho Cloud NDB và Cloud Pub/Sub, trong đó Cloud Pub/Sub cung cấp ứng dụng khách cho cả chủ đề và gói thuê bao.
- Pub/Sub yêu cầu mã dự án trên đám mây, vì vậy, hãy nhập và lấy mã này từ
google.auth.default(). - Pub/Sub yêu cầu "tên đường dẫn đủ điều kiện" cho các chủ đề và gói thuê bao, vì vậy, hãy tạo các tên đường dẫn đó bằng cách sử dụng các hàm tiện ích
*_path().
Dưới đây là các hoạt động nhập và khởi tạo từ Mô-đun 18, sau đó là cách các phần sẽ xuất hiện sau khi triển khai các thay đổi ở trên, trong đó hầu hết mã mới là các tài nguyên Pub/Sub:
TRƯỚC:
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb
HOUR = 3600
LIMIT = 10
TASKS = 1000
QNAME = 'pullq'
QUEUE = taskqueue.Queue(QNAME)
app = Flask(__name__)
SAU:
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, pubsub
LIMIT = 10
TASKS = 1000
TOPIC = 'pullq'
SBSCR = 'worker'
app = Flask(__name__)
ds_client = ndb.Client()
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
_, PROJECT_ID = google.auth.default()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
Truy cập vào phần cập nhật mô hình dữ liệu
Mô hình dữ liệu Visit không thay đổi. Để truy cập vào Datastore, bạn cần sử dụng rõ ràng trình quản lý bối cảnh ứng dụng Cloud NDB API, ds_client.context(). Trong mã, điều này có nghĩa là bạn sẽ bao bọc các lệnh gọi Datastore trong cả store_visit() và fetch_visits() bên trong các khối with của Python. Bản cập nhật này giống hệt với nội dung trong Mô-đun 2.
Thay đổi phù hợp nhất đối với Pub/Sub là thay thế việc xếp hàng một tác vụ kéo Hàng đợi tác vụ bằng việc xuất bản một thông báo Pub/Sub cho chủ đề pullq. Dưới đây là mã trước và sau khi thực hiện những nội dung cập nhật này:
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 in Datastore and queue request to bump visitor count'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
QUEUE.add(taskqueue.Task(payload=remote_addr, method='PULL'))
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)
def store_visit(remote_addr, user_agent):
'create new Visit in Datastore and queue request to bump visitor count'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
ppc_client.publish(TOP_PATH, remote_addr.encode('utf-8'))
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Nội dung cập nhật về mô hình dữ liệu VisitorCount
Mô hình dữ liệu VisitorCount không thay đổi và không fetch_counts(), ngoại trừ việc bao bọc truy vấn Datastore bên trong một khối with, như minh hoạ dưới đây:
TRƯỚC:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
SAU:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
with ds_client.context():
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
Cập nhật mã worker
Mã worker cập nhật trong phạm vi thay thế NDB bằng Cloud NDB và Task Queue bằng Pub/Sub, nhưng quy trình của mã này vẫn giữ nguyên.
- Bao bọc các lệnh gọi Datastore trong khối trình quản lý ngữ cảnh Cloud NDB
with. - Dọn dẹp Hàng đợi tác vụ bao gồm việc xoá tất cả các tác vụ khỏi hàng đợi kéo. Với Pub/Sub, "mã nhận dạng xác nhận" được thu thập trong
acksrồi bị xoá/xác nhận ở cuối. - Các tác vụ kéo của Hàng đợi tác vụ được cho thuê theo cách tương tự như các thông báo Pub/Sub được kéo. Mặc dù việc xoá các tác vụ kéo được thực hiện bằng chính các đối tượng tác vụ, nhưng các thông báo Pub/Sub sẽ bị xoá thông qua mã nhận dạng xác nhận của chúng.
- Tải trọng thông báo Pub/Sub yêu cầu byte (không phải chuỗi Python), vì vậy, có một số hoạt động mã hoá và giải mã UTF-8 khi xuất bản và kéo thông báo từ một chủ đề, tương ứng.
Thay thế log_visitors() bằng đoạn mã đã cập nhật bên dưới để triển khai những thay đổi vừa mô tả:
TRƯỚC:
@app.route('/log')
def log_visitors():
'worker processes recent visitor counts and updates them in Datastore'
# tally recent visitor counts from queue then delete those tasks
tallies = {}
tasks = QUEUE.lease_tasks(HOUR, TASKS)
for task in tasks:
visitor = task.payload
tallies[visitor] = tallies.get(visitor, 0) + 1
if tasks:
QUEUE.delete_tasks(tasks)
# increment those counts in Datastore and return
for visitor in tallies:
counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
if not counter:
counter = VisitorCount(visitor=visitor, counter=0)
counter.put()
counter.counter += tallies[visitor]
counter.put()
return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
len(tasks), len(tallies))
SAU:
@app.route('/log')
def log_visitors():
'worker processes recent visitor counts and updates them in Datastore'
# tally recent visitor counts from queue then delete those tasks
tallies = {}
acks = set()
rsp = psc_client.pull(subscription=SUB_PATH, max_messages=TASKS)
msgs = rsp.received_messages
for rcvd_msg in msgs:
acks.add(rcvd_msg.ack_id)
visitor = rcvd_msg.message.data.decode('utf-8')
tallies[visitor] = tallies.get(visitor, 0) + 1
if acks:
psc_client.acknowledge(subscription=SUB_PATH, ack_ids=acks)
try:
psc_client.close()
except AttributeError: # special handler for grpcio<1.12.0
pass
# increment those counts in Datastore and return
if tallies:
with ds_client.context():
for visitor in tallies:
counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
if not counter:
counter = VisitorCount(visitor=visitor, counter=0)
counter.put()
counter.counter += tallies[visitor]
counter.put()
return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
len(msgs), len(tallies))
Không có thay đổi nào đối với trình xử lý ứng dụng chính root(). Bạn cũng không cần thay đổi tệp mẫu HTML templates/index.html. Như vậy là bạn đã hoàn tất mọi nội dung cập nhật cần thiết. Chúc mừng bạn đã đến được ứng dụng Mô-đun 19 mới bằng Cloud Pub/Sub!
7. Tóm tắt/Dọn dẹp
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. Ngoài ra, hãy chạy worker để xử lý số lượt truy cập. 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
Đảm bảo bạn đã tạo chủ đề pullq và gói thuê bao worker. Nếu bạn đã hoàn tất bước này và ứng dụng mẫu đã sẵn sàng hoạt động, hãy triển khai ứng dụng bằng gcloud app deploy. Đầu ra sẽ giống hệt với ứng dụng trong Mô-đun 18, ngoại trừ việc bạn đã thay thế thành công toàn bộ cơ chế xếp hàng cơ bản:

Giờ đây, giao diện người dùng web của ứng dụng sẽ xác minh phần này của ứng dụng. Mặc dù phần này của ứng dụng truy vấn và hiển thị thành công những khách truy cập hàng đầu và lượt truy cập gần đây nhất, nhưng hãy nhớ rằng ứng dụng sẽ đăng ký lượt truy cập này cùng với việc tạo một tác vụ kéo để thêm khách truy cập này vào tổng số lượt truy cập. Giờ đây, tác vụ đó nằm trong hàng đợi chờ xử lý.
Bạn có thể thực thi việc này bằng dịch vụ phụ trợ App Engine, một công việc cron, duyệt đến /log hoặc đưa ra yêu cầu HTTP dòng lệnh. Sau đây là một ví dụ về việc thực thi và gọi mã worker bằng curl (thay thế PROJECT_ID của bạn):
$ curl https://PROJECT_ID.appspot.com/log DONE (with 1 task[s] logging 1 visitor[s])
Sau đó, số lượt truy cập đã cập nhật sẽ xuất hiện trong lần truy cập tiếp theo vào trang web. Vậy là xong!
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 bị tính phí. Tuy nhiên, nếu muốn kiểm thử hoặc thử nghiệm thêm, nền tảng App Engine có một hạn mức miễn phí. Vì vậy, miễn là không vượt quá cấp sử dụng đó, bạn sẽ không bị tính phí. Đó là mức phí cho hoạt động tính toán, nhưng cũng có thể có các khoản phí cho các dịch vụ App Engine có liên quan. Vì vậy, hãy xem trang định 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ụ đám mây khác, 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.
Để công bố đầy đủ, việc triển khai trê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 một khoản chi phí nhỏ cho việc tạo và lưu trữ. 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ẽ chiếm một phần hạn mức. Tuy nhiên, có thể bạn sinh sống ở một khu vực không có gói miễn phí như vậy, vì vậy, hãy lưu ý đến mức sử dụng bộ nhớ để giảm thiểu chi phí phát sinh. Bạn nên xem xét các "thư mục" cụ thể trên Cloud Storage, 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*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.
Cụ thể đối với lớp học lập trình này
Các dịch vụ trong danh sách dưới đây là riêng biệt đối với 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 thành phần khác nhau của Cloud Pub/Sub đều có một bậc miễn phí; hãy xác định mức sử dụng tổng thể của bạn để hiểu rõ hơn về các tác động đến chi phí và xem trang định giá của dịch vụ này để biết thêm thông tin chi tiết.
- Dịch vụ App Engine Datastore do Cloud Datastore (Cloud Firestore ở chế độ Datastore) cung cấp, dịch vụ này cũng có một cấp miễn phí; hãy xem trang định giá của dịch vụ này để biết thêm thông tin.
Các bước tiếp theo
Ngoài hướng dẫn này, bạn nên cân nhắc các mô-đun di chuyển khác tập trung vào việc chuyển từ các dịch vụ cũ đi kèm, bao gồm:
- Mô-đun 2: di chuyển từ
ndbApp Engine sang Cloud NDB - Các mô-đun 7-9: di chuyển từ Hàng đợi tác vụ App Engine (đẩy tác vụ) sang Cloud Tasks
- Các mô-đun 12 – 13: di chuyển từ App Engine Memcache sang Cloud Memorystore
- Các mô-đun 15-16: di chuyển từ Blobstore của App Engine sang Cloud Storage
App Engine không còn là nền tảng duy nhất không cần máy chủ trên Google Cloud nữa. Nếu bạn có một ứng dụng App Engine nhỏ hoặc một ứng dụng có chức năng hạn chế và muốn biến ứng dụng đó thành một vi dịch vụ độc lập, hoặc bạn muốn chia một ứng dụng nguyên khối thành nhiều thành phần có thể dùng lại, thì đây là những lý do chính đáng để cân nhắc việc chuyển sang Cloud Functions. Nếu việc tạo vùng chứa đã trở thành một phần trong quy trình phát triển ứng dụng của bạn, đặc biệt là nếu quy trình này bao gồm một quy trình CI/CD (tích hợp liên tục/phân phối liên tục hoặc triển khai liên tục), hãy cân nhắc việc di chuyển sang Cloud Run. Các trường hợp này được đề cập trong các mô-đun sau:
- Di chuyển từ App Engine sang Cloud Functions: xem Mô-đun 11
- Di chuyển từ App Engine sang Cloud Run: xem Mô-đun 4 để đóng gói ứng dụng của bạn bằng Docker hoặc Mô-đùn 5 để thực hiện việc này mà không cần vùng chứa, kiến thức về Docker hoặc
Dockerfile
Bạn không bắt buộc phải chuyển sang một nền tảng không máy chủ khác. Bạn nên cân nhắc những lựa chọn phù hợp nhất cho ứng dụng và trường hợp sử dụng của mình trước khi thực hiện bất kỳ thay đổi nào.
Bất kể bạn cân nhắc mô-đun di chuyển nào tiếp theo, bạn đều có thể truy cập vào tất cả nội dung của Serverless Migration Station (lớp học lập trình, video, mã nguồn [nếu có]) tại kho lưu trữ nguồn mở. README của kho lưu trữ này cũng cung cấp hướng dẫn về những hoạt động di chuyển cần cân nhắc và "thứ tự" liên quan của các Mô-đun di chuyển.
8. Tài nguyên khác
Dưới đây là các tài nguyên bổ sung dành cho những nhà phát triển muốn tìm hiểu thêm về Mô-đun di chuyển này hoặc các mô-đun di chuyển có liên quan, cũng như các sản phẩm có liên quan. Trong đó có những nơi để bạn gửi ý kiến phản hồi về nội dung này, đường liên kết đến mã và nhiều phần tài liệu mà bạn có thể thấy hữu ích.
Vấn đề/ý kiến phản hồi về Lớp học lập trình
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 kiếm vấn đề của bạn trước khi 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 18 (BẮT ĐẦU) và Mô-đun 19 (KẾT THÚC) trong bảng bên dưới.
Lớp học lập trình | Python 2 | Python 3 |
(không áp dụng) | ||
Mô-đun 19 (lớp học lập trình này) | (tương tự như Python 2, ngoại trừ việc sử dụng app3.yaml, trừ phi bạn đã cập nhật app.yaml như đã đề cập ở trên) |
Tài liệu tham khảo trực tuyến
Dưới đây là các tài nguyên liên quan đến hướng dẫn này:
Hàng đợi tác vụ App Engine
- Tổng quan về Hàng đợi tác vụ của App Engine
- Tổng quan về hàng đợi kéo của Hàng đợi tác vụ App Engine
- Ứng dụng mẫu đầy đủ của hàng đợi kéo Hàng đợi tác vụ App Engine
- Tạo hàng đợi kéo Task Queue
- Video ra mắt hàng đợi kéo Google I/O 2011 ( Ứng dụng mẫu Votelator)
queue.yamltài liệu tham khảoqueue.yamlso với Cloud Tasks- Hướng dẫn di chuyển hàng đợi kéo sang Pub/Sub
Cloud Pub/Sub
- Trang sản phẩm Cloud Pub/Sub
- Sử dụng thư viện ứng dụng Pub/Sub
- Mẫu thư viện ứng dụng Pub/Sub Python
- Tài liệu về thư viện ứng dụng Pub/Sub Python
- Tạo và quản lý chủ đề Pub/Sub
- Nguyên tắc đặt tên chủ đề Pub/Sub
- Tạo và quản lý gói thuê bao Pub/Sub
- Ứng dụng mẫu App Engine (Linh hoạt) (cũng có thể triển khai cho phiên bản Chuẩn; Python 3)
- Kho lưu trữ cho ứng dụng mẫu ở trên
- Gói thuê bao Pub/Sub kéo
- Gói thuê bao Pub/Sub push
- Ứng dụng mẫu đẩy Pub/Sub của App Engine (Python 3)
- Kho lưu trữ ứng dụng mẫu đẩy Pub/Sub của App Engine
- Thông tin về giá của Pub/Sub
- Cloud Tasks hay Cloud Pub/Sub? (đẩy so với kéo)
App Engine NDB và Cloud NDB (Datastore)
- Tài liệu về NDB của App Engine
- Kho lưu trữ NDB của App Engine
- Tài liệu về NDB của Google Cloud
- Kho lưu trữ NDB của Google Cloud
- Thông tin về giá của Cloud Datastore
Nền tảng App Engine
- Tài liệu về App Engine
- Thời gian chạy Python 2 App Engine (môi trường tiêu chuẩn)
- Sử dụng các thư viện tích hợp sẵn của App Engine trên App Engine Python 2
- Thời gian chạy Python 3 App Engine (môi trường tiêu chuẩn)
- Sự khác biệt giữa thời gian chạy Python 2 và 3 App Engine (môi trường tiêu chuẩn)
- Hướng dẫn di chuyển ứng dụng từ Python 2 sang Python 3 trên App Engine (môi trường tiêu chuẩn)
- 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ứ hai
- Hỗ trợ dài hạn cho các thời gian chạy cũ
- Các mẫu di chuyển tài liệu
- Các mẫu di chuyển do cộng đồng đóng góp
Thông tin khác về Cloud
- Python trên Google Cloud Platform
- Thư viện ứng dụng Google Cloud Python
- Cấp "Luôn miễn phí" của Google Cloud
- SDK Google Cloud (công cụ dòng lệnh
gcloud) - Tất cả tài liệu của Google Cloud
Video
- Serverless Migration Station
- Expeditions không cần máy chủ
- Đăng ký theo dõi Google Cloud Tech
- Đăng ký theo dõi 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.