Di chuyển & NDB App Engine Cloud của Python 2 Ứng dụng Cloud Tasks sang Python 3 và Cloud Datastore (Mô-đun 9)

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 FunctionsCloud 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à chuyển ứng dụng mẫu trong Mô-đun 8 sang Python 3, cũng như chuyển quyền truy cập kho dữ liệu (Cloud Firestore ở chế độ kho dữ liệu) từ việc sử dụng Cloud NDB sang thư viện ứng dụng Cloud Datastore gốc và nâng cấp lên phiên bản mới nhất của thư viện ứng dụng Cloud Tasks.

Chúng tôi đã thêm việc sử dụng Hàng đợi tác vụ cho các tác vụ đẩy trong Mô-đun 7, sau đó di chuyển việc sử dụng đó sang Cloud Tasks trong Mô-đun 8. Trong Mô-đun 9 này, chúng ta sẽ tiếp tục tìm hiểu về Python 3 và Cloud Datastore. Những người sử dụng Hàng đợi tác vụ cho các tác vụ kéo sẽ di chuyển sang Cloud Pub/Sub và nên tham khảo các Mô-đun 18-19.

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

  • Chuyển ứng dụng mẫu trong Mô-đun 8 sang Python 3
  • Chuyển quyền truy cập Datastore từ Cloud NDB sang thư viện ứng dụng Cloud Datastore
  • Nâng cấp lên phiên bản thư viện ứng dụng Cloud Tasks mới nhất

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 qua Đọc và hoàn thành các bài tập

Bạn đánh giá thế nào về trải nghiệm của mình với Python?

Người mới bắt đầu Trung cấp Thành thạo

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?

Người mới bắt đầu Trung cấp Thành thạo

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

Mô-đun 7 minh hoạ cách sử dụng các tác vụ đẩy của hàng đợi tác vụ App Engine trong các ứng dụng App Engine Python 2 Flask. Trong Học phần 8, bạn sẽ di chuyển ứng dụng đó từ Hàng đợi tác vụ sang Cloud Tasks. Trong Mô-đun 9, bạn sẽ tiếp tục hành trình đó và chuyển ứng dụng sang Python 3 cũng như chuyển quyền truy cập kho dữ liệu từ việc sử dụng Cloud NDB sang thư viện ứng dụng Cloud Datastore gốc.

Vì Cloud NDB hoạt động cho cả Python 2 và 3, nên người dùng App Engine chỉ cần chuyển ứng dụng của họ từ Python 2 sang 3. Việc di chuyển thêm các thư viện ứng dụng sang Cloud Datastore là hoàn toàn không bắt buộcchỉ có một lý do để cân nhắc việc này: bạn có các ứng dụng không phải App Engine (và/hoặc các ứng dụng App Engine Python 3) đã sử dụng thư viện ứng dụng Cloud Datastore và muốn hợp nhất cơ sở mã để truy cập vào Datastore chỉ bằng một thư viện ứng dụng. Cloud NDB được tạo riêng cho nhà phát triển Python 2 App Engine dưới dạng một công cụ di chuyển Python 3. Vì vậy, nếu chưa có mã sử dụng thư viện ứng dụng Cloud Datastore, bạn không cần cân nhắc việc di chuyển này.

Cuối cùng, việc phát triển thư viện ứng dụng Cloud Tasks sẽ chỉ tiếp tục trong Python 3, vì vậy, chúng tôi đang "di chuyển" từ một trong những phiên bản Python 2 cuối cùng sang phiên bản Python 3 tương ứng. May mắn là không có thay đổi nào từ Python 2, tức là bạn không cần làm gì khác ở đây.

Hướng dẫn này có các bước sau:

  1. Thiết lập/Công việc chuẩn bị
  2. Cập nhật cấu hình
  3. 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:

  1. Thiết lập dự án trên đám mây
  2. Tải ứng dụng mẫu cơ sở
  3. (Triển khai lại) và xác thực ứng dụng cơ sở

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 8, 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 8: hoàn thành lớp học lập trình Mô-đun 8 (nên dùng) hoặc sao chép ứng dụng Mô-đun 8 từ kho lưu trữ. Dù bạn dùng mã của mình hay của chúng tôi, mã của Mô-đun 8 sẽ là nơi chúng ta 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ữ của Mô-đun 9 ("FINISH").

Bất kể bạn sử dụng ứng dụng nào trong Mô-đun 7, 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     requirements.txt
app.yaml                main.py                 templates

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

  1. Xoá thư mục lib (nếu có) rồi chạy pip install -t lib -r requirements.txt để điền lại lib. Bạn có thể cần dùng pip2 nếu đã cài đặt cả Python 2 và 3 trên máy phát triển.
  2. Đảm bảo bạn đã cài đặtkhở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.
  3. (không bắt buộc) Đặt dự án trên Đám mây bằng gcloud config set project PROJECT_ID nếu bạn không muốn nhập PROJECT_ID cho mỗi lệnh gcloud mà bạn đưa ra.
  4. Triển khai ứng dụng mẫu bằng gcloud app deploy
  5. 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 8, 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). Ở dưới cùng là thông tin về những việc cần làm cũ sẽ bị xoá.

4aa8a2cb5f527079.png

4. Cập nhật cấu hình

requirements.txt

requirements.txt mới gần giống với requirements.txt của Mô-đun 8, chỉ có một thay đổi lớn: thay thế google-cloud-ndb bằng google-cloud-datastore. Hãy thực hiện thay đổi này để tệp requirements.txt của bạn có dạng như sau:

flask
google-cloud-datastore
google-cloud-tasks

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ỳ điểm không tương thích nào, việc sử dụng số phiên bản để khoá các phiên bản hoạt động cho một ứng dụng là phương pháp tiêu chuẩn.

app.yaml

Thời gian chạy App Engine thế hệ thứ hai không hỗ trợ các thư viện tích hợp sẵn của bên thứ ba như trong phiên bản 2.x, cũng như không hỗ trợ việc sao chép các thư viện không tích hợp sẵn. Yêu cầu duy nhất đối với các gói của bên thứ ba là bạn phải liệt kê chúng trong requirements.txt. Do đó, bạn có thể xoá toàn bộ phần libraries của app.yaml.

Một điểm cập nhật khác là thời gian chạy Python 3 yêu cầu sử dụng các khung web tự định tuyến. Do đó, bạn phải thay đổi tất cả trình xử lý tập lệnh thành auto. Tuy nhiên, vì tất cả các tuyến đường đều phải được thay đổi thành auto và không có tệp tĩnh nào được phân phát từ ứng dụng mẫu này, nên việc có bất kỳ trình xử lý nào là không liên quan, vì vậy, hãy xoá toàn bộ phần handlers.

Điều duy nhất cần thiết trong app.yaml là đặt thời gian chạy thành một phiên bản Python 3 được hỗ trợ, chẳng hạn như 3.10. Hãy thay đổi để app.yaml mới, viết tắt chỉ có một dòng như sau:

runtime: python310

Xoá appengine_config.py và lib

Thế hệ tiếp theo của thời gian chạy App Engine cải tiến việc sử dụng gói của bên thứ ba:

  • Thư viện tích hợp là những thư viện được Google kiểm tra và cung cấp trên các máy chủ App Engine, có thể là do chúng chứa mã C/C++ mà nhà phát triển không được phép triển khai lên đám mây. Những thư viện này không còn có trong thời gian chạy thế hệ thứ 2 nữa.
  • Bạn không cần sao chép các thư viện không tích hợp sẵn (đôi khi được gọi là "vendoring" hoặc "self-bundling") trong thời gian chạy thế hệ thứ 2. Thay vào đó, chúng phải được liệt kê trong requirements.txt, nơi hệ thống xây dựng tự động cài đặt chúng thay cho bạn tại thời điểm triển khai.

Do những thay đổi đó đối với việc quản lý gói của bên thứ ba, bạn không cần tệp appengine_config.py cũng như thư mục lib, vì vậy hãy xoá chúng. Trong thời gian chạy thế hệ thứ 2, App Engine sẽ tự động cài đặt các gói của bên thứ ba có trong requirements.txt. Tóm tắt:

  1. Không có thư viện tự đóng gói hoặc sao chép của bên thứ ba; hãy liệt kê các thư viện đó trong requirements.txt
  2. Không có pip install nào trong thư mục lib, tức là không có thư mục lib nào
  3. Không có thư viện tích hợp sẵn của bên thứ ba (do đó không có phần libraries) trong app.yaml; liệt kê các thư viện đó trong requirements.txt
  4. Không có thư viện bên thứ ba nào để tham chiếu từ ứng dụng của bạn, tức là không có tệp appengine_config.py

Yêu cầu duy nhất đối với nhà phát triển là liệt kê tất cả các thư viện bên thứ ba mong muốn trong requirements.txt.

5. Cập nhật tệp ứng dụng

Chỉ có một tệp ứng dụng, main.py, nên mọi thay đổi trong phần này chỉ ảnh hưởng đến tệp đó. Dưới đây là hình minh hoạ "diffs" (khác biệt) về những thay đổi tổng thể cần thực hiện để tái cấu trúc mã hiện có thành ứng dụng mới. Người đọc không cần đọc từng dòng mã, vì mục đích của hình minh hoạ này chỉ là để có được cái nhìn tổng quan bằng hình ảnh về những gì cần thiết trong quá trình tái cấu trúc này (nhưng bạn có thể mở trong Tab mới hoặc tải xuống và phóng to nếu muốn).

5d043768ba7be742.png

Cập nhật các hoạt động nhập và khởi tạo

Phần nhập trong main.py cho Mô-đun 8 sử dụng Cloud NDB và Cloud Tasks; phần này sẽ có dạng như sau:

TRƯỚC:

from datetime import datetime
import json
import logging
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, tasks

app = Flask(__name__)
ds_client = ndb.Client()
ts_client = tasks.CloudTasksClient()

Tính năng ghi nhật ký được đơn giản hoá và cải thiện trong thời gian chạy thế hệ thứ hai như Python 3:

  • Để có trải nghiệm ghi nhật ký toàn diện, hãy sử dụng Cloud Logging
  • Để ghi nhật ký đơn giản, chỉ cần gửi đến stdout (hoặc stderr) qua print()
  • Bạn không cần sử dụng mô-đun logging của Python (nên hãy xoá mô-đun này)

Do đó, hãy xoá lệnh nhập logging và thay thế google.cloud.ndb bằng google.cloud.datastore. Tương tự, hãy thay đổi ds_client để trỏ đến một máy khách Datastore thay vì máy khách NDB. Sau khi bạn thực hiện những thay đổi này, phần trên cùng của ứng dụng mới sẽ có dạng như sau:

SAU:

from datetime import datetime
import json
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import datastore, tasks

app = Flask(__name__)
ds_client = datastore.Client()
ts_client = tasks.CloudTasksClient()

Di chuyển sang Cloud Datastore

Giờ là lúc bạn thay thế việc sử dụng thư viện ứng dụng NDB bằng Datastore. Cả App Engine NDB và Cloud NDB đều yêu cầu một mô hình dữ liệu (lớp); đối với ứng dụng này, đó là Visit. Hàm store_visit() hoạt động giống nhau trong tất cả các mô-đun di chuyển khác: hàm này đăng ký một lượt truy cập bằng cách tạo một bản ghi Visit mới, lưu địa chỉ IP và tác nhân người dùng (loại trình duyệt) của một máy khách truy cập.

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'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

Tuy nhiên, Cloud Datastore không sử dụng lớp mô hình dữ liệu, vì vậy, hãy xoá lớp này. Ngoài ra, Cloud Datastore không tự động tạo dấu thời gian khi bản ghi được tạo, bạn phải thực hiện việc này theo cách thủ công bằng lệnh gọi datetime.now().

Nếu không có lớp dữ liệu, store_visit() đã sửa đổi của bạn sẽ có dạng như sau:

SAU:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    entity = datastore.Entity(key=ds_client.key('Visit'))
    entity.update({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })
    ds_client.put(entity)

Chức năng chính là fetch_visits(). Thao tác này không chỉ thực hiện truy vấn ban đầu cho Visit mới nhất mà còn lấy dấu thời gian của Visit gần đây nhất được hiển thị và tạo tác vụ đẩy gọi /trim (do đó trim()) để xoá hàng loạt Visit cũ. Sau đây là cách sử dụng Cloud NDB:

TRƯỚC:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    with ds_client.context():
        data = Visit.query().order(-Visit.timestamp).fetch(limit)
    oldest = time.mktime(data[-1].timestamp.timetuple())
    oldest_str = time.ctime(oldest)
    logging.info('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return (v.to_dict() for v in data), oldest_str

Những thay đổi chính:

  1. Thay thế truy vấn Cloud NDB bằng truy vấn tương đương trên Cloud Datastore; các kiểu truy vấn có chút khác biệt.
  2. Datastore không yêu cầu bạn sử dụng trình quản lý bối cảnh cũng như không yêu cầu bạn trích xuất dữ liệu của trình quản lý này (bằng to_dict()) như Cloud NDB.
  3. Thay thế các lệnh gọi ghi nhật ký bằng print()

Sau những thay đổi đó, fetch_visits() sẽ có dạng như sau:

SAU:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Đây thường là tất cả những gì cần thiết. Rất tiếc, có một vấn đề lớn.

(Có thể) Tạo một hàng đợi (đẩy) mới

Trong Mô-đun 7, chúng ta đã thêm việc sử dụng App Engine taskqueue vào ứng dụng Mô-đun 1 hiện có. Một lợi ích chính của việc có các tác vụ truyền dữ liệu dưới dạng một tính năng cũ của App Engine là hệ thống sẽ tự động tạo một hàng đợi "mặc định". Khi ứng dụng đó được di chuyển sang Cloud Tasks trong Mô-đun 8, hàng đợi mặc định đó đã có sẵn, vì vậy, chúng ta vẫn không cần lo lắng về vấn đề này. Điều đó sẽ thay đổi ở Mô-đun 9.

Một khía cạnh quan trọng cần cân nhắc là ứng dụng App Engine mới không còn sử dụng các dịch vụ App Engine nữa. Do đó, bạn không thể giả định rằng App Engine tự động tạo một hàng đợi tác vụ trong một sản phẩm khác (Cloud Tasks). Như đã viết, việc tạo một tác vụ trong fetch_visits() (cho một hàng đợi không tồn tại) sẽ không thành công. Bạn cần một hàm mới để kiểm tra xem hàng đợi ("mặc định") có tồn tại hay không. Nếu không, hãy tạo một hàng đợi.

Gọi hàm này là _create_queue_if() và thêm hàm này vào ứng dụng của bạn ngay phía trên fetch_visits() vì đó là nơi hàm này được gọi. Nội dung của hàm cần thêm:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

Hàm create_queue() Cloud Tasks yêu cầu đường dẫn đầy đủ của hàng đợi ngoại trừ tên hàng đợi. Để đơn giản, hãy tạo một biến khác PATH_PREFIX đại diện cho QUEUE_PATH trừ đi tên hàng đợi (QUEUE_PATH.rsplit('/', 2)[0]). Thêm định nghĩa của biến này ở gần đầu để khối mã có tất cả các phép gán hằng số trông như sau:

_, PROJECT_ID = google.auth.default()
REGION_ID = 'REGION_ID'    # replace w/your own
QUEUE_NAME = 'default'     # replace w/your own
QUEUE_PATH = ts_client.queue_path(PROJECT_ID, REGION_ID, QUEUE_NAME)
PATH_PREFIX = QUEUE_PATH.rsplit('/', 2)[0]

Bây giờ, hãy sửa đổi dòng cuối cùng trong fetch_visits() để sử dụng _create_queue_if(), trước tiên tạo hàng đợi (nếu cần), sau đó tạo tác vụ:

    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Giờ đây, cả _create_queue_if()fetch_visits() đều có dạng như sau:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Ngoài việc phải thêm đoạn mã bổ sung này, phần còn lại của mã Cloud Tasks hầu như vẫn giữ nguyên so với Mô-đun 8. Đoạn mã cuối cùng cần xem là trình xử lý tác vụ.

Trình xử lý tác vụ cập nhật (đẩy)

Trong trình xử lý tác vụ trim(), mã Cloud NDB sẽ truy vấn các lượt truy cập cũ hơn lượt truy cập cũ nhất được hiển thị. Thao tác này sử dụng truy vấn chỉ có khoá để tăng tốc độ – tại sao phải tìm nạp tất cả dữ liệu nếu bạn chỉ cần mã nhận dạng lượt truy cập? Sau khi bạn có tất cả mã nhận dạng lượt truy cập, hãy xoá tất cả mã nhận dạng đó theo lô bằng hàm delete_multi() của Cloud NDB.

TRƯỚC:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    with ds_client.context():
        keys = Visit.query(
                Visit.timestamp < datetime.fromtimestamp(oldest)
        ).fetch(keys_only=True)
        nkeys = len(keys)
        if nkeys:
            logging.info('Deleting %d entities: %s' % (
                    nkeys, ', '.join(str(k.id()) for k in keys)))
            ndb.delete_multi(keys)
        else:
            logging.info(
                    'No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

Giống như fetch_visits(), phần lớn các thay đổi liên quan đến việc thay thế mã Cloud NDB bằng Cloud Datastore, điều chỉnh kiểu truy vấn, xoá việc sử dụng trình quản lý bối cảnh và thay đổi các lệnh gọi ghi nhật ký thành print().

SAU:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    query = ds_client.query(kind='Visit')
    query.add_filter('timestamp', '<', datetime.fromtimestamp(oldest))
    query.keys_only()
    keys = list(visit.key for visit in query.fetch())
    nkeys = len(keys)
    if nkeys:
        print('Deleting %d entities: %s' % (
                nkeys, ', '.join(str(k.id) for k in keys)))
        ds_client.delete_multi(keys)
    else:
        print('No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

Không có thay đổi nào đối với trình xử lý ứng dụng chính root().

Chuyển sang Python 3

Ứng dụng mẫu này được thiết kế để chạy trên cả Python 2 và 3. Mọi thay đổi dành riêng cho Python 3 đều được đề cập trước đó trong các phần liên quan của hướng dẫn này. Bạn không cần thực hiện thêm bước nào cũng như không cần thư viện tương thích.

Thông tin cập nhật về Cloud Tasks

Phiên bản cuối cùng của thư viện ứng dụng Cloud Tasks hỗ trợ Python 2 là 1.5.0. Tại thời điểm viết bài này, phiên bản mới nhất của thư viện ứng dụng cho Python 3 hoàn toàn tương thích với phiên bản đó, do đó, bạn không cần cập nhật thêm.

Cập nhật mẫu HTML

Bạn cũng không cần thay đổi gì trong tệp mẫu HTML, templates/index.html. Như vậy là bạn đã thực hiện xong mọi thay đổi cần thiết để có được ứng dụng Mô-đun 9.

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

Triển khai và xác minh ứng dụng

Sau khi hoàn tất việc cập nhật mã (chủ yếu là chuyển sang Python 3), hãy triển khai ứng dụng bằng gcloud app deploy. Đầu ra phải giống với các ứng dụng trong ứng dụng Mô-đun 7 và 8, ngoại trừ việc bạn đã chuyển quyền truy cập vào cơ sở dữ liệu sang thư viện ứng dụng Cloud Datastore và đã nâng cấp lên Python 3:

Ứng dụng visitme trong Mô-đun 7

Bước này hoàn tất lớp học lập trình. Bạn nên so sánh mã của mình với mã trong thư mục Mô-đun 9. Xin chúc mừng!

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/images
  • console.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_ID và *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 bước tiếp theo

Như vậy là chúng ta đã hoàn tất việc di chuyển từ các tác vụ đẩy của Hàng đợi tác vụ App Engine sang Cloud Tasks. Quá trình di chuyển không bắt buộc từ Cloud NDB sang Cloud Datastore cũng được đề cập riêng (không có Hàng đợi tác vụ hoặc Cloud Tasks) trong Mô-đun 3. Ngoài Mô-đun 3, bạn cũng 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ụ đi kèm cũ của App Engine:

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.

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 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 8 (BẮT ĐẦU) và Mô-đun 9 (KẾT THÚC) trong bảng bên dưới. Bạn cũng có thể truy cập vào các hướng dẫn này trong kho lưu trữ cho tất cả các hoạt động di chuyển codelab 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

Module 8

code

(không áp dụng)

Mô-đun 9

(không áp dụng)

code

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

Cloud NDB

Lưu trữ dữ liệu trên đám mây

Cloud Tasks

Thông tin khác về Cloud

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.