Migracja z kolejki zadań App Engine do Cloud Pub/Sub (moduł 19)

1. Omówienie

Seria ćwiczeń z programowania dla bezserwerowych stacji migracji (samouczek, samouczków) i podobnych filmów ma pomóc deweloperom bezserwerowych Google Cloud w modernizacji aplikacji przez przeprowadzenie co najmniej 1 migracji, w wyniku rezygnacji ze starszych usług. W ten sposób Twoje aplikacje stają się bardziej przenośne, mają więcej opcji i elastyczność, co pozwala na integrację z szerszą gamą usług Cloud i uzyskiwanie do nich dostępu, a także łatwiejsze przejście na nowsze wersje językowe. Choć początkowo koncentrowaliśmy się na pierwszych użytkownikach Cloud, głównie deweloperów korzystających ze środowiska App Engine (środowisko standardowe), ta seria jest na tyle szeroka, aby uwzględnić inne platformy bezserwerowe, takie jak Cloud Functions i Cloud Run, oraz inne, w stosownych przypadkach.

Celem tego ćwiczenia w Codelabs jest pokazanie programistom App Engine w języku Python 2, jak przejść z zadań pull kolejki zadań App Engine do Cloud Pub/Sub. Dostępna jest też migracja z App Engine NDB do Cloud NDB na potrzeby dostępu do Datastore (omówiona głównie w module 2), a także przejście na Pythona 3.

W module 18 dowiesz się, jak dodać do aplikacji zadania pull. W tym module ukończysz aplikację z modułu 18, a następnie przeprowadzisz migrację do Cloud Pub/Sub. Użytkownicy korzystający z kolejek zadań do wykonywania zadań push zamiast tego zostaną przeniesieni do Cloud Tasks i powinni zapoznać się z modułami 7–9.

Dowiesz się, jak:

Czego potrzebujesz

Ankieta

Jak wykorzystasz ten samouczek?

tylko do przeczytania. Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z językiem Python?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz korzystanie z usług Google Cloud?

Początkujący Poziom średnio zaawansowany Biegły
.

2. Tło

Kolejka zadań App Engine obsługuje zarówno zadania push, jak i pobieranie. Aby zwiększyć przenośność aplikacji, Google Cloud zaleca migrację ze starszych pakietów usług, takich jak kolejka zadań, do innych samodzielnych usług Cloud lub ich odpowiedników innych firm.

Moduły 7–9 migracji obejmują migrację zadań push, a moduły 18–19 koncentrują się na migracji zadań pull. O ile Cloud Tasks odpowiada bliżej zadań push kolejki zadań, Pub/Sub nie jest aż tak zbliżony do zadań pull kolejki zadań.

Pub/Sub ma więcej funkcji niż funkcja pull dostępna w kolejce zadań. Na przykład Pub/Sub ma również funkcję push, jednak Cloud Tasks przypomina zadania push kolejki zadań, więc push Pub/Sub nie jest objęta żadnym modułem migracji. W tym ćwiczeniu z programowania w module 19 pokazujemy, jak przełączyć mechanizm kolejkowania z kolejek zadań do Pub/Sub oraz przejść z App Engine NDB do Cloud NDB w celu uzyskania dostępu do Datastore, powtarzając migrację modułu 2.

Chociaż kod modułu 18 jest „reklamowany” jako przykładowa aplikacja w języku Python 2, samo źródło jest zgodne z językiem Python 2 i 3 i pozostaje tak nawet po migracji do Cloud Pub/Sub (i Cloud NDB) w module 19.

W tym samouczku omawiamy następujące kroki:

  1. Konfiguracja/praca
  2. Aktualizacja konfiguracji
  3. Modyfikowanie kodu aplikacji

3. Konfiguracja/praca

W tej sekcji dowiesz się, jak:

  1. Konfigurowanie projektu Cloud
  2. Pobierz przykładową aplikację bazową
  3. (Ponowne) wdrażanie i weryfikowanie aplikacji bazowej
  4. Włącz nowe usługi i interfejsy API Google Cloud

Dzięki tym krokom masz pewność, że zaczynasz od działającego kodu i czy jest on gotowy do migracji do usług Cloud.

1. Konfigurowanie projektu

Jeśli masz już za sobą moduł 18 z programowania, wykorzystaj ponownie ten sam projekt (i kod). Możesz też utworzyć nowy projekt lub wykorzystać inny istniejący projekt. Sprawdź, czy projekt ma aktywne konto rozliczeniowe i włączoną aplikację App Engine. Znajdź identyfikator projektu, który będzie Ci potrzebny podczas tego ćwiczenia z programowania. Użyj go, gdy natrafisz na zmienną PROJECT_ID.

2. Pobierz przykładową aplikację bazową

Jednym z warunków wstępnych jest działająca aplikacja z modułu 18 App Engine, więc wykonaj ćwiczenia z programowania (zalecane; link powyżej) lub skopiuj kod modułu 18 z repozytorium. Bez względu na to, czy używasz swoich czy naszych danych, od tego zaczniemy („START”). To ćwiczenie w Codelabs przeprowadzi Cię przez proces migracji, zakończy się kodem podobnym do tego, który znajduje się w folderze repozytorium modułu 19 („FINISH”).

Niezależnie od tego, której aplikacji w module 18 używasz, folder powinien wyglądać tak jak poniżej (może być też zawierający folder lib):

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

3. (Ponowne) wdrażanie i weryfikowanie aplikacji bazowej

Aby wdrożyć aplikację w module 18, wykonaj te czynności:

  1. Usuń folder lib (jeśli istnieje), a następnie uruchom polecenie pip install -t lib -r requirements.txt, aby ponownie uzupełnić dane lib. Jeśli na komputerze, na którym tworzysz aplikacje, masz zainstalowany język Python 2 i 3, może być konieczne użycie interfejsu pip2.
  2. Upewnij się, że masz zainstalowane i zainicjowane narzędzie wiersza poleceń gcloud, a także sprawdź, jak używasz tego narzędzia.
  3. (Opcjonalnie) Jeśli nie chcesz wpisywać PROJECT_ID przy każdym uruchamianym poleceniu gcloud, ustaw w swoim projekcie Cloud wartość gcloud config set project PROJECT_ID.
  4. Wdróż przykładową aplikację za pomocą: gcloud app deploy
  5. Sprawdź, czy aplikacja działa prawidłowo, bez problemów. Jeśli udało Ci się ukończyć Moduł 18, aplikacja wyświetli najczęstszych użytkowników wraz z najnowszymi wizytami (poniżej). Jeśli nie, może nie być żadnej liczby użytkowników do wyświetlenia.

b667551dcbab1a09.png

Przed migracją przykładowej aplikacji modułu 18 musisz najpierw włączyć usługi Cloud, których będzie używać zmodyfikowana aplikacja.

4. Włącz nowe usługi i interfejsy API Google Cloud

Stara aplikacja korzystała z pakietów App Engine, które nie wymagają dodatkowej konfiguracji, w przeciwieństwie do samodzielnych usług Cloud, które wymagają aktualizacji. Zaktualizowana aplikacja będzie wykorzystywać zarówno Cloud Pub/Sub, jak i Cloud Datastore (za pomocą biblioteki klienta Cloud NDB). Interfejsy App Engine i oba interfejsy API Cloud mają „Zawsze bezpłatne” poziomu. Jeśli będziesz go przekraczać, nie będziemy naliczać opłat za wykonanie tego samouczka. Interfejsy Cloud APIs można włączyć w konsoli Cloud lub z poziomu wiersza poleceń – w zależności od potrzeb.

W konsoli Google Cloud

Otwórz stronę biblioteki menedżera interfejsów API (odpowiedni projekt) w konsoli Cloud i za pomocą paska wyszukiwania na środku strony wyszukaj interfejsy Cloud Datastore i Cloud Pub/Sub API:

c7a740304e9d35b.png

Kliknij przycisk Włącz oddzielnie dla każdego interfejsu API – może pojawić się prośba o podanie informacji rozliczeniowych. Oto przykładowa strona biblioteki Cloud Pub/Sub API:

1b6c0a2a73124f6b.jpeg

Wiersz poleceń

Chociaż dobrze jest korzystać z interfejsu API w konsoli, niektórzy wolą używać wiersza poleceń. Uruchom polecenie gcloud services enable pubsub.googleapis.com datastore.googleapis.com, aby włączyć oba interfejsy API jednocześnie:

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

Może pojawić się prośba o podanie informacji rozliczeniowych. Jeśli chcesz włączyć inne interfejsy Cloud API i chcesz poznać ich identyfikatory URI, znajdziesz je u dołu strony z biblioteką każdego z interfejsów API. Na przykład obserwuj pubsub.googleapis.com jako „Nazwę usługi” na dole strony Pub/Sub tuż powyżej.

Po wykonaniu tych czynności Twój projekt będzie miał dostęp do interfejsów API. Teraz czas zaktualizować aplikację, aby używała tych interfejsów API.

4. Tworzenie zasobów Pub/Sub

Podsumowanie procesu tworzenia kolejki zadań z modułu 18.

  1. Moduł 18 użył pliku queue.yaml do utworzenia kolejki pull o nazwie pullq.
  2. Aplikacja dodaje do kolejki pull zadania, które śledzą użytkowników.
  3. Zadania są ostatecznie przetwarzane przez pracownika i wynajmowane na określony czas (na godzinę).
  4. Wykonywane są zadania polegające na zliczaniu ostatnich użytkowników.
  5. Po zakończeniu zadania są usuwane z kolejki.

Zamierzasz powielić podobny przepływ pracy w Pub/Sub. W następnej sekcji przedstawimy podstawową terminologię Pub/Sub oraz 3 różne sposoby tworzenia niezbędnych zasobów Pub/Sub.

Terminologia Cloud Pub/Sub z kolejki zadań App Engine (pobieranie)

Przejście na Pub/Sub wymaga niewielkiego dostosowania słownika. Poniżej znajdziesz listę głównych kategorii wraz z odpowiednimi hasłami dotyczącymi obu usług. Zapoznaj się też z przewodnikiem po migracji, który zawiera podobne porównania.

  • Tworzenie struktury danych w kolejce: w ramach kolejki zadań dane trafiają do kolejek pobierania. dzięki Pub/Sub dane trafiają do tematów.
  • Jednostki danych w kolejce: zadania pobierania z kolejki zadań są nazywane wiadomościami w Pub/Sub.
  • Podmioty przetwarzające dane: dzięki kolejki zadań pracownicy mają dostęp do zadań pull; używając Pub/Sub, do odbierania wiadomości potrzebujesz subskrybentów.
  • Wyodrębnianie danych: dzierżawienie zadania pull jest jednoznaczne z pobieraniem wiadomości z tematu (za pomocą subskrypcji).
  • Czyszczenie/ukończenie: usunięcie zadania z kolejki zadań z kolejki pull po zakończeniu jest analogiczne do potwierdzenia wiadomości Pub/Sub.

Chociaż usługa kolejkowania się zmienia, przepływ pracy pozostaje względnie podobny:

  1. Zamiast kolejki pull aplikacja używa tematu o nazwie pullq.
  2. Zamiast dodawać zadania do kolejki pull, aplikacja wysyła wiadomości do tematu (pullq).
  3. Zamiast instancji roboczej leasingu zadań z kolejki pull, subskrybent o nazwie worker pobiera wiadomości z tematu pullq.
  4. Aplikacja przetwarza ładunki wiadomości, zwiększając liczbę użytkowników w Datastore.
  5. Zamiast usuwać zadania z kolejki pull, aplikacja potwierdza przetworzone wiadomości.

W przypadku kolejki zadań konfiguracja obejmuje utworzenie kolejki pull. Konfiguracja Pub/Sub wymaga utworzenia zarówno tematu, jak i subskrypcji. W module 18 przetworzyliśmy queue.yaml poza wykonaniem aplikacji. to samo trzeba zrobić w przypadku Pub/Sub.

Dostępne są 3 opcje tworzenia tematów i subskrypcji:

  1. W konsoli Google Cloud
  2. z poziomu wiersza poleceń,
  3. Z kodu (krótki skrypt Pythona)

Wybierz jedną z poniższych opcji i postępuj zgodnie z odpowiednimi instrukcjami, aby utworzyć zasoby Pub/Sub.

W konsoli Google Cloud

Aby utworzyć temat w konsoli Cloud, wykonaj te czynności:

  1. Otwórz stronę tematów Pub/Sub w konsoli Cloud.
  2. Kliknij Utwórz temat u góry. otworzy się nowe okno (patrz obraz poniżej)
  3. W polu Identyfikator tematu wpisz pullq.
  4. Odznacz wszystkie zaznaczone opcje i wybierz Klucz szyfrowania zarządzany przez Google.
  5. Kliknij przycisk Utwórz temat.

Okno tworzenia tematu wygląda tak:

a05cfdbf64571ceb.png

Po utworzeniu tematu musisz utworzyć dla niego subskrypcję:

  1. Otwórz stronę subskrypcji Pub/Sub w konsoli Cloud.
  2. Kliknij Utwórz subskrypcję na górze (patrz ilustracja poniżej).
  3. W polu Identyfikator subskrypcji wpisz worker.
  4. Wybierz pullq z menu Select a Cloud Pub/Sub topic (Wybierz temat Cloud Pub/Sub) z zachowaniem pełnej i odpowiedniej nazwy ścieżki. na przykład projects/PROJECT_ID/topics/pullq
  5. W polu Typ dostawy wybierz Pociągnij.
  6. Pozostaw wszystkie inne opcje bez zmian i kliknij przycisk Utwórz.

Tak wygląda ekran tworzenia subskrypcji:

c5444375c20b0618.jpeg

Subskrypcję możesz również utworzyć na stronie Tematy – ten „skrót” mogą być przydatne w powiązaniu tematów z subskrypcjami. Więcej informacji o tworzeniu subskrypcji znajdziesz w dokumentacji.

Wiersz poleceń

Użytkownicy Pub/Sub mogą tworzyć tematy i subskrypcje za pomocą poleceń gcloud pubsub topics create TOPIC_ID i gcloud pubsub subscriptions create SUBSCRIPTION_ID --topic=TOPIC_ID. Wykonanie tych poleceń z parametrem TOPIC_ID o wartości pullq i SUBSCRIPTION_ID o wartości worker daje w projekcie PROJECT_ID takie dane wyjściowe:

$ 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].

Zapoznaj się też z tą stroną w krótkiej dokumentacji. Wiersz poleceń może uprościć przepływy pracy, w których tematy i subskrypcje są regularnie tworzone. W tym celu można stosować takie polecenia w skryptach powłoki.

Z kodu (krótki skrypt Pythona)

Innym sposobem automatyzacji tworzenia tematów i subskrypcji jest użycie interfejsu Pub/Sub API w kodzie źródłowym. Poniżej znajdziesz kod skryptu maker.py z folderu repozytorium modułu 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()

Wykonanie tego skryptu spowoduje wyświetlenie oczekiwanych danych wyjściowych (o ile nie będzie żadnych błędów):

$ python3 maker.py
Created topic 'pullq' (projects/PROJECT_ID/topics/pullq)
Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)

Wywołanie interfejsu API w celu utworzenia już istniejących zasobów powoduje zgłoszenie wyjątku google.api_core.exceptions.AlreadyExists zgłoszonego przez bibliotekę klienta. Obsługiwany jest w sposób płynny przez skrypt:

$ python3 maker.py
Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq'
Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'

Jeśli nie masz doświadczenia z Pub/Sub, zapoznaj się z dokumentem na temat architektury Pub/Sub, aby uzyskać dodatkowe informacje.

5. Aktualizacja konfiguracji

Zmiany w konfiguracji obejmują zarówno zmianę różnych plików konfiguracji, jak i utworzenie odpowiednika kolejek pull App Engine, ale w ramach ekosystemu Cloud Pub/Sub.

Usuwanie pliku Que.yaml

Wycofujemy się całkowicie z kolejki zadań, więc usuń queue.yaml, ponieważ Pub/Sub nie korzysta z tego pliku. Zamiast tworzyć kolejkę pull, możesz utworzyć temat (i subskrypcję) w Pub/Sub.

requirements.txt

Dołącz zarówno google-cloud-ndb, jak i google-cloud-pubsub do elementu requirements.txt, tak aby złączyć flask z Modułu 18. Twój zaktualizowany moduł 19 (requirements.txt) powinien teraz wyglądać tak:

flask
google-cloud-ndb
google-cloud-pubsub

Ten plik requirements.txt nie zawiera żadnych numerów wersji, co oznacza, że wybierane są najnowsze wersje. Jeśli wystąpią jakiekolwiek niezgodności, stosuj standardową metodę blokowania wersji roboczych aplikacji, używając numerów wersji.

app.yaml

Zmiany w języku app.yaml różnią się w zależności od tego, czy chcesz pozostać w Pythonie 2, czy przejść na Pythona 3.

Python 2

W ramach powyższej aktualizacji requirements.txt dodaliśmy biblioteki klienta Google Cloud. Wymagają one dodatkowej obsługi ze strony App Engine, czyli kilku bibliotek wbudowanych oraz setuptools i grpcio. Korzystanie z wbudowanych bibliotek wymaga sekcji libraries w tagu app.yaml i numerów wersji biblioteki lub atrybutu „najnowsza” . Moduł 18 app.yaml nie zawiera jeszcze jednej z tych sekcji:

PRZED:

runtime: python27
threadsafe: yes
api_version: 1

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

Dodaj sekcję libraries do pliku app.yaml wraz z wpisami dotyczącymi setuptools i grpcio, wybierając ich najnowsze wersje. W momencie pisania tego posta dodaj też symbol zastępczy runtime dotyczący Pythona 3 wraz z obecną wersją 3.x, na przykład 3.10. Po wprowadzeniu tych zmian app.yaml wygląda tak:

PO:

#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

W przypadku użytkowników Pythona 3 i app.yaml chodzi przede wszystkim o usuwanie różnych rzeczy. W tej sekcji usuniesz sekcję handlers, dyrektywy threadsafe i api_version oraz nie utworzysz sekcji libraries.

Środowiska wykonawcze drugiej generacji nie zawierają wbudowanych bibliotek zewnętrznych, więc sekcja libraries nie jest potrzebna w systemie app.yaml. Poza tym kopiowanie (nazywane czasem „dodawaniem do dostawców” lub „samodzielnym grupowaniem”) niewbudowanych pakietów innych firm nie jest już wymagane. Wystarczy, że w requirements.txt zamieścisz listę bibliotek innych firm, z których korzysta Twoja aplikacja.

Sekcja handlers w narzędziu app.yaml służy do określania aplikacji (skryptu) i statycznych modułów obsługi plików. Ponieważ środowisko wykonawcze Pythona 3 wymaga platform internetowych do samodzielnego routingu, należy zmienić wszystkie moduły obsługi skryptów na auto. Jeśli Twoja aplikacja (np. Moduł 18) nie obsługuje plików statycznych, wszystkie trasy miałyby postać auto, przez co są nieistotne. Oznacza to, że sekcja handlers też jest niepotrzebna, więc ją usuń.

W Pythonie 3 nie są używane dyrektywy threadsafe ani api_version, więc je też usuń. Najważniejsze jest, aby usunąć wszystkie sekcje app.yaml, aby pozostała tylko dyrektywa runtime określająca nowoczesną wersję Pythona 3, na przykład 3.10. Tak wygląda app.yaml przed aktualizacją i po niej:

PRZED:

runtime: python27
threadsafe: yes
api_version: 1

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

PO:

runtime: python310

Dla użytkowników, którzy nie są gotowi na usunięcie wszystkiego z app.yaml w języku Python 3, w folderze repozytorium modułu 19 udostępniliśmy alternatywny plik app3.yaml. Jeśli chcesz użyć tego pliku we wdrożeniach, dołącz tę nazwę pliku na końcu polecenia: gcloud app deploy app3.yaml (w przeciwnym razie aplikacja będzie domyślnie działać i wdrożona z niezmienionym plikiem Python 2 app.yaml).

appengine_config.py

Jeśli aktualizujesz Pythona 3 do wersji 3, nie potrzebujesz dyrektywy appengine_config.py, więc usuń ją. Nie jest to konieczne, ponieważ obsługa bibliotek zewnętrznych wymaga ich jedynie w polu requirements.txt. Użytkownicy języka Python 2 – czytaj dalej.

Moduł 18 appengine_config.py zawiera odpowiedni kod do obsługi bibliotek zewnętrznych, np. biblioteki Flask i biblioteki klienta Cloud dodane właśnie do requirements.txt:

PRZED:

from google.appengine.ext import vendor

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

Jednak ten kod nie wystarczy do obsługi dodanych przed chwilą bibliotek wbudowanych (setuptools, grpcio). Potrzebnych jest jeszcze kilka wierszy, więc zaktualizuj appengine_config.py, by wyglądał tak:

PO:

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)

Więcej informacji o zmianach wymaganych do obsługi bibliotek klienta Cloud znajdziesz w dokumentacji migracji pakietów usług.

Inne aktualizacje konfiguracji

Jeśli masz folder lib, usuń go. Jeśli korzystasz z języka Python 2, uzupełnij folder lib, wykonując to polecenie:

pip install -t lib -r requirements.txt  # or pip2

Jeśli w Twoim systemie programistycznym masz zainstalowany język Python 2 i 3, może być konieczne użycie pip2 zamiast pip.

6. Modyfikowanie kodu aplikacji

W tej sekcji znajdziesz informacje o aktualizacjach w głównym pliku aplikacji main.py, które zastąpiły użycie kolejek pull kolejki zadań App Engine usługą Cloud Pub/Sub. W szablonie internetowym (templates/index.html) nie wprowadzono żadnych zmian. Obie aplikacje powinny działać identycznie i wyświetlać te same dane.

Aktualizowanie importów i inicjowania

Wprowadzono kilka aktualizacji dotyczących importowania i inicjowania:

  1. Na potrzeby importu zastąp NDB i kolejkę zadań App Engine danymi Cloud NDB i Pub/Sub.
  2. Zmień nazwę pullq z QUEUE na TOPIC.
  3. W przypadku zadań pobierania instancja robocza dzierżawi je na godzinę, ale w przypadku Pub/Sub limity czasu są mierzone na podstawie poszczególnych wiadomości, więc usuń stałą HOUR.
  4. Interfejsy Cloud APIs wymagają użycia klienta API, więc inicjuj je dla Cloud NDB i Cloud Pub/Sub, a ten drugi będzie dostarczać klienty zarówno dla tematów, jak i subskrypcji.
  5. Pub/Sub wymaga identyfikatora projektu Cloud, więc zaimportuj go i pobierz z usługi google.auth.default().
  6. Pub/Sub wymaga „pełnych i jednoznacznych nazw ścieżek” dla tematów i subskrypcji, więc twórz je za pomocą wygodnych funkcji *_path().

Poniżej znajdziesz informacje o importach i inicjowaniu z Modułu 18, a następnie, jak powinny wyglądać poszczególne sekcje po wprowadzeniu powyższych zmian, przy czym większość nowego kodu to różne zasoby Pub/Sub:

PRZED:

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

PO:

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)

Aktualizacje modelu danych wizyt

Model danych Visit się nie zmienia. Dostęp do Datastore wymaga jawnego użycia menedżera kontekstu klienta Cloud NDB API (ds_client.context()). W kodzie oznacza to opakowanie wywołań Datastore zarówno w store_visit(), jak i fetch_visits() wewnątrz bloków Pythona with. Ta aktualizacja jest identyczna z informacjami omówionymi w module 2.

Najważniejsza zmiana w przypadku Pub/Sub polega na zastąpieniu zadania pobierania kolejki zadań publikacją wiadomości Pub/Sub w temacie pullq. Poniżej znajduje się kod przed wprowadzeniem tych zmian i po ich wprowadzeniu:

PRZED:

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)

PO:

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)

Aktualizacje modelu danych liczby użytkowników

Model danych VisitorCount nie zmienia się i zmienia działanie fetch_counts() z wyjątkiem pakowania zapytania Datastore w blok with, jak pokazano poniżej:

PRZED:

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)

PO:

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)

Zaktualizuj kod instancji roboczej

Kod instancji roboczej aktualizuje się aż do zastąpienia NDB przez Cloud NDB, a kolejka zadań na Pub/Sub, ale jego przepływ pracy pozostaje taki sam.

  1. Opakuj wywołania Datastore w bloku with menedżera kontekstu Cloud NDB.
  2. Czyszczenie kolejki zadań obejmuje usunięcie z niej wszystkich zadań. W przypadku Pub/Sub „identyfikatory potwierdzenia” są zbierane w acks, a następnie usuwane/potwierdzone na końcu.
  3. Zadania pull kolejki zadań są dzierżawione w podobny sposób, jak pobieranie wiadomości Pub/Sub. Usuwanie zadań pull odbywa się za pomocą samych obiektów zadań, a wiadomości Pub/Sub są usuwane za pomocą ich identyfikatorów potwierdzenia.
  4. Ładunki wiadomości Pub/Sub wymagają bajtów (nie ciągów Pythona), dlatego podczas publikowania i pobierania wiadomości z tematu jest odpowiednie kodowanie i dekodowanie UTF-8.

Zastąp log_visitors() zaktualizowanym kodem poniżej, wprowadzając opisane poniżej zmiany:

PRZED:

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

PO:

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

Nie zmienił się główny moduł obsługi aplikacji root(). Nie musisz wprowadzać żadnych zmian w pliku szablonu HTML (templates/index.html), więc obejmuje to wszystkie niezbędne aktualizacje. Gratulujemy dotarcia do nowej aplikacji modułu 19 wykorzystującej Cloud Pub/Sub.

7. Podsumowanie/Czyszczenie

Wdróż aplikację, aby sprawdzić, czy działa prawidłowo i w odpowiednich danych wyjściowych. Uruchom także instancję roboczą, aby przetworzyć liczbę użytkowników. Po sprawdzeniu aplikacji wykonaj czynności związane z czyszczeniem i zastanów się nad dalszymi czynnościami.

Wdróż i zweryfikuj aplikację

Sprawdź, czy masz już utworzony temat pullq i subskrypcję worker. Jeśli przykładowa aplikacja jest gotowa do użycia, wdróż ją za pomocą gcloud app deploy. Dane wyjściowe powinny być takie same jak dane z aplikacji modułu 18, z wyjątkiem tego, że cały bazowy mechanizm kolejki został zastąpiony:

b667551dcbab1a09.png

Internetowy frontend aplikacji weryfikuje teraz działanie tej części aplikacji. W tej części aplikacji użytkownicy wyszukują informacje oraz wyświetlają informacje o największych i ostatnich wizytach. Pamiętaj jednak, że aplikacja rejestruje tę wizytę razem z zadaniem pull, aby dodać tego użytkownika do łącznej liczby użytkowników. To zadanie oczekuje teraz na przetworzenie.

Możesz to zrobić, korzystając z usługi backendu App Engine, zadania cron, przeglądając stronę /log lub wysyłając żądanie HTTP z wiersza poleceń. Oto przykładowe wykonanie, które nie spowoduje wywołania kodu instancji roboczej za pomocą curl (zastąp PROJECT_ID):

$ curl https://PROJECT_ID.appspot.com/log
DONE (with 1 task[s] logging 1 visitor[s])

Zaktualizowana liczba zostanie uwzględniona podczas następnej wizyty w witrynie. Znakomicie.

Czyszczenie danych

Ogólne

Jeśli na razie wszystko jest gotowe, wyłącz aplikację App Engine, aby uniknąć naliczania opłat. Jeśli jednak chcesz jeszcze bardziej przetestować lub poeksperymentować, platforma App Engine ma bezpłatny limit. Dopóki nie przekroczysz tego limitu, nie pobierzemy żadnych opłat. Oznacza to obliczenia, ale mogą być też naliczane opłaty za odpowiednie usługi App Engine. Więcej informacji znajdziesz na stronie z cennikiem. Jeśli ta migracja obejmuje inne usługi Cloud, są one rozliczane osobno. W obu przypadkach zapoznaj się z sekcją „Zapoznaj się z tymi ćwiczeniami”. sekcji poniżej.

Aby w pełni wyjaśnić wszystkie kwestie, wdrożenie na bezserwerowej platformie obliczeniowej Google Cloud, takiej jak App Engine, wiąże się z niewielkimi kosztami kompilacji i przechowywania danych. Cloud Build ma własny bezpłatny limit, podobnie jak Cloud Storage. Przechowywanie tego obrazu wykorzystuje część tego limitu. Możesz jednak mieszkać w regionie, w którym nie ma takiego poziomu bezpłatnego. Dlatego pamiętaj o wykorzystaniu miejsca na dane, aby zminimalizować potencjalne koszty. Określone „foldery” Cloud Storage należy sprawdzić m.in.:

  • 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
  • Powyższe linki do miejsca na dane zależą od Twoich danych PROJECT_ID oraz *LOC*, np. „us” jeśli aplikacja jest hostowana w Stanach Zjednoczonych.

Jeśli natomiast nie zamierzasz dalej korzystać z tej aplikacji lub innych powiązanych z nią ćwiczeń w Codelabs i chcesz całkowicie usunąć wszystko, zamknij projekt.

Powiązane z tym ćwiczeniam z programowania

Wymienione poniżej usługi są dostępne tylko w ramach tego ćwiczenia z programowania. Więcej informacji znajdziesz w dokumentacji poszczególnych usług:

  • Różne komponenty Cloud Pub/Sub mają poziom bezpłatny. określić ogólne wykorzystanie, aby uzyskać więcej informacji na temat kosztów usługi i zapoznać się ze stroną z cennikiem.
  • Usługa App Engine Datastore jest świadczona przez Cloud Datastore (Cloud Firestore w trybie Datastore), który również ma poziom bezpłatny. więcej informacji znajdziesz na stronie z cennikiem.

Dalsze kroki

Oprócz tego samouczka dostępne są też inne moduły migracji koncentrujące się na odejściu od starszych pakietów usług, które warto rozważyć:

  • Moduł 2. Migracja z App Engine ndb do Cloud NDB
  • Moduły 7–9. Migracja z kolejki zadań App Engine (zadań push) do Cloud Tasks
  • Moduły 12–13: migracja z App Engine Memcache do Cloud Memorystore
  • Moduły 15–16: migracja z App Engine Blobstore do Cloud Storage

App Engine nie jest już jedyną bezserwerową platformą w Google Cloud. Jeśli masz małą aplikację App Engine lub taką, która ma ograniczoną funkcjonalność i chcesz przekształcić ją w samodzielny mikroserwis, albo chcesz podzielić aplikację monolityczną na kilka komponentów wielokrotnego użytku, rozważ przejście na Cloud Functions. Jeśli konteneryzacja stała się częścią przepływu pracy przy tworzeniu aplikacji, zwłaszcza jeśli składa się z potoku CI/CD (ciągła integracja/ciągłe dostarczanie lub wdrażanie), rozważ migrację do Cloud Run. Te scenariusze są opisane w tych modułach:

  • Migracja z App Engine do Cloud Functions: patrz Moduł 11.
  • Migracja z App Engine do Cloud Run: zapoznaj się z Modułem 4, aby skonteneryzować aplikację za pomocą Dockera, lub Moduł 5, aby zrobić to bez kontenerów, Dockera lub Dockerfile.

Przejście na inną bezserwerową platformę jest opcjonalne. Zalecamy, aby przed wprowadzeniem jakichkolwiek zmian wybrać najlepsze opcje dla swoich aplikacji i przypadków użycia.

Niezależnie od tego, który moduł migracji wykorzystasz w następnej kolejności, wszystkie materiały z serwerowej platformy migracji (laboratorium, filmy, kod źródłowy [jeśli jest dostępne]) są dostępne w repozytorium open source. README repozytorium zawiera też wskazówki dotyczące migracji, które warto wziąć pod uwagę, i wszelkich odpowiednich „zamówień” modułów migracji.

8. Dodatkowe materiały

Poniżej znajdziesz dodatkowe materiały dla deweloperów omawiające ten lub powiązany moduł migracji oraz powiązane usługi. Są to miejsca, w których można przesłać opinię o tych treściach, linki do kodu i różne artykuły, które mogą Ci się przydać.

Problemy/opinie dotyczące ćwiczeń z programowania

Jeśli podczas korzystania z tych ćwiczeń z programowania zauważysz jakiekolwiek problemy, najpierw je wyszukaj. Linki do wyszukiwania i tworzenia nowych problemów:

Zasoby migracji

Linki do folderów repozytorium w modułach 18 (START) i modułach 19 (FINISH) znajdziesz w tabeli poniżej.

Codelab

Python 2

Python 3

Część 18

kod

(nd.)

Moduł 19 (to ćwiczenia z programowania)

kod

(tak samo jak w Pythonie 2, z wyjątkiem użycia app3.yaml, chyba że zaktualizujesz app.yaml w sposób opisany powyżej)

Dokumentacja online

Poniżej znajdziesz informacje na temat tego samouczka:

Kolejka zadań App Engine

Cloud Pub/Sub

App Engine NDB i Cloud NDB (Datastore)

Platforma App Engine

Inne informacje o Google Cloud

Filmy

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.