Moduł 2. Migracja z App Engine ndb do Cloud NDB

1. Przegląd

Ta seria ćwiczeń z programowania (samodzielnych samouczków praktycznych) ma pomóc deweloperom Google App Engine (Standard) w modernizacji aplikacji poprzez przeprowadzenie ich przez serię migracji. Najważniejszym krokiem jest odejście od usług dołączonych do oryginalnego środowiska wykonawczego, ponieważ środowiska wykonawcze nowej generacji są bardziej elastyczne i zapewniają użytkownikom większy wybór opcji usług. Przejście na środowisko wykonawcze nowszej generacji ułatwia integrację z usługami Google Cloud, korzystanie z szerszego zakresu obsługiwanych usług i obsługę bieżących wersji językowych.

Z tego samouczka dowiesz się, jak przeprowadzić migrację z wbudowanej w App Engine biblioteki klienta ndb (Next Database) na bibliotekę klienta Cloud NDB.

Dowiesz się, jak:

  • Użyj biblioteki ndb App Engine (jeśli jej nie znasz).
  • Migracja z ndb do Cloud NDB
  • Dalsze przenoszenie aplikacji do Pythona 3

Czego potrzebujesz

Ankieta

Jak zamierzasz wykorzystać to ćwiczenie?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

2. Tło

W module 1 przeprowadziliśmy migrację platform internetowych z wbudowanego środowiska webapp2 App Engine do Flask. W tym ćwiczeniu z programowania nadal odchodzimy od wbudowanych usług App Engine, przechodząc z biblioteki ndb App Engine na Cloud NDB od Google.

Po zakończeniu migracji możesz:

  1. Przejście na Pythona 3 i środowisko wykonawcze App Engine nowej generacji
  2. Migracja do Cloud Datastore (biblioteka klienta dla aplikacji innych niż App Engine)
  3. Skonteneryzuj aplikację w języku Python 2 (lub 3) i przenieś ją do Cloud Run.
  4. Dodaj korzystanie z kolejek zadań App Engine (push), a następnie przenieś je do Cloud Tasks.

Ale jeszcze do tego nie doszliśmy. Zanim przejdziesz do kolejnych kroków, dokończ ten codelab. Migracja opisana w tym samouczku obejmuje te główne kroki:

  1. Konfiguracja/przygotowanie
  2. Dodawanie biblioteki Cloud NDB
  3. Aktualizowanie plików aplikacji

3. Konfiguracja/przygotowanie

Zanim przejdziemy do głównej części samouczka, skonfigurujmy projekt, pobierzmy kod i wdrożymy aplikację podstawową, aby mieć pewność, że zaczynamy od działającego kodu.

1. Konfigurowanie projektu

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

2. Pobieranie przykładowej aplikacji podstawowej

Jednym z wymagań wstępnych jest działająca przykładowa aplikacja z modułu 1. Jeśli udało Ci się ukończyć ten samouczek, użyj swojego rozwiązania. Możesz to zrobić teraz (link powyżej) lub, jeśli chcesz pominąć ten krok, skopiuj repozytorium modułu 1 (link poniżej).

Niezależnie od tego, czy używasz własnego kodu, czy naszego, zaczniemy od kodu modułu 1. W tym module 2 znajdziesz szczegółowe instrukcje. Po jego ukończeniu kod powinien wyglądać jak kod w punkcie FINISH (w tym opcjonalny port „bonusowy” z Pythona 2 na Pythona 3):

Folder z kodem modułu STARTing 1 powinien zawierać te elementy:

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

Jeśli wykonasz samouczek z modułu 1, będziesz mieć też folder lib z Flaskiem i jego zależnościami. Jeśli nie masz folderu lib, utwórz go za pomocą polecenia pip install -t lib -r requirements.txt, abyśmy mogli w następnym kroku wdrożyć tę podstawową aplikację. Jeśli masz zainstalowane obie wersje Pythona, zalecamy używanie polecenia pip2 zamiast pip, aby uniknąć pomyłki z Pythonem 3.

3. (Ponowne) wdrażanie aplikacji z modułu 1

Pozostałe czynności przygotowawcze, które musisz teraz wykonać:

  1. Przypomnij sobie, jak korzystać z narzędzia wiersza poleceń gcloud (w razie potrzeby).
  2. (Ponowne) wdrożenie kodu modułu 1 w App Engine (w razie potrzeby)

Po pomyślnym wykonaniu tych czynności i potwierdzeniu, że wszystko działa, przejdziemy do dalszej części tego samouczka, zaczynając od plików konfiguracyjnych.

4. Aktualizowanie plików konfiguracyjnych (dodawanie biblioteki Cloud NDB)

Wiele oryginalnych wbudowanych usług App Engine przekształciło się w osobne produkty, a Datastore jest jednym z nich. Obecnie aplikacje inne niż App Engine mogą korzystać z Cloud Datastore. Dla użytkowników, którzy od dawna korzystają z ndb, zespół Google Cloud stworzył bibliotekę klienta Cloud NDB do komunikacji z Cloud Datastore. Jest on dostępny w wersji dla Pythona 2 i 3.

Zaktualizujmy pliki potwierdzenia, aby zastąpić App Engine ndb Cloud NDB, a następnie zmodyfikujmy aplikację.

1. Zaktualizuj: requirements.txt

W module 1 jedyną zewnętrzną zależnością naszej aplikacji był Flask. Teraz dodamy Cloud NDB. Oto jak wyglądał plik requirements.txt na końcu modułu 1:

  • PRZED:
Flask==1.1.2

Migracja z App Engine ndb wymaga biblioteki Cloud NDB (google-cloud-ndb), więc dodaj jej pakiet do requirements.txt.

  • PO:
Flask==1.1.2
google-cloud-ndb==1.7.1

W momencie pisania tego samouczka najnowszą zalecaną wersją była 1.7.1, ale w repozytorium requirements.txt może być dostępna nowsza wersja. Zalecamy korzystanie z najnowszych wersji każdej biblioteki, ale jeśli nie działają, możesz wycofać zmiany do starszej wersji.

Usuń folder lib, jeśli go masz i nie został on utworzony w poprzednim kroku. Teraz (ponownie) zainstaluj zaktualizowane biblioteki za pomocą polecenia pip install -t lib -r requirements.txt, w razie potrzeby używając pip2 zamiast pip.

2. Zaktualizuj: app.yaml

Dodanie bibliotek klienta Google Cloud, takich jak google-cloud-ndb, wiąże się z kilkoma wymaganiami, które dotyczą włączenia „wbudowanych” bibliotek, czyli pakietów innych firm dostępnych już na serwerach Google. Nie wymieniasz ich w requirements.txt ani nie kopiujesz za pomocą pip install. Wymagania:

  1. Określanie wbudowanych bibliotek w app.yaml
  2. Wskaż im skopiowane biblioteki zewnętrzne, z którymi mogą pracować (w lib).

Oto początkowy app.yaml z modułu 1:

  • PRZED:
runtime: python27
threadsafe: yes
api_version: 1

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

Teraz dodaj te wiersze do app.yaml, aby odwołać się do pary pakietów zewnętrznych: grpciosetuptools w nowej sekcji libraries:

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

Dlaczego warto używać tych wbudowanych bibliotek? gRPC to otwarty framework RPC używany przez wszystkie biblioteki klienta Google Cloud, w tym google-cloud-ndb. Biblioteka grpcio to adapter gRPC w Pythonie, dlatego jest wymagana. Wyjaśnienie, dlaczego uwzględniamy symbol setuptools, znajdziesz poniżej.

  • PO:

Po wprowadzeniu powyższych zmian zaktualizowany plik app.yaml powinien wyglądać tak:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

3. Zaktualizuj: appengine_config.py

Narzędzie pkg_resources, które jest częścią biblioteki setuptools, umożliwia wbudowanym bibliotekom innych firm dostęp do bibliotek dołączonych. Zaktualizuj appengine_config.py, aby używać pkg_resources i wskazywać dołączone biblioteki w lib. Po wprowadzeniu tej zmiany cały plik powinien wyglądać tak:

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)

5. Aktualizowanie plików aplikacji

Po dopełnieniu formalności związanych z plikiem konfiguracyjnym możesz przeprowadzić migrację z ndb do Cloud NDB. Aby dokończyć migrację, zaktualizuj importowane biblioteki i dodaj użycie zarządzania kontekstem w main.py.

1. Importy

W pliku main.py zamień import na ten:

  • PRZED
from google.appengine.ext import ndb
  • PO:
from google.cloud import ndb

Zmiana biblioteki App Engine na bibliotekę Google Cloud może być czasami tak subtelna jak w tym przypadku. W przypadku wbudowanych usług, które stały się pełnymi produktami Google Cloud, atrybuty będziesz importować z google.cloud zamiast z google.appengine.

2. Dostęp do Datastore

Aby móc korzystać z biblioteki Cloud NDB, aplikacja musi używać menedżerów kontekstu Pythona. Ich celem jest „ograniczanie” dostępu do zasobów w taki sposób, aby można było z nich korzystać dopiero po ich uzyskaniu. Menedżerowie kontekstu opierają się na technice sterowania w informatyce znanej jako alokacja zasobów to inicjalizacja (Resource Allocation Is Initialization, RAII). Menedżery kontekstu są używane w przypadku plików Pythona (które muszą być otwarte, zanim będzie można uzyskać do nich dostęp) i równoczesności. Przed wykonaniem kodu w „sekcji krytycznej” należy uzyskać „blokady spinlock”.

Podobnie Cloud NDB wymaga uzyskania kontekstu klienta do komunikacji z Datastore, zanim będzie można wykonać jakiekolwiek polecenia Datastore. Najpierw utwórz klienta (ndb.Client()), dodając ds_client = ndb.Client() w main.py bezpośrednio po zainicjowaniu Flaska:

app = Flask(__name__)
ds_client = ndb.Client()

Polecenie Pythonwith służy wyłącznie do uzyskiwania kontekstu obiektu. Obejmij wszystkie bloki kodu, które uzyskują dostęp do Datastore, instrukcjami with.

Poniżej znajdziesz te same funkcje z modułu 1, które służą do zapisywania nowego obiektu w Datastore i odczytywania ostatnio dodanych obiektów w celu ich wyświetlenia:

  • PRZED:

Oto oryginalny kod bez zarządzania kontekstem:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))
  • PO:

Teraz dodaj with ds_client.context(): i przenieś kod dostępu do Datastore do bloku with:

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

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch(limit))

Główna aplikacja sterownika pozostaje taka sama jak w module 1, ponieważ nie ma w niej kodu ndb (ani Cloud NDB):

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

Sprawdzoną metodą jest zapewnienie wyraźnego rozróżnienia między kodem aplikacji a dostępem do danych. Dzięki temu główny kod aplikacji nie zmienia się, gdy zmieniamy podstawowy mechanizm przechowywania danych, tak jak w przypadku tej migracji.

6. Podsumowanie i czyszczenie

Wdróż aplikację

Ponownie wdróż aplikację za pomocą gcloud app deploy i sprawdź, czy działa. Twój kod powinien teraz być zgodny z kodem w repozytorium modułu 2.

Jeśli zaczniesz od tego artykułu, nie wykonując żadnych poprzednich ćwiczeń z programowania, aplikacja się nie zmieni. Będzie rejestrować wszystkie wizyty na głównej stronie internetowej (/) i po wystarczającej liczbie wizyt będzie wyglądać tak:

aplikacja visitme

Gratulujemy ukończenia ćwiczenia z modułu 2. To już ostatnia z zdecydowanie zalecanych migracji z tej serii dotyczących Datastore.

Opcjonalnie: zwalnianie miejsca

A co z wyczyszczeniem danych, aby uniknąć opłat do czasu, aż będziesz gotowy(-a) na kolejny etap migracji? Jako obecni deweloperzy prawdopodobnie znasz już informacje o cenach App Engine.

Opcjonalnie: wyłączanie aplikacji

Jeśli nie chcesz jeszcze przechodzić do następnego samouczka, wyłącz aplikację, aby uniknąć naliczania opłat. Gdy zechcesz przejść do kolejnych ćwiczeń, możesz ponownie włączyć tę funkcję. Gdy aplikacja jest wyłączona, nie generuje ruchu, a tym samym nie powoduje naliczania opłat. Możesz jednak ponosić koszty związane z korzystaniem z Datastore, jeśli przekroczysz bezpłatny limit. W takim przypadku usuń wystarczającą ilość danych, aby zmieścić się w limicie.

Jeśli nie chcesz kontynuować migracji i chcesz wszystko całkowicie usunąć, możesz zamknąć projekt.

Dalsze kroki

Dalsze kroki zależą od Ciebie. Wybierz jedną z tych opcji:

  • Moduł 2 (dodatkowy): przejdź do dodatkowej części tego samouczka, aby dowiedzieć się więcej o przenoszeniu aplikacji do Pythona 3 i środowiska wykonawczego App Engine nowej generacji.
  • Moduł 7: kolejki zadań push App Engine (wymagane, jeśli używasz kolejek zadań [push])
    • Dodaje zadania push App Engine taskqueue do aplikacji Moduł 1
    • Przygotowuje użytkowników do migracji do Cloud Tasks w module 8.
  • Moduł 4. Migracja do Cloud Run za pomocą Dockera
    • Konteneryzowanie aplikacji do uruchamiania w Cloud Run za pomocą Dockera
    • Umożliwia pozostanie przy Pythonie 2
  • Moduł 5. Migracja do Cloud Run za pomocą Cloud Buildpacks
    • Konteneryzowanie aplikacji do uruchamiania w Cloud Run za pomocą pakietów kompilacji Cloud Build
    • Nie musisz nic wiedzieć o Dockerze, kontenerach ani Dockerfiles.
    • Wymaga przeniesienia aplikacji do Pythona 3.
  • Moduł 3:
    • Modernizacja dostępu do Datastore z Cloud NDB do Cloud Datastore
    • Jest to biblioteka używana w przypadku aplikacji App Engine w Pythonie 3 i aplikacji spoza App Engine.

7. BONUS: Migracja do Pythona 3

Aby mieć dostęp do najnowszego środowiska wykonawczego i funkcji App Engine, zalecamy migrację do Pythona 3. W naszej przykładowej aplikacji Datastore była jedyną wbudowaną usługą, z której korzystaliśmy. Po przejściu z ndb na Cloud NDB możemy teraz przenieść aplikację do środowiska wykonawczego Pythona 3 w App Engine.

Przegląd

Przenoszenie kodu do języka Python 3 nie jest tematem samouczka Google Cloud, ale ta część laboratorium daje programistom wyobrażenie o tym, czym różni się środowisko wykonawcze App Engine w Pythonie 3. Jedną z najważniejszych funkcji środowiska wykonawczego nowej generacji jest uproszczony dostęp do pakietów innych firm. Nie musisz określać wbudowanych pakietów w app.yaml ani kopiować ani przesyłać bibliotek niewbudowanych. Są one instalowane niejawnie na podstawie informacji w requirements.txt.

Ponieważ nasz przykład jest bardzo prosty i Cloud NDB jest zgodny z Pythonem 2 i 3, nie trzeba przenosić kodu aplikacji do wersji 3.x. Aplikacja działa w wersjach 2.x i 3.x bez zmian, co oznacza, że w tym przypadku jedyne wymagane zmiany dotyczą konfiguracji:

  1. Uprość app.yaml, aby odwoływać się do Pythona 3 i usunąć biblioteki innych firm.
  2. Usuń appengine_config.py i folder lib, ponieważ nie są już potrzebne.

Oprócz pliku main.py pliki requirements.txttemplates/index.html pozostają bez zmian.

Uprość app.yaml

PRZED:

Jedyną prawdziwą zmianą w tej przykładowej aplikacji jest znaczne skrócenie app.yaml. Przypominamy, co mieliśmy w app.yaml na koniec Modułu 2:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

PO:

W Pythonie 3 dyrektywy threadsafe, api_versionlibraries są przestarzałe. Zakłada się, że wszystkie aplikacje są bezpieczne dla wątków, a dyrektywa api_version nie jest używana w Pythonie 3. W usługach App Engine nie ma już wstępnie zainstalowanych pakietów innych firm, więc libraries też jest wycofany. Więcej informacji o tych zmianach znajdziesz w dokumentacji dotyczącej zmian w app.yaml. W związku z tym usuń wszystkie 3 wersje z app.yaml i zaktualizuj je do obsługiwanej wersji Pythona 3 (patrz poniżej).

Opcjonalnie: użycie dyrektywy handlers

Poza tym wycofana została dyrektywa handlers, która kieruje ruch do aplikacji App Engine. Środowisko wykonawcze nowej generacji oczekuje, że frameworki internetowe będą zarządzać routingiem aplikacji, dlatego wszystkie „skrypty obsługi” muszą zostać zmienione na „auto”. Łącząc powyższe zmiany, otrzymasz ten kod: app.yaml.

runtime: python38

handlers:
- url: /.*
  script: auto

Dowiedz się więcej o script: auto na stronie dokumentacji.

Usuwanie dyrektywy handlers

Ponieważ element handlers jest wycofany, możesz też usunąć całą sekcję, pozostawiając jedno wierszowy element app.yaml:

runtime: python38

Domyślnie uruchomi to serwer WWW Gunicorn WSGI, który jest dostępny dla wszystkich aplikacji. Jeśli znasz gunicorn, to jest polecenie wykonywane, gdy jest ono uruchamiane domyślnie z najprostszym app.yaml:

gunicorn main:app --workers 2 -c /config/gunicorn.py

Opcjonalnie: użycie dyrektywy entrypoint

Jeśli jednak aplikacja wymaga określonego polecenia uruchamiania, można je określić za pomocą dyrektywy entrypoint, w której app.yaml wyglądałoby tak:

runtime: python38
entrypoint: python main.py

W tym przykładzie wyraźnie żądamy użycia serwera deweloperskiego Flask zamiast gunicorn. Do aplikacji należy też dodać kod, który uruchamia serwer deweloperski na interfejsie 0.0.0.0 na porcie 8080. W tym celu dodaj ten mały fragment na końcu pliku main.py:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Więcej informacji o entrypoint znajdziesz na stronie dokumentacji. Więcej przykładów i sprawdzonych metod znajdziesz w dokumentacji dotyczącej uruchamiania standardowego środowiska App Engine oraz w dokumentacji dotyczącej uruchamiania elastycznego środowiska App Engine.

Usuń: appengine_config.pylib

Usuń plik appengine_config.py i folder lib. Podczas migracji do Pythona 3 App Engine pobiera i instaluje pakiety wymienione w requirements.txt.

Plik konfiguracyjny appengine_config.py służy do rozpoznawania bibliotek i pakietów innych firm, niezależnie od tego, czy zostały skopiowane przez Ciebie, czy są już dostępne na serwerach App Engine (wbudowane). Podczas przechodzenia na język Python 3 najważniejsze zmiany to:

  1. Brak pakietów skopiowanych bibliotek innych firm (wymienionych w requirements.txt)
  2. Brak pip install w folderze lib, co oznacza, że nie ma folderu lib.
  3. Brak wbudowanych bibliotek zewnętrznych w app.yaml
  4. Nie trzeba odwoływać się do aplikacji w bibliotekach innych firm, więc nie ma pliku appengine_config.py.

Wystarczy wymienić wszystkie wymagane biblioteki innych firm w requirements.txt.

Wdróż aplikację

Ponownie wdróż aplikację, aby mieć pewność, że działa. Możesz też sprawdzić, jak blisko Twoje rozwiązanie jest przykładowego kodu w Pythonie 3 z modułu 2. Aby zobaczyć różnice w Pythonie 2, porównaj kod z jego wersją w Pythonie 2.

Gratulujemy ukończenia kroku dodatkowego w module 2. Zapoznaj się z dokumentacją dotyczącą przygotowywania plików konfiguracyjnych dla środowiska wykonawczego Python 3. Na koniec zapoznaj się ze stroną Podsumowanie/Czyszczenie (wcześniejszą), aby poznać kolejne kroki i wykonać czyszczenie.

Przygotowywanie Twojej aplikacji

Gdy nadejdzie czas na migrację aplikacji, musisz przenieść pliki main.py i inne pliki aplikacji do wersji 3.x. Dlatego warto zadbać o to, aby aplikacja w wersji 2.x była jak najbardziej „kompatybilna z przyszłymi wersjami”.

W sieci znajdziesz wiele materiałów, które Ci w tym pomogą. Oto kilka najważniejszych wskazówek:

  1. Upewnij się, że wszystkie zależności aplikacji są w pełni zgodne z wersją 3.x.
  2. Upewnij się, że aplikacja działa w wersji co najmniej 2.6 (najlepiej 2.7).
  3. Upewnij się, że aplikacja przechodzi cały zestaw testów (i ma co najmniej 80% pokrycia).
  4. Korzystaj z bibliotek zgodności, takich jak six, Future lub Modernize.
  5. Poznaj najważniejsze różnice między wersjami 2.x i 3.x, które nie są ze sobą zgodne
  6. Każda operacja wejścia-wyjścia prawdopodobnie spowoduje niezgodności między ciągami Unicode a ciągami bajtów.

Aplikacja przykładowa została zaprojektowana z uwzględnieniem tych kwestii, dlatego działa od razu w wersjach 2.x i 3.x. Dzięki temu możemy skupić się na pokazaniu Ci, co należy zmienić, aby korzystać z platformy nowej generacji.

8. Dodatkowe materiały

Problemy i opinie dotyczące ćwiczeń z programowania modułu migracji App Engine

Jeśli zauważysz jakieś problemy z tym kursem, najpierw poszukaj rozwiązania, a dopiero potem zgłoś problem. Linki do wyszukiwania i tworzenia nowych problemów:

Materiały dotyczące migracji

Linki do folderów repozytorium dla modułu 1 (START) i modułu 2 (FINISH) znajdziesz w tabeli poniżej. Możesz też uzyskać do nich dostęp w repozytorium wszystkich migracji codelabów App Engine, które możesz sklonować lub pobrać jako plik ZIP.

Ćwiczenia z programowania

Python 2

Python 3

Moduł 1

kod

(n/a)

Moduł 2

kod

kod

Zasoby App Engine

Poniżej znajdziesz dodatkowe materiały dotyczące tej konkretnej migracji: