Jak korzystać z kolejki zadań App Engine (zadania push) w aplikacjach Flask (moduł 7)

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.

Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak korzystać z zadań push kolejki zadań w App Engine w przykładowej aplikacji z modułu 1 Codelabs. Post na blogu i film w module 7 uzupełniają ten samouczek i zawiera krótkie omówienie jego treści.

W tym module dodamy sposób użycia zadań push, a następnie w module 8 i nowszych przenieśmy to wykorzystanie do Cloud Tasks, do Pythona 3 i Cloud Datastore w module 9. Osoby korzystające z kolejek zadań do zadań pull zostaną przeniesione do Cloud Pub/Sub i powinny skorzystać z modułów 18–19.

Dowiesz się, jak:

  • Używanie interfejsu App Engine Task Queue API/usługi pakietu
  • Dodawanie użycia zadań push do podstawowej aplikacji w Pythonie 2 Flask App Engine NDB

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, zespół Google Cloud zaleca migrację ze starszych pakietów usług, takich jak Task Queue, do innych samodzielnych usług Cloud lub ich odpowiedników innych firm.

Migracja zadań pull jest uwzględniona w modułach migracji 18–19, a moduły 7–9 dotyczą migracji zadań push. Aby przeprowadzić migrację z zadań push kolejki zadań App Engine, dodaj informacje o ich wykorzystaniu do dotychczasowej aplikacji Flask i App Engine NDB w ramach modułu 1 Codelabs. W tej aplikacji nowe wyświetlenie strony rejestruje nowe odwiedziny i wyświetla informacje o ostatnich wizytach użytkownika. Starsze wizyty nigdy nie są wyświetlane ponownie i zajmują miejsce w Datastore, dlatego utworzymy zadanie push, aby automatycznie usuwać najstarsze wizyty. W module 8 przeniesiemy tę aplikację z kolejki zadań do Cloud Tasks.

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

Dzięki tym krokom zaczynasz od działającego kodu.

1. Konfigurowanie projektu

Jeśli masz już za sobą moduł 1 z programowania, zalecamy ponowne wykorzystanie tego samego projektu (i kodu). Możesz też utworzyć nowy projekt lub wykorzystać inny istniejący projekt. Sprawdź, czy projekt ma aktywne konto rozliczeniowe i jest włączona usługa App Engine.

2. Pobierz przykładową aplikację bazową

Jednym z warunków wstępnych tego ćwiczenia z programowania jest posiadanie działającej aplikacji App Engine 1 w module 1. Wykonaj ćwiczenie z modułu 1 (zalecane) lub skopiuj aplikację z modułu 1 z repozytorium. Bez względu na to, czy używasz swojego czy naszego, „ROZPOCZNIJ” kod Modułu 1. To ćwiczenie w Codelabs przeprowadzi Cię przez poszczególne kroki, kończąc kodem przypominającym zawartość folderu repozytorium modułu 7 „FINISH”.

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

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

3. (Ponowne) wdrażanie aplikacji podstawowej

Aby (ponownie) wdrożyć aplikację w module 1, 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 masz zainstalowany język Python 2 i 3, może być konieczne użycie polecenia pip2.
  2. Upewnij się, że narzędzie wiersza poleceń gcloud zostało zainstalowane i zainicjowane, a także sprawdzisz jego użycie.
  3. Jeśli nie chcesz wpisywać PROJECT_ID w projekcie Cloud z każdym wydanym poleceniem gcloud, ustaw w nim gcloud config set project PROJECT_ID.
  4. Wdróż przykładową aplikację za pomocą: gcloud app deploy
  5. Potwierdź, że aplikacja w module 1 działa zgodnie z oczekiwaniami, bez problemów z wyświetlaniem ostatnich wizyt (poniżej).

a7a9d2b80d706a2b.png

4. Aktualizacja konfiguracji

W standardowych plikach konfiguracji App Engine (app.yaml, requirements.txt, appengine_config.py) nie musisz wprowadzać żadnych zmian.

5. Modyfikowanie plików aplikacji

Główny plik aplikacji to main.py i wszystkie aktualizacje w tej sekcji odnoszą się do tego pliku. Wprowadzono też niewielką aktualizację w szablonie internetowym: templates/index.html. W tej sekcji należy wprowadzić następujące zmiany:

  1. Aktualizowanie importów
  2. Dodaj zadanie push
  3. Dodaj moduł obsługi zadań
  4. Zaktualizuj szablon internetowy

1. Aktualizowanie importów

Import aplikacji google.appengine.api.taskqueue udostępnia funkcję kolejki zadań. Wymagane są też niektóre pakiety biblioteki standardowej w Pythonie:

  • Dodajemy zadanie usuwania najstarszych wizyt, więc aplikacja będzie musiała obsługiwać sygnatury czasowe, co oznacza korzystanie z funkcji time i datetime.
  • Aby zarejestrować przydatne informacje o wykonywaniu zadań, potrzebujemy pliku logging.

Gdy dodasz wszystkie te operacje importu, Twój kod będzie wyglądał przed tymi zmianami i po ich wprowadzeniu:

PRZED:

from flask import Flask, render_template, request
from google.appengine.ext import ndb

PO:

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

2. Dodaj zadanie push (zbieranie danych dla zadania, dodawanie do kolejki nowego zadania)

Według dokumentacji kolejki push: „Aby przetworzyć zadanie, musisz dodać je do kolejki push. App Engine udostępnia domyślną kolejkę push o nazwie default, która jest skonfigurowana i gotowa do użycia z ustawieniami domyślnymi. Jeśli chcesz, możesz po prostu dodać wszystkie zadania do kolejki domyślnej bez konieczności tworzenia i konfigurowania innych kolejek”. Dla zachowania zwięzłości te ćwiczenia w Codelabs korzystają z kolejki default. Więcej informacji na temat definiowania własnych kolejek push, które mają takie same lub różniące się cechy, znajdziesz w dokumentacji dotyczącej tworzenia kolejek push.

Głównym celem tego ćwiczenia w Codelabs jest dodanie zadania (do kolejki push default), którego zadaniem jest usuwanie z Datastore starych wizyt, które nie są już wyświetlane. Aplikacja bazowa rejestruje każdą wizytę (żądanie GET do /), tworząc nowy element Visit, a następnie pobiera i wyświetla ostatnie wizyty. Żadna z najstarszych wizyt nigdy nie zostanie wyświetlona ani użyta, więc zadanie push usuwa wszystkie wizyty starsze niż najstarsze wyświetlone. W tym celu musisz zmienić działanie aplikacji:

  1. Podczas wysyłania zapytań dotyczących ostatnich wizyt, zamiast od razu zwracać te wizyty, zmodyfikuj aplikację tak, aby zapisywała sygnaturę czasową ostatniego Visit – najstarszej wyświetlonej wizyty – można bezpiecznie usunąć wszystkie starsze wizyty.
  2. Utwórz zadanie push z tą sygnaturą czasową jako ładunkiem i skieruj je do modułu obsługi zadania dostępnego przez HTTP POST do /trim. W szczególności używaj standardowych narzędzi w języku Python, aby przekonwertować sygnaturę czasową Datastore i wysyłać ją (w postaci liczby zmiennoprzecinkowej) do zadania, a także zarejestrować ją (jako ciąg znaków) i zwrócić ten ciąg jako wartość, która zostanie wyświetlona użytkownikowi.

Wszystko to dzieje się w fetch_visits(), a przed wprowadzeniem tych zmian i po ich wprowadzeniu wygląda to tak:

PRZED:

def fetch_visits(limit):
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))

PO:

def fetch_visits(limit):
    'get most recent visits and 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 (v.to_dict() for v in data), oldest_str

3. Dodaj moduł obsługi zadania (kod jest wywoływany po uruchomieniu zadania)

Usunięcie starych wizyt w aplikacji fetch_visits() mogłoby być łatwe, ale pamiętaj, że ta funkcja nie ma zbyt wiele wspólnego z użytkownikami. Jest to funkcja pomocnicza, która nadaje się do przetwarzania asynchronicznego poza standardowymi żądaniami aplikacji. Użytkownik będzie mógł skorzystać z szybszych zapytań, ponieważ będzie zawierać mniej informacji w Datastore. Utwórz nową funkcję trim() wywoływaną za pomocą żądania POST kolejki zadań na stronie /trim, która wykonuje te czynności:

  1. Wyodrębnia „najstarszą wizytę” ładunek sygnatury czasowej
  2. Wysyła zapytanie Datastore, aby znaleźć wszystkie encje starsze niż wskazana sygnatura czasowa.
  3. Wolimy szybszą szybkość obsługi „tylko klucze” ponieważ dane użytkowników nie są potrzebne.
  4. Rejestruje liczbę encji do usunięcia (wliczając 0).
  5. Wywołuje funkcję ndb.delete_multi(), aby usunąć wszystkie jednostki (w przeciwnym razie zostaje pominięty).
  6. Zwraca pusty ciąg (wraz z niejawnym zwracanym kodem HTTP 200).

To wszystko znajdziesz poniżej w trim(). Dodaj do main.py tuż po fetch_visits():

@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

4. Zaktualizuj szablon internetowy

Zaktualizuj szablon internetowy (templates/index.html) za pomocą tego warunkowego Jinja2, aby wyświetlić najstarszą sygnaturę czasową, jeśli ta zmienna istnieje:

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}

Dodaj ten fragment kodu po wyświetlanej liście wizyt, ale przed zamknięciem treści. W ten sposób szablon będzie wyglądał tak:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}
</body>
</html>

6. Podsumowanie/Czyszczenie

W tej sekcji znajdziesz podsumowanie tego ćwiczenia w programie przez wdrożenie aplikacji oraz sprawdzenie, czy działa ona zgodnie z oczekiwaniami i we wszystkich uwzględnionych danych wyjściowych. Po sprawdzeniu aplikacji oczyść ją i zastanów się nad dalszymi czynnościami.

Wdróż i zweryfikuj aplikację

Wdróż aplikację za pomocą: gcloud app deploy. Dane wyjściowe powinny być takie same jak w przypadku aplikacji z modułu 1, z wyjątkiem u dołu nowego wiersza pokazującego, które wizyty zostaną usunięte:

4aa8a2cb5f527079.png

Gratulujemy ukończenia ćwiczeń z programowania. Twój kod powinien być zgodny z zawartością w folderze repozytorium modułu 7. Możesz teraz przejść na Cloud Tasks w module 8.

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:

Dalsze kroki

W trakcie migracji dodano użycie kolejki push kolejki zadań do przykładowej aplikacji w module 1 i dodano obsługę śledzenia użytkowników, co spowodowało powstanie przykładowej aplikacji w module 7. W ramach następnej migracji nauczysz się, jak przejść z zadań push App Engine do Cloud Tasks. Jesienią 2021 roku użytkownicy nie muszą już migrować do Cloud Tasks po przejściu na Pythona 3. Więcej informacji na ten temat znajdziesz w następnej sekcji.

Jeśli chcesz przejść do Cloud Tasks, przejdź do modułu 8 Codelabs. Oprócz tego trzeba wziąć pod uwagę dodatkowe migracje, takie jak Cloud Datastore, Cloud Memorystore, Cloud Storage czy Cloud Pub/Sub (kolejki pull). Dostępne są też migracje z różnych usług do Cloud Run i Cloud Functions. Wszystkie materiały z serwerowej stacji migracji (laboratoria, filmy, kod źródłowy [jeśli jest dostępne]) są dostępne w repozytorium open source tej platformy.

7. Migracja do Pythona 3

Jesienią 2021 r. zespół App Engine rozszerzył obsługę wielu pakietów usług na środowiska wykonawcze 2 generacji (wcześniej dostępne tylko w środowiskach wykonawczych 1 generacji). Oznacza to, że podczas przenoszenia aplikacji na Pythona 3 nie trzeba już przeprowadzać migracji z pakietów usług, takich jak kolejka zadań App Engine, do samodzielnych usług Cloud lub ich odpowiedników innych firm, takich jak Cloud Tasks. Inaczej mówiąc, możesz nadal korzystać z kolejki zadań w aplikacjach App Engine w języku Python 3, o ile tylko zmodernizuj kod, aby uzyskał dostęp do pakietów usług ze środowisk wykonawczych nowej generacji.

Więcej informacji o tym, jak przenieść użycie usług zawartych w pakiecie do Pythona 3, znajdziesz w module Codelabs (Moduł 17) i odpowiednim filmie. Chociaż ten temat nie jest objęty Modułem 7, poniżej znajdziesz linki do wersji Pythona 3 obu modułów 1 i 7 aplikacji przeniesionych do Pythona 3, które nadal używają App Engine NDB i kolejki zadań.

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ę na temat tych treści, linki do kodu i różne artykuły, które mogą Ci się przydać.

Problemy z ćwiczeniami w Codelabs/opinie

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 2 (START) i modułach 7 (FINISH) znajdziesz w tabeli poniżej.

Codelab

Python 2

Python 3

Część 1

kod

code (kod nie jest omówiony w tym samouczku)

Moduł 7 (to ćwiczenia z programowania)

kod

code (kod nie jest omówiony w tym samouczku)

Zasoby online

Poniżej znajdują się zasoby online, które mogą być pomocne w przypadku tego samouczka:

Kolejka zadań App Engine

Platforma App Engine

Inne informacje o Google Cloud

Filmy

Licencja

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