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. Większość takich migracji polega na rezygnacji z 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. Innym sposobem modernizacji aplikacji jest przejście na nowszą usługę. Temu właśnie poświęcone są te warsztaty.
Użytkownicy App Engine, którzy uzyskują dostęp do Datastore za pomocą bibliotek klienta Cloud NDB lub Cloud Datastore, nie muszą przeprowadzać dalszej migracji. Cloud Firestore to jednak najnowszy, skalowalny, wysoce dostępny magazyn danych NoSQL z funkcjami bazy danych czasu rzeczywistego Firebase.
Jeśli jesteś programistą, który chce korzystać z funkcji Firestore lub przynajmniej jest zainteresowany tym, co wiąże się z migracją, to dobrze trafiłeś. Z tego samouczka dowiesz się, jak przeprowadzić migrację aplikacji App Engine korzystającej z Cloud Datastore do Cloud Firestore.
Dowiesz się, jak:
- Rozpoznawanie różnic między Datastore a Firestore
- Migracja z Cloud Datastore do Cloud Firestore
Czego potrzebujesz
- Projekt Google Cloud Platform z tymi elementami:
- podstawowe umiejętności w zakresie Pythona,
- Praktyczna znajomość typowych poleceń systemu Linux
- Podstawowa wiedza na temat tworzenia i wdrażania aplikacji App Engine
- Zanim rozpoczniesz ten moduł (6), zalecamy ukończenie modułu 3, w tym przeniesienie go do Pythona 3.
- Działająca aplikacja w języku Python 3 App Engine z modułu 3 Cloud Datastore.
Ankieta
Jak zamierzasz wykorzystać to ćwiczenie?
2. Tło
Usługa Datastore w App Engine stała się osobnym produktem w 2013 roku, Google Cloud Datastore, i jest teraz dostępna dla deweloperów poza App Engine. W następnym roku Firebase zostało przejęte przez Google. W tym czasie była znana z bazy danych czasu rzeczywistego.
W ciągu kolejnych kilku lat zespoły Firebase i Cloud Datastore pracowały nad zintegrowaniem niektórych funkcji Firebase z Datastore. W 2017 roku wydaliśmy kolejną generację Cloud Datastore. Aby odzwierciedlić dziedziczenie niektórych funkcji Firebase, zmieniliśmy nazwę na Cloud Firestore.
Cloud Firestore stał się domyślnym mechanizmem przechowywania danych NoSQL w projektach Google Cloud. Nowe aplikacje mogą natywnie korzystać z Cloud Firestore, a istniejące bazy danych Datastore zostały przekonwertowane na Firestore i działają teraz jako „Firestore w trybie Datastore”, aby zachować zgodność z operacjami Datastore. W rezultacie aplikacje mogą korzystać z Cloud Firestore tylko w jednym z tych trybów, a po ustawieniu nie można go zmienić.
Obecnie, gdy użytkownicy tworzą nowe projekty i wybierają rozwiązanie NoSQL, są proszeni o wybranie Firestore w trybie Datastore lub Firestore w trybie natywnym. Gdy użytkownicy dodadzą encje Datastore, nie mogą przejść na Firestore. Podobnie, gdy wybiorą tryb natywny Firestore, nie mogą już wrócić do Datastore (a raczej do Firestore w trybie Datastore). Więcej informacji znajdziesz na stronie dotyczącej wyboru między Cloud Firestore w trybie Datastore a trybem natywnym Firestore w dokumentacji. Aby przenieść aplikację do Firestore, musisz utworzyć nowy projekt, wyeksportować Datastore, a następnie zaimportować go do Firestore. Celem tego samouczka jest przedstawienie programistom różnic między korzystaniem z Cloud Datastore a Cloud Firestore.
Nie oczekujemy, że użytkownicy będą przeprowadzać tę migrację, dlatego jest ona opcjonalna. Korzystanie z Cloud Firestore w sposób natywny ma oczywiste zalety, takie jak uwierzytelnianie klienta, integracja z regułami Firebase i oczywiście baza danych czasu rzeczywistego Firebase, ale kroki migracji są „niewygodne”:
- Musisz użyć innego projektu niż projekt bieżącej aplikacji.
- Projekt, w którym aplikacja dodała encje Datastore, nie może zostać przełączony na Firestore w trybie natywnym.
- Podobnie projekt, w którym wybrano Firestore w trybie natywnym, nie może wrócić do Firestore w trybie Datastore.
- Nie ma narzędzia do migracji, które umożliwiałoby przesyłanie strumieniowe danych z jednego projektu do drugiego.
- Niektóre kluczowe funkcje Datastore, w tym przestrzenie nazw i większa przepustowość zapisu (ponad 10 tys. operacji na sekundę), są niedostępne w Firestore.
- Narzędzia do eksportowania i importowania są „proste” i działają na zasadzie „wszystko albo nic”.
- Jeśli aplikacja ma wiele encji Datastore, eksportowanie, a następnie importowanie do Firestore może potrwać wiele godzin.
- W tym czasie aplikacja lub usługa nie będzie mogła zapisywać ani aktualizować danych.
- Działania związane z migracją są wliczane do normalnego użytkowania. Aby zminimalizować koszty, możesz rozłożyć je w czasie (w miarę możliwości w ramach dziennych limitów).
- Nowa usługa działa w innym projekcie, więc musisz poczekać, aż zmiany DNS zostaną rozpowszechnione.
- Datastore i Firestore mają podobne, ale różne modele danych, więc migracja wymaga zaktualizowania sposobu działania aplikacji lub usługi.
- Zapytania o elementy nadrzędne z Datastore są teraz zapytaniami o kolekcje Firestore (domyślnie).
- Zapytania o szerokim zakresie typów z Datastore to zapytania dotyczące grupy kolekcji w Firestore.
- Indeksy i obsługa są inne itp.
Jeśli jednak masz prostą aplikację, którą chcesz przenieść, przygotowujesz się do symulacji takiej migracji lub po prostu chcesz dowiedzieć się więcej o różnicach między Datastore a Firestore, czytaj dalej.
Użytkownicy Pythona 2: ten opcjonalny samouczek dotyczący migracji jest dostępny tylko w języku Python 3, ale ponieważ Cloud Firestore obsługuje też wersję 2.x, użytkownicy mogą sami określić różnice w użyciu. Na przykład rekordy Firestore używają ciągów Unicode (zamiast ciągów bajtów), więc w przypadku literałów ciągów w Pythonie 2 wymagany jest wskaźnik u'', co oznacza, że funkcja 2.x store_visit() będzie wyglądać tak:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
Poza tym biblioteka klienta powinna działać podobnie. Jedyną inną kwestią, którą należy wziąć pod uwagę, jest to, że biblioteka Cloud Firestore w wersji 2.x jest „zamrożona” pod względem programowania, więc coraz więcej nowszych funkcji będzie dostępnych tylko w bibliotece klienta Firestore w wersji 3.x.
Główne etapy tego samouczka to:
- Konfiguracja/przygotowanie
- Dodawanie biblioteki Cloud Firestore
- 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
Zalecamy ponowne użycie projektu, którego używasz do ukończenia ćwiczenia programistycznego z modułu 3. 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 (aplikacja) jest włączona.
2. Pobieranie przykładowej aplikacji podstawowej
Jednym z wymagań wstępnych do tego ćwiczenia z programowania jest działająca przykładowa aplikacja z modułu 3. Jeśli jej nie masz, przed przejściem do dalszej części wykonaj ćwiczenie z programowania z modułu 3 (link powyżej). Jeśli znasz już jego zawartość, możesz od razu pobrać kod modułu 3 poniżej.
Niezależnie od tego, czy używasz swojego kodu, czy naszego, ZACZNIEMY od kodu modułu 3. W tym module 6 znajdziesz szczegółowe instrukcje. Po jego ukończeniu kod powinien wyglądać jak w punkcie FINISH. (Ten samouczek jest dostępny tylko w przypadku języka Python 3).
- START: Repozytorium modułu 3
- FINISH: Repozytorium modułu 6
- Całe repozytorium (sklonuj lub pobierz plik ZIP)
Katalog plików modułu 3 (Twój lub nasz) powinien wyglądać tak:
$ ls
README.md main.py templates
app.yaml requirements.txt
3. (Ponowne) wdrażanie aplikacji z modułu 3
Pozostałe czynności przygotowawcze, które musisz teraz wykonać:
- Przypomnij sobie, jak korzystać z narzędzia wiersza poleceń
gcloud(w razie potrzeby). - (Ponowne) wdrożenie kodu modułu 3 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.
Wymagania dotyczące Pythona 2
- Sprawdź, czy
app.yamlnadal odwołuje się do pakietów zewnętrznych:grpcioisetuptools. - Upewnij się, że
appengine_config.pynadal używapkg_resourcesigoogle.appengine.ext.vendor, aby kierować aplikację do zasobów innych firm. - W następnej sekcji dotyczącej aktualizacji
requirements.txtmusisz użyćgoogle-cloud-firestore==1.9.0, ponieważ jest to ostatnia wersja biblioteki klienta Firestore w języku Python zgodna z wersją 2.x.- Jeśli w sekcji
requirements.txtjest wpis dotyczącygoogle-cloud-core, pozostaw go bez zmian. - Usuń
libi zainstaluj ponownie za pomocąpip install -t lib -r requirements.txt.
- Jeśli w sekcji
4. Aktualizowanie plików konfiguracyjnych (dodawanie biblioteki Cloud Firestore)
Po skonfigurowaniu musisz zaktualizować konfigurację, a następnie pliki aplikacji. W pierwszym przypadku jedyną zmianą konfiguracji jest niewielka zamiana pakietu w pliku requirements.txt, więc zróbmy to teraz.
Zastąp wiersz google-cloud-datastore w pliku requirements.txt wierszem google-cloud-firestore, aby wyglądał tak:
Flask==1.1.2
google-cloud-firestore==2.0.2
Zalecamy używanie najnowszych wersji każdej biblioteki. Podane powyżej numery wersji są najnowsze w momencie pisania tego artykułu. Kod w folderze repozytorium FINISH jest częściej aktualizowany i może mieć nowszą wersję.
Nie ma innych zmian konfiguracji, więc app.yaml i templates/index.html pozostają bez zmian.
5. Aktualizowanie plików aplikacji
Jest tylko jeden plik aplikacji, main.py, więc wszystkie zmiany w tej sekcji dotyczą tylko tego pliku.
1. Importy
Zmiana importu pakietu to drobna zmiana z datastore na firestore:
- PRZED:
from google.cloud import datastore
- PO:
from google.cloud import firestore
2. Dostęp do Firestore
Po zainicjowaniu Flaska utwórz klienta Firestore. Wprowadź podobną zmianę jak powyżej, ale w przypadku inicjowania klienta:
- PRZED:
app = Flask(__name__)
ds_client = datastore.Client()
- PO:
app = Flask(__name__)
fs_client = firestore.Client()
Przeprowadzając migrację z Cloud NDB do Cloud Datastore, wykonujesz już większość pracy potrzebnej do przejścia na Cloud Firestore. Za pomocą Datastore możesz tworzyć rekordy danych w postaci encji składających się z wspólnych właściwości i grupować je według kluczy. Rekordy danych w Firestore to dokumenty składające się z par klucz-wartość, które są pogrupowane w kolekcje. Migracja z Datastore wymaga uwzględnienia tych różnic, ponieważ będą one widoczne podczas tworzenia rekordów danych i wysyłania zapytań o nie. Wyniki mogą się różnić w zależności od złożoności kodu Datastore.
W przypadku Datastore zapytania są tworzone na podstawie typu encji wraz z kryteriami filtrowania i sortowania. W przypadku Firestore zapytania o dane działają podobnie. Spójrzmy na przykład, w którym założymy te wartości zapytania, klientów (ds_client lub fs_client) i importy:
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
W przypadku Datastore zapytajmy o 10 najnowszych Visit jednostek nowszych niż 1 października 2020 r. w kolejności malejącej:
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Zrób to samo w przypadku Firestore, wybierając Visit kolekcję:
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
Zapytanie w przykładowej aplikacji jest prostsze (nie zawiera klauzuli „WHERE”). Przypomnijmy sobie kod Cloud Datastore:
- PRZED:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
Po przejściu na Firestore tworzenie nowych dokumentów będzie podobne do tworzenia encji, a zapytania będą wyglądać tak jak wcześniej.
- PO:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
Główna funkcja root() pozostaje taka sama jak plik szablonu index.html. Sprawdź zmiany, zapisz je, wdróż i zweryfikuj.
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 6 (lub z wersją 2.x, jeśli wolisz).
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:

Gratulujemy ukończenia opcjonalnej migracji modułu 6. Jest to prawdopodobnie jedna z ostatnich migracji, jakie możesz przeprowadzić w zakresie przechowywania danych w App Engine. Jeśli jeszcze tego nie zrobisz, możesz rozważyć przeniesienie aplikacji do kontenera w Cloud Run (patrz moduły 4 i 5 w samouczkach podanych poniżej).
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 zostać obciążony(-a) za korzystanie z Firestore, jeśli przekroczy ono bezpłatny limit. W takim przypadku usuń wystarczającą ilość danych, aby zmieścić się w tym limicie.
Jeśli nie chcesz kontynuować migracji i chcesz wszystko całkowicie usunąć, możesz zamknąć projekt.
Dalsze kroki
Oprócz tego samouczka możesz skorzystać z kilku innych ćwiczeń z programowania dotyczących modułu migracji:
- Moduł 7: kolejki zadań push App Engine (wymagane, jeśli używasz kolejek zadań [push])
- Dodaje zadania push App Engine
taskqueuedo aplikacji Moduł 1 - Przygotowuje użytkowników do migracji do Cloud Tasks w module 8.
- Dodaje zadania push App Engine
- Moduł 4. Migracja do Cloud Run za pomocą Dockera
- Konteneryzowanie aplikacji do uruchamiania w Cloud Run za pomocą Dockera
- Ta migracja umożliwia dalsze korzystanie z języka Python 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
Dockerfile. - Wymaga migracji aplikacji do języka Python 3 (pakiety kompilacji nie obsługują języka Python 2).
7. 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 3 (START) i modułu 6 (FINISH) znajdziesz w tabeli poniżej. Możesz też uzyskać do nich dostęp w repozytorium wszystkich migracji App Engine, które możesz sklonować lub pobrać jako plik ZIP.
Ćwiczenia z programowania | Python 2 | Python 3 |
(kod) | ||
Moduł 6 | (n/a) |
Zasoby App Engine
Poniżej znajdziesz dodatkowe materiały dotyczące tej konkretnej migracji:
- Dokumentacja Cloud Datastore i Cloud Firestore w Pythonie
- Przenoszenie do języka Python 3 i środowiska wykonawczego GAE nowej generacji
- Ogólne