ย้ายข้อมูลจากงานพุชคิวงานของ App Engine ไปยัง Cloud Tasks (โมดูล 8)

1. ภาพรวม

ชุด Codelab ของ Serverless Migration Station (บทแนะนำแบบลงมือปฏิบัติจริงที่ทำตามได้ด้วยตนเอง) และวิดีโอที่เกี่ยวข้องมีจุดมุ่งหมายเพื่อช่วยให้นักพัฒนาแอป Google Cloud แบบไร้เซิร์ฟเวอร์ปรับปรุงแอปพลิเคชันให้ทันสมัยโดยแนะนำการย้ายข้อมูลอย่างน้อย 1 รายการ ซึ่งส่วนใหญ่เป็นการย้ายข้อมูลออกจากบริการเดิม การทำเช่นนี้จะทำให้แอปของคุณพกพาได้มากขึ้น และช่วยให้คุณมีตัวเลือกและความยืดหยุ่นมากขึ้น ซึ่งจะช่วยให้คุณผสานรวมและเข้าถึงผลิตภัณฑ์ระบบคลาวด์ที่หลากหลายยิ่งขึ้น รวมถึงอัปเกรดเป็นภาษาเวอร์ชันใหม่ๆ ได้ง่ายขึ้น แม้ว่าในตอนแรกจะมุ่งเน้นไปที่ผู้ใช้ Cloud รุ่นแรกๆ ซึ่งส่วนใหญ่เป็นนักพัฒนาซอฟต์แวร์ App Engine (สภาพแวดล้อมมาตรฐาน) แต่ชุดข้อมูลนี้ก็ครอบคลุมแพลตฟอร์มแบบไร้เซิร์ฟเวอร์อื่นๆ เช่น Cloud Functions และ Cloud Run หรือที่อื่นๆ หากเกี่ยวข้อง

Codelab นี้มีจุดประสงค์เพื่อแสดงให้นักพัฒนาแอป App Engine ที่ใช้ Python 2 ทราบวิธีย้ายข้อมูลจากคิวงานของ App Engine (งานแบบพุช) ไปยัง Cloud Tasks นอกจากนี้ ยังมีการย้ายข้อมูลโดยนัยจาก App Engine NDB ไปยัง Cloud NDB สำหรับการเข้าถึง Datastore (ซึ่งจะกล่าวถึงในโมดูลที่ 2 เป็นหลัก)

เราได้เพิ่มการใช้ งานงานแบบพุชในโมดูลที่ 7 และย้ายข้อมูลการใช้งานดังกล่าวไปยัง Cloud Tasks ในโมดูลที่ 8 จากนั้นจะไปยัง Python 3 และ Cloud Datastore ในโมดูลที่ 9 ผู้ที่ใช้คิวงานสำหรับงานดึงจะย้ายข้อมูลไปยัง Cloud Pub/Sub และควรดูโมดูลที่ 18-19 แทน

คุณจะได้เรียนรู้วิธีต่อไปนี้

สิ่งที่คุณต้องมี

แบบสำรวจ

คุณจะใช้บทแนะนำนี้อย่างไร

อ่านอย่างเดียว อ่านและทำแบบฝึกหัดให้เสร็จ

คุณจะให้คะแนนประสบการณ์การใช้งาน Python เท่าใด

ผู้ฝึกหัด ขั้นกลาง ผู้ชำนาญ

คุณจะให้คะแนนประสบการณ์การใช้บริการ Google Cloud เท่าใด

ผู้ฝึกหัด ขั้นกลาง ผู้ชำนาญ

2. ฉากหลัง

คิวงานของ App Engine รองรับทั้งงานแบบพุชและแบบดึง ทีม Google Cloud ขอแนะนำให้ย้ายข้อมูลจากบริการแบบแพ็กเกจเดิม เช่น Task Queue ไปยังบริการอื่นๆ แบบสแตนด์อโลนในระบบคลาวด์หรือบริการเทียบเท่าของบุคคลที่สาม เพื่อปรับปรุงความสามารถในการพกพาของแอปพลิเคชัน

การย้ายข้อมูลงานแบบดึงจะครอบคลุมในโมดูลการย้ายข้อมูล 18-19 ขณะที่โมดูล 7-9 จะเน้นที่การย้ายข้อมูลงานแบบพุช เราได้เพิ่มการใช้งานของ App Engine Task Queue แบบพุชลงในแอปตัวอย่าง Python 2 App Engine ที่มีอยู่ ซึ่งจะลงทะเบียนการเข้าชมหน้าเว็บใหม่และแสดงการเข้าชมล่าสุด เพื่อให้คุณย้ายข้อมูลจากงานแบบพุชของ App Engine Task Queue ได้ Codelab โมดูลที่ 7 เพิ่มงานแบบพุชเพื่อลบการเข้าชมที่เก่าที่สุด ซึ่งจะไม่แสดงอีกต่อไป ดังนั้นจึงไม่ควรใช้พื้นที่เก็บข้อมูลเพิ่มเติมใน Datastore Codelab โมดูลที่ 8 นี้ยังคงฟังก์ชันการทำงานเดิมไว้ แต่จะย้ายกลไกการจัดคิวพื้นฐานจากงานแบบพุชของคิวงานไปยัง Cloud Tasks รวมถึงทำซ้ำการย้ายข้อมูลโมดูลที่ 2 จาก App Engine NDB ไปยัง Cloud NDB สำหรับการเข้าถึง Datastore

บทแนะนำนี้มีขั้นตอนต่อไปนี้

  1. การตั้งค่า/การเตรียมการ
  2. อัปเดตการกำหนดค่า
  3. แก้ไขโค้ดแอปพลิเคชัน

3. การตั้งค่า/การเตรียมการ

ส่วนนี้จะอธิบายวิธี

  1. ตั้งค่าโปรเจ็กต์ Cloud
  2. รับแอปตัวอย่างพื้นฐาน
  3. (อีกครั้ง) นำไปใช้งานและตรวจสอบแอปพื้นฐาน
  4. เปิดใช้บริการ/API ใหม่ของ Google Cloud

ขั้นตอนเหล่านี้จะช่วยให้คุณเริ่มต้นด้วยโค้ดที่ใช้งานได้ และแอปตัวอย่างพร้อมสำหรับการย้ายข้อมูลไปยังบริการระบบคลาวด์

1. ตั้งค่าโปรเจ็กต์

หากทำ Codelab ของโมดูลที่ 7 เสร็จแล้ว ให้ใช้โปรเจ็กต์ (และโค้ด) เดียวกันนั้นซ้ำ หรือจะสร้างโปรเจ็กต์ใหม่หรือนำโปรเจ็กต์อื่นที่มีอยู่มาใช้ซ้ำก็ได้ ตรวจสอบว่าโปรเจ็กต์มีบัญชีสำหรับการเรียกเก็บเงินที่ใช้งานอยู่และแอป App Engine ที่เปิดใช้แล้ว ค้นหารหัสโปรเจ็กต์เนื่องจากคุณจะต้องใช้รหัสนี้ในระหว่าง Codelab นี้ โดยใช้รหัสเมื่อใดก็ตามที่พบตัวแปร PROJECT_ID

2. รับแอปตัวอย่างพื้นฐาน

ข้อกำหนดเบื้องต้นอย่างหนึ่งคือแอป App Engine ของโมดูลที่ 7 ที่ใช้งานได้ ให้ทำตาม Codelab ของโมดูลที่ 7 (แนะนำ) หรือคัดลอกแอปของโมดูลที่ 7 จากที่เก็บ ไม่ว่าคุณจะใช้โค้ดของคุณเองหรือโค้ดของเรา เราจะเริ่มต้นที่โค้ดของโมดูลที่ 7 ("START") Codelab นี้จะแนะนำขั้นตอนการย้ายข้อมูลให้คุณ โดยจะจบด้วยโค้ดที่คล้ายกับโค้ดในโฟลเดอร์ที่เก็บข้อมูลของโมดูลที่ 8 ("FINISH")

ไม่ว่าคุณจะใช้แอป Module 7 ใด โฟลเดอร์ควรมีลักษณะดังที่แสดงด้านล่างนี้ และอาจมีโฟลเดอร์ lib ด้วย

$ ls
README.md               appengine_config.py     requirements.txt
app.yaml                main.py                 templates

3. (อีกครั้ง) นำไปใช้งานและตรวจสอบแอปพื้นฐาน

ทำตามขั้นตอนต่อไปนี้เพื่อติดตั้งใช้งานแอปโมดูลที่ 7

  1. ลบโฟลเดอร์ lib หากมี แล้วเรียกใช้ pip install -t lib -r requirements.txt เพื่อสร้าง lib ใหม่ คุณอาจต้องใช้ pip2 แทนหากติดตั้งทั้ง Python 2 และ 3 ไว้ในคอมพิวเตอร์สำหรับการพัฒนาซอฟต์แวร์
  2. ตรวจสอบว่าคุณได้ติดตั้งและเริ่มต้นเครื่องมือบรรทัดคำสั่ง gcloud รวมถึงได้อ่านการใช้งานแล้ว
  3. (ไม่บังคับ) ตั้งค่าโปรเจ็กต์ Cloud ด้วย gcloud config set project PROJECT_ID หากไม่ต้องการป้อน PROJECT_ID กับคำสั่ง gcloud แต่ละคำสั่งที่คุณออก
  4. ทำให้แอปตัวอย่างใช้งานได้ด้วย gcloud app deploy
  5. ยืนยันว่าแอปทำงานได้ตามที่คาดไว้โดยไม่มีปัญหา หากคุณทำ Codelab โมดูลที่ 7 เสร็จแล้ว แอปจะแสดงผู้เข้าชมยอดนิยมพร้อมกับการเข้าชมล่าสุด (ดังภาพด้านล่าง) ที่ด้านล่างจะมีข้อบ่งชี้ของงานเก่ากว่าซึ่งจะถูกลบ

4aa8a2cb5f527079.png

4. เปิดใช้บริการ/API ใหม่ของ Google Cloud

แอปเวอร์ชันเก่าใช้บริการที่รวมไว้ของ App Engine ซึ่งไม่ต้องตั้งค่าเพิ่มเติม แต่บริการ Cloud แบบสแตนด์อโลนต้องตั้งค่า และแอปที่อัปเดตแล้วจะใช้ทั้ง Cloud Tasks และ Cloud Datastore (ผ่านไลบรารีของไคลเอ็นต์ Cloud NDB) ผลิตภัณฑ์ Cloud หลายรายการมีโควต้าระดับ"ใช้งานฟรีเสมอ" ซึ่งรวมถึง App Engine, Cloud Datastore และ Cloud Tasks ตราบใดที่คุณยังคงใช้บริการไม่เกินขีดจำกัดดังกล่าว คุณก็จะไม่เสียค่าใช้จ่ายในการทำบทแนะนำนี้ คุณเปิดใช้ Cloud API ได้จาก Cloud Console หรือจากบรรทัดคำสั่งก็ได้ ขึ้นอยู่กับความต้องการ

จาก Cloud Console

ไปที่หน้าคลังของ API Manager (สำหรับโปรเจ็กต์ที่ถูกต้อง) ใน Cloud Console แล้วค้นหา Cloud Datastore และ Cloud Tasks API โดยใช้แถบค้นหาที่อยู่ตรงกลางของหน้า

c7a740304e9d35b.png

คลิกปุ่มเปิดใช้สำหรับแต่ละ API แยกกัน ระบบอาจแจ้งให้คุณระบุข้อมูลการเรียกเก็บเงิน นี่คือตัวอย่างที่มีหน้าไลบรารี Cloud Pub/Sub API (อย่าเปิดใช้ Pub/Sub API สำหรับ Codelab นี้ ให้ใช้เฉพาะ Cloud Tasks และ Datastore)

1b6c0a2a73124f6b.jpeg

จากบรรทัดคำสั่ง

แม้ว่าการเปิดใช้ API จากคอนโซลจะให้ข้อมูลที่เป็นภาพ แต่บางคนก็อาจชอบใช้บรรทัดคำสั่งมากกว่า ออกคำสั่ง gcloud services enable cloudtasks.googleapis.com datastore.googleapis.com เพื่อเปิดใช้ทั้ง 2 API พร้อมกัน

$ gcloud services enable cloudtasks.googleapis.com datastore.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

ระบบอาจแจ้งให้คุณระบุข้อมูลสำหรับการเรียกเก็บเงิน หากต้องการเปิดใช้ Cloud API อื่นๆ และต้องการทราบ "URI" ของ API เหล่านั้น คุณจะดูได้ที่ด้านล่างของหน้าไลบรารีของแต่ละ API เช่น ดู pubsub.googleapis.com เป็น "ชื่อบริการ" ที่ด้านล่างของหน้า Pub/Sub ด้านบน

หลังจากทำตามขั้นตอนเสร็จแล้ว โปรเจ็กต์จะเข้าถึง API ได้ ตอนนี้ได้เวลาอัปเดตแอปเพื่อใช้ API เหล่านั้นแล้ว

4. อัปเดตการกำหนดค่า

การอัปเดตในการกำหนดค่าเป็นผลมาจากการเพิ่มการใช้ไลบรารีของไคลเอ็นต์ Cloud อย่างชัดเจน ไม่ว่าคุณจะใช้ไลบรารีใดก็ตาม คุณต้องทำการเปลี่ยนแปลงเดียวกันกับแอปที่ไม่ได้ใช้ไลบรารีไคลเอ็นต์ของ Cloud ใดๆ

requirements.txt

โมดูลที่ 8 จะเปลี่ยนการใช้ App Engine NDB และคิวงานจากโมดูลที่ 1 เป็น Cloud NDB และ Cloud Tasks ต่อท้ายทั้ง google-cloud-ndb และ google-cloud-tasks ไปยัง requirements.txt เพื่อเข้าร่วม flask จากโมดูลที่ 7

flask
google-cloud-ndb
google-cloud-tasks

requirements.txtไฟล์นี้ไม่มีหมายเลขเวอร์ชัน ซึ่งหมายความว่าระบบจะเลือกเวอร์ชันล่าสุด หากเกิดปัญหาความไม่เข้ากัน ให้ระบุหมายเลขเวอร์ชันเพื่อล็อกเวอร์ชันที่ใช้งานได้สำหรับแอป

app.yaml

เมื่อใช้ไลบรารีของไคลเอ็นต์ Cloud รันไทม์ของ App Engine สำหรับ Python 2 จะต้องใช้แพ็กเกจของบุคคลที่สามที่เฉพาะเจาะจง ได้แก่ grpcio และ setuptools ผู้ใช้ Python 2 ต้องแสดงรายการไลบรารีในตัว เช่น ไลบรารีเหล่านี้ พร้อมกับเวอร์ชันที่ใช้ได้หรือ "ล่าสุด" ใน app.yaml หากยังไม่มีส่วน libraries ให้สร้างส่วนและเพิ่มทั้ง 2 ไลบรารีดังนี้

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest

เมื่อย้ายข้อมูลแอปของคุณ แอปอาจมีส่วน libraries อยู่แล้ว หากมี และไม่มีทั้ง grpcio และ setuptools ให้เพิ่มลงในส่วน libraries ที่มีอยู่ ตอนนี้ app.yaml ที่อัปเดตแล้วควรมีลักษณะดังนี้

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest

appengine_config.py

การเรียก google.appengine.ext.vendor.add() ใน appengine_config.py จะเชื่อมต่อไลบรารีของบุคคลที่สามที่คัดลอกมา (บางครั้งเรียกว่า "การจัดจำหน่าย" หรือ "การรวมแพ็กเกจด้วยตนเอง") ใน lib กับแอปของคุณ ใน app.yaml ด้านบน เราได้เพิ่มไลบรารีของบุคคลที่สามในตัว และไลบรารีเหล่านั้นต้องใช้ setuptools.pkg_resources.working_set.add_entry() เพื่อเชื่อมต่อแอปของคุณกับแพ็กเกจในตัวเหล่านั้นใน lib ด้านล่างนี้คือโมดูลที่ 1 ฉบับเดิม appengine_config.py และหลังจากที่คุณได้อัปเดตโมดูลที่ 8 แล้ว

ก่อน:

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

หลังจากนั้น

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)

คุณยังดูคำอธิบายที่คล้ายกันได้ในเอกสารประกอบการย้ายข้อมูล App Engine

5. แก้ไขโค้ดแอปพลิเคชัน

ส่วนนี้มีการอัปเดตไฟล์แอปพลิเคชันหลัก main.py โดยแทนที่การใช้คิวแบบพุชของคิวงาน App Engine ด้วย Cloud Tasks ไม่มีการเปลี่ยนแปลงเทมเพลตเว็บ templates/index.htmlแอปทั้ง 2 ควรทำงานเหมือนกันและแสดงข้อมูลเดียวกัน การแก้ไขแอปพลิเคชันหลักจะแบ่งออกเป็น "สิ่งที่ต้องทำ" 4 อย่างต่อไปนี้

  1. อัปเดตการนำเข้าและการเริ่มต้น
  2. อัปเดตฟังก์ชันการทำงานของโมเดลข้อมูล (Cloud NDB)
  3. ย้ายข้อมูลไปยัง Cloud Tasks (และ Cloud NDB)
  4. ตัวแฮนเดิลงานอัปเดต (พุช)

1. อัปเดตการนำเข้าและการเริ่มต้น

  1. แทนที่ App Engine NDB (google.appengine.ext.ndb) และคิวงาน (google.appengine.api.taskqueue) ด้วย Cloud NDB (google.cloud.ndb) และ Cloud Tasks (google.cloud.tasks) ตามลำดับ
  2. ไลบรารีของไคลเอ็นต์ระบบคลาวด์ต้องมีการเริ่มต้นและการสร้าง "ไคลเอ็นต์ API" จากนั้นกำหนดให้กับ ds_client และ ts_client ตามลำดับ
  3. เอกสารประกอบของคิวของงานระบุว่า "App Engine มีคิวแบบพุชเริ่มต้นชื่อ default ซึ่งได้รับการกำหนดค่าและพร้อมใช้งานกับการตั้งค่าเริ่มต้น" Cloud Tasks ไม่มีคิว default (เนื่องจากเป็นผลิตภัณฑ์ Cloud แบบสแตนด์อโลนที่ไม่ขึ้นอยู่กับ App Engine) จึงต้องใช้โค้ดใหม่เพื่อสร้างคิว Cloud Tasks ที่ชื่อ default
  4. คิวของ App Engine ไม่กำหนดให้คุณต้องระบุภูมิภาคเนื่องจากใช้ภูมิภาคที่แอปของคุณทำงานอยู่ อย่างไรก็ตาม เนื่องจากตอนนี้ Cloud Tasks เป็นผลิตภัณฑ์อิสระ จึงต้องใช้ภูมิภาค และภูมิภาคนั้นต้องตรงกับภูมิภาคที่แอปของคุณทำงานอยู่ ต้องระบุชื่อภูมิภาคและรหัสโปรเจ็กต์ Cloud เพื่อสร้าง "เส้นทางแบบเต็ม" เป็นตัวระบุที่ไม่ซ้ำกันของคิว

การอัปเดตที่อธิบายไว้ในหัวข้อย่อยที่ 3 และ 4 ด้านบนเป็นส่วนใหญ่ของค่าคงที่และการเริ่มต้นเพิ่มเติมที่จำเป็น ดูในส่วน "ก่อน" และ "หลัง" ด้านล่าง แล้วทำการเปลี่ยนแปลงเหล่านี้ที่ด้านบนของ main.py

ก่อน:

from datetime import datetime
import logging
import time
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb

app = Flask(__name__)

หลังจากนั้น

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

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

_, 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)

2. อัปเดตฟังก์ชันการทำงานของโมเดลข้อมูล (Cloud NDB)

App Engine NDB และ Cloud NDB ทำงานเกือบจะเหมือนกัน ไม่มีการเปลี่ยนแปลงที่สำคัญทั้งในโมเดลข้อมูลและstore_visit()ฟังก์ชัน ความแตกต่างที่เห็นได้ชัดเพียงอย่างเดียวคือตอนนี้การสร้างเอนทิตี Visit ใน store_visit() จะอยู่ในบล็อก with ของ Python Cloud NDB กำหนดให้ควบคุมการเข้าถึง Datastore ทั้งหมดภายในเครื่องมือจัดการบริบท จึงต้องมีคำสั่ง with ข้อมูลโค้ดด้านล่างแสดงความแตกต่างเล็กน้อยนี้เมื่อย้ายข้อมูลไปยัง Cloud NDB ทำการเปลี่ยนแปลงนี้

ก่อน:

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()

หลังจากนั้น

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()

3. ย้ายข้อมูลไปยัง Cloud Tasks (และ Cloud NDB)

การเปลี่ยนแปลงที่สำคัญที่สุดในการย้ายข้อมูลนี้คือการเปลี่ยนโครงสร้างพื้นฐานการจัดคิวที่อยู่เบื้องหลัง ซึ่งเกิดขึ้นในฟังก์ชัน fetch_visits() โดยจะมีการสร้างและจัดคิวงาน (พุช) เพื่อลบการเข้าชมเก่าสำหรับการดำเนินการ อย่างไรก็ตาม ฟังก์ชันเดิมจากโมดูลที่ 7 จะยังคงอยู่

  1. ค้นหาการเข้าชมล่าสุด
  2. แทนที่จะแสดงการเข้าชมเหล่านั้นทันที ให้บันทึกการประทับเวลาของ Visit รายการล่าสุด ซึ่งเป็นรายการที่เก่าที่สุดที่แสดง คุณสามารถลบการเข้าชมทั้งหมดที่เก่ากว่านี้ได้
  3. แยกการประทับเวลาเป็น Float และสตริงโดยใช้ยูทิลิตี Python มาตรฐาน แล้วใช้ทั้ง 2 อย่างในความสามารถต่างๆ เช่น แสดงต่อผู้ใช้ เพิ่มลงในบันทึก ส่งไปยังแฮนเดิล เป็นต้น
  4. สร้างงานแบบพุชโดยใช้การประทับเวลานี้เป็นเพย์โหลดพร้อมกับ /trim เป็น URL
  5. ในที่สุดระบบจะเรียกใช้ตัวแฮนเดิลงานผ่าน HTTP POST ไปยัง URL นั้น

เวิร์กโฟลว์นี้แสดงด้วยข้อมูลโค้ด "ก่อน" ดังนี้

ก่อน:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    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)
    taskqueue.add(url='/trim', params={'oldest': oldest})
    return data, oldest_str

แม้ว่าฟังก์ชันการทำงานจะยังคงเหมือนเดิม แต่ Cloud Tasks จะกลายเป็นแพลตฟอร์มการดำเนินการ การอัปเดตเพื่อให้การเปลี่ยนแปลงนี้มีผลรวมถึงสิ่งต่อไปนี้

  1. ห่อหุ้มVisitการค้นหาภายในบล็อก with Python (ทำซ้ำการย้ายข้อมูลโมดูล 2 ไปยัง Cloud NDB)
  2. สร้างข้อมูลเมตาของ Cloud Tasks รวมถึงแอตทริบิวต์ที่คาดไว้ เช่น เพย์โหลดการประทับเวลาและ URL แต่ยังเพิ่มประเภท MIME และเข้ารหัสเพย์โหลดเป็น JSON ด้วย
  3. ใช้ไคลเอ็นต์ Cloud Tasks API เพื่อสร้างงานที่มีข้อมูลเมตาและเส้นทางแบบเต็มของคิว

การเปลี่ยนแปลงเหล่านี้ใน fetch_visits() แสดงไว้ด้านล่าง

หลังจากนั้น

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 data, oldest_str

4. ตัวแฮนเดิลงานอัปเดต (พุช)

ฟังก์ชันตัวแฮนเดิลงาน (พุช) ไม่จำเป็นต้องมีการอัปเดตครั้งใหญ่ เพียงแค่ต้องมีการดำเนินการเท่านั้น ซึ่งใช้ได้กับคิวงานหรือ Cloud Tasks "รหัสก็คือรหัส" พวกเขาว่าอย่างนั้น แต่มีการเปลี่ยนแปลงเล็กน้อยดังนี้

  1. ระบบจะส่งเพย์โหลดการประทับเวลาไปยังคิวงานตามตัวอักษร แต่จะเข้ารหัส JSON สำหรับ Cloud Tasks ดังนั้นจึงต้องแยกวิเคราะห์ JSON เมื่อมาถึง
  2. การเรียกใช้ HTTP POST ไปยัง /trim ที่มี Task Queue มี MIMEtype โดยนัยเป็น application/x-www-form-urlencoded แต่ใน Cloud Tasks จะมีการกำหนดเป็น application/json อย่างชัดเจน ดังนั้นจึงมีวิธีแยกเพย์โหลดที่แตกต่างกันเล็กน้อย
  3. ใช้เครื่องมือจัดการบริบทไคลเอ็นต์ Cloud NDB API (การย้ายข้อมูลโมดูล 2 ไปยัง Cloud NDB)

ด้านล่างนี้คือข้อมูลโค้ดก่อนและหลังทำการเปลี่ยนแปลงเหล่านี้กับตัวแฮนเดิลงาน trim()

ก่อน:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = request.form.get('oldest', type=float)
    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

หลังจากนั้น

@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

ไม่มีการอัปเดตตัวแฮนเดิลแอปพลิเคชันหลัก root() หรือเทมเพลตเว็บ templates/index.html

6. สรุป/ล้างข้อมูล

ส่วนนี้จะสรุป Codelab นี้ด้วยการติดตั้งใช้งานแอป ยืนยันว่าแอปทำงานได้ตามที่ต้องการและในเอาต์พุตที่แสดง หลังจากตรวจสอบแอปแล้ว ให้ล้างข้อมูลและพิจารณาขั้นตอนถัดไป

ทำให้แอปพลิเคชันใช้งานได้และยืนยัน

ทําให้แอปใช้งานได้ด้วย gcloud app deploy เอาต์พุตควรเหมือนกับแอปในโมดูลที่ 7 แต่คุณจะเห็นว่าคุณได้เปลี่ยนไปใช้ผลิตภัณฑ์คิวการพุชที่แตกต่างกันโดยสิ้นเชิง ซึ่งทำให้แอปของคุณพกพาได้มากกว่าเดิม

4aa8a2cb5f527079.png

ล้างข้อมูล

ทั่วไป

หากคุณดำเนินการเสร็จแล้วในตอนนี้ เราขอแนะนำให้ปิดใช้แอป App Engine เพื่อไม่ให้มีการเรียกเก็บเงิน อย่างไรก็ตาม หากต้องการทดสอบหรือทดลองเพิ่มเติม แพลตฟอร์ม App Engine มีโควต้าฟรี ดังนั้นตราบใดที่คุณไม่เกินระดับการใช้งานดังกล่าว คุณก็จะไม่ถูกเรียกเก็บเงิน ซึ่งเป็นค่าบริการสำหรับการประมวลผล แต่อาจมีค่าบริการสำหรับบริการ App Engine ที่เกี่ยวข้องด้วย ดังนั้นโปรดดูข้อมูลเพิ่มเติมในหน้าการกำหนดราคา หากการย้ายข้อมูลนี้เกี่ยวข้องกับบริการอื่นๆ ของระบบคลาวด์ ระบบจะเรียกเก็บเงินสำหรับบริการเหล่านั้นแยกต่างหาก ไม่ว่าจะในกรณีใดก็ตาม หากมี ให้ดูส่วน "เฉพาะสำหรับ Codelab นี้" ด้านล่าง

เพื่อความโปร่งใสอย่างเต็มที่ การติดตั้งใช้งานแพลตฟอร์มการประมวลผลแบบ Serverless ของ Google Cloud เช่น App Engine จะทำให้เกิดค่าใช้จ่ายในการสร้างและพื้นที่เก็บข้อมูลเล็กน้อย Cloud Build มีโควต้าฟรีของตัวเอง เช่นเดียวกับ Cloud Storage การจัดเก็บรูปภาพนั้นจะใช้โควต้าบางส่วน อย่างไรก็ตาม คุณอาจอาศัยอยู่ในภูมิภาคที่ไม่มีระดับการใช้งานฟรีดังกล่าว ดังนั้นโปรดทราบการใช้พื้นที่เก็บข้อมูลเพื่อลดค่าใช้จ่ายที่อาจเกิดขึ้น "โฟลเดอร์" ของ Cloud Storage ที่คุณควรตรวจสอบ ได้แก่

  • 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
  • ลิงก์พื้นที่เก็บข้อมูลด้านบนจะขึ้นอยู่กับPROJECT_IDและ *LOC*ation ของคุณ เช่น "us" หากแอปโฮสต์อยู่ในสหรัฐอเมริกา

ในทางกลับกัน หากคุณจะไม่ดำเนินการต่อกับแอปพลิเคชันนี้หรือ Codelab การย้ายข้อมูลอื่นๆ ที่เกี่ยวข้อง และต้องการลบทุกอย่างออกทั้งหมด ให้ปิดโปรเจ็กต์

เฉพาะสำหรับ Codelab นี้

บริการที่ระบุไว้ด้านล่างเป็นบริการเฉพาะสำหรับโค้ดแล็บนี้ ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบของแต่ละผลิตภัณฑ์

ขั้นตอนถัดไป

การย้ายข้อมูลจากงานพุชคิวงานของ App Engine ไปยัง Cloud Tasks ก็มีเพียงเท่านี้ หากคุณสนใจที่จะพอร์ตแอปนี้ไปยัง Python 3 ต่อไปและย้ายข้อมูลไปยัง Cloud Datastore จาก Cloud NDB ให้พิจารณาโมดูลที่ 9

Cloud NDB มีไว้สำหรับนักพัฒนาแอป App Engine ที่ใช้ Python 2 โดยเฉพาะ ซึ่งมอบประสบการณ์การใช้งานที่แทบจะเหมือนกัน แต่ Cloud Datastore มีไลบรารีของไคลเอ็นต์ดั้งเดิมของตัวเองที่สร้างขึ้นสำหรับผู้ใช้ที่ไม่ใช่ App Engine หรือผู้ใช้ App Engine รายใหม่ (Python 3) อย่างไรก็ตาม เนื่องจาก Cloud NDB พร้อมใช้งานสำหรับ Python 2 และ 3 จึงไม่จำเป็นต้องย้ายข้อมูลไปยัง Cloud Datastore

ทั้ง Cloud NDB และ Cloud Datastore ต่างก็เข้าถึง Datastore (แม้จะเข้าถึงด้วยวิธีที่แตกต่างกัน) ดังนั้นเหตุผลเดียวที่ควรพิจารณาเปลี่ยนไปใช้ Cloud Datastore คือหากคุณมีแอปอื่นๆ อยู่แล้ว โดยเฉพาะแอปที่ไม่ใช่ App Engine ที่ใช้ Cloud Datastore และต้องการใช้ไลบรารีของไคลเอ็นต์ Datastore เดียวกัน การย้ายข้อมูลจาก Cloud NDB ไปยัง Cloud Datastore ซึ่งเป็นขั้นตอนที่ไม่บังคับนี้จะกล่าวถึงแยกกัน (โดยไม่มี Task Queue หรือ Cloud Tasks) ในโมดูลที่ 3

นอกเหนือจากโมดูลที่ 3, 8 และ 9 แล้ว โมดูลการย้ายข้อมูลอื่นๆ ที่มุ่งเน้นการย้ายออกจากบริการแบบกลุ่มเดิมของ App Engine ที่ควรพิจารณา ได้แก่

  • โมดูลที่ 2: ย้ายข้อมูลจาก App Engine NDB ไปยัง Cloud NDB
  • โมดูล 12-13: ย้ายข้อมูลจาก Memcache ของ App Engine ไปยัง Cloud Memorystore
  • โมดูล 15-16: ย้ายข้อมูลจาก App Engine Blobstore ไปยัง Cloud Storage
  • โมดูล 18-19: คิวงานของ App Engine (งานแบบดึง) ไปยัง Cloud Pub/Sub

App Engine ไม่ใช่แพลตฟอร์มแบบไร้เซิร์ฟเวอร์เพียงอย่างเดียวใน Google Cloud อีกต่อไป หากคุณมีแอป App Engine ขนาดเล็กหรือแอปที่มีฟังก์ชันการทำงานจำกัด และต้องการเปลี่ยนให้เป็นไมโครเซอร์วิสแบบสแตนด์อโลน หรือต้องการแยกแอปแบบ Monolithic ออกเป็นคอมโพเนนต์ที่นำกลับมาใช้ใหม่ได้หลายรายการ นี่เป็นเหตุผลที่ดีที่ควรพิจารณาเปลี่ยนไปใช้ Cloud Functions หากการใช้คอนเทนเนอร์กลายเป็นส่วนหนึ่งของเวิร์กโฟลว์การพัฒนาแอปพลิเคชัน โดยเฉพาะอย่างยิ่งหากประกอบด้วยไปป์ไลน์ CI/CD (การผสานรวมอย่างต่อเนื่อง/การนำส่งหรือการติดตั้งใช้งานอย่างต่อเนื่อง) ให้พิจารณาการย้ายข้อมูลไปยัง Cloud Run สถานการณ์เหล่านี้จะครอบคลุมในโมดูลต่อไปนี้

  • ย้ายข้อมูลจาก App Engine ไปยัง Cloud Functions: ดูโมดูลที่ 11
  • ย้ายข้อมูลจาก App Engine ไปยัง Cloud Run: ดูโมดูลที่ 4 เพื่อจัดคอนเทนเนอร์แอปด้วย Docker หรือโมดูลที่ 5 เพื่อดำเนินการโดยไม่ต้องใช้คอนเทนเนอร์ ความรู้เกี่ยวกับ Docker หรือ Dockerfile

การเปลี่ยนไปใช้แพลตฟอร์มแบบไม่ใช้เซิร์ฟเวอร์อื่นเป็นทางเลือก และเราขอแนะนำให้พิจารณาตัวเลือกที่ดีที่สุดสำหรับแอปและ Use Case ของคุณก่อนทำการเปลี่ยนแปลงใดๆ

ไม่ว่าคุณจะพิจารณาโมดูลการย้ายข้อมูลใดเป็นโมดูลถัดไป คุณจะเข้าถึงเนื้อหาของ Serverless Migration Station ทั้งหมด (Codelab, วิดีโอ, ซอร์สโค้ด [หากมี]) ได้ที่ที่เก็บแบบโอเพนซอร์ส README ของที่เก็บยังให้คำแนะนำเกี่ยวกับการย้ายข้อมูลที่ควรพิจารณาและ "ลำดับ" ที่เกี่ยวข้องของโมดูลการย้ายข้อมูลด้วย

7. แหล่งข้อมูลเพิ่มเติม

ด้านล่างนี้คือแหล่งข้อมูลเพิ่มเติมสำหรับนักพัฒนาแอปที่ต้องการสำรวจโมดูลการย้ายข้อมูลนี้หรือโมดูลที่เกี่ยวข้อง รวมถึงผลิตภัณฑ์ที่เกี่ยวข้องเพิ่มเติม ซึ่งรวมถึงส่วนที่ให้ความคิดเห็นเกี่ยวกับเนื้อหานี้ ลิงก์ไปยังโค้ด และเอกสารต่างๆ ที่คุณอาจเห็นว่ามีประโยชน์

ปัญหา/ความคิดเห็นเกี่ยวกับ Codelabs

หากพบปัญหาเกี่ยวกับ Codelab นี้ โปรดค้นหาปัญหาของคุณก่อนที่จะยื่นเรื่อง ลิงก์สำหรับค้นหาและสร้างปัญหาใหม่

แหล่งข้อมูลเกี่ยวกับการย้ายข้อมูล

คุณจะพบลิงก์ไปยังโฟลเดอร์ที่เก็บสำหรับโมดูลที่ 7 (START) และโมดูลที่ 8 (FINISH) ได้ในตารางด้านล่าง

Codelab

Python 2

Python 3

โมดูล 7

รหัส

โค้ด (ไม่ได้กล่าวถึงในบทแนะนำนี้)

โมดูล 8 (Codelab นี้)

รหัส

(ไม่มี)

แหล่งข้อมูลออนไลน์

ด้านล่างนี้คือแหล่งข้อมูลออนไลน์ที่อาจเกี่ยวข้องกับบทแนะนำนี้

คิวงาน App Engine และ Cloud Tasks

App Engine NDB และ Cloud NDB (Datastore)

แพลตฟอร์ม App Engine

ข้อมูลอื่นๆ เกี่ยวกับระบบคลาวด์

วิดีโอ

ใบอนุญาต

ผลงานนี้ได้รับอนุญาตภายใต้สัญญาอนุญาตครีเอทีฟคอมมอนส์สำหรับยอมรับสิทธิของผู้สร้าง (Creative Commons Attribution License) 2.0 แบบทั่วไป