Z tego dokumentu dowiesz się, jak skalować aplikację bezserwerową, aby obsługiwała więcej niż tysiące operacji na sekundę lub setki tysięcy użytkowników jednocześnie. Ten dokument zawiera zaawansowane tematy, które pomogą Ci dogłębnie zrozumieć system. Jeśli dopiero zaczynasz korzystać z Cloud Firestore, zapoznaj się z krótkim przewodnikiem.
Cloud Firestore i pakiety SDK Firebase na urządzenia mobilne i do internetu zapewniają zaawansowany model tworzenia aplikacji bezserwerowych, w których kod po stronie klienta ma bezpośredni dostęp do bazy danych. Pakiety SDK umożliwiają klientom nasłuchiwanie aktualizacji danych w czasie rzeczywistym. Możesz używać aktualizacji w czasie rzeczywistym do tworzenia responsywnych aplikacji, które nie wymagają infrastruktury serwerowej. Chociaż uruchomienie aplikacji jest bardzo proste, warto poznać ograniczenia systemów, które składają się na Cloud Firestore, aby aplikacja bezserwerowa skalowała się i działała wydajnie w przypadku zwiększonego ruchu.
W sekcjach poniżej znajdziesz porady dotyczące skalowania aplikacji.
Wybierz lokalizację bazy danych w pobliżu użytkowników
Ten diagram przedstawia architekturę aplikacji działającej w czasie rzeczywistym:
Gdy aplikacja działająca na urządzeniu użytkownika (mobilnym lub w internecie) nawiązuje połączenie z Cloud Firestore, jest ono kierowane do serwera front-end Cloud Firestore w tym samym regionie, w którym znajduje się Twoja baza danych. Jeśli na przykład baza danych znajduje się w regionie us-east1
, połączenie jest kierowane do frontendu Cloud Firestore, który również znajduje się w regionie us-east1
. Te połączenia są długotrwałe i pozostają otwarte, dopóki nie zostaną wyraźnie zamknięte przez aplikację. Interfejs odczytuje dane z bazowych Cloud Firestore systemów pamięci masowej.
Odległość między fizyczną lokalizacją użytkownika a lokalizacją bazy danych Cloud Firestore wpływa na opóźnienie odczuwane przez użytkownika. Na przykład użytkownik w Indiach, którego aplikacja komunikuje się z bazą danych w regionie Google Cloud w Ameryce Północnej, może zauważyć, że aplikacja działa wolniej i mniej płynnie niż w przypadku, gdyby baza danych znajdowała się bliżej, np. w Indiach lub w innej części Azji.
Projektowanie z myślą o niezawodności
Poniższe tematy dotyczą zwiększania lub zmniejszania niezawodności aplikacji:
Włączanie trybu offline
Pakiety SDK Firebase zapewniają trwałość danych offline. Jeśli aplikacja na urządzeniu użytkownika nie może połączyć się z Cloud Firestore, pozostaje dostępna dzięki danym przechowywanym lokalnie w pamięci podręcznej. Zapewnia to dostęp do danych nawet wtedy, gdy użytkownicy mają problemy z połączeniem internetowym lub całkowicie tracą dostęp na kilka godzin lub dni. Więcej informacji o trybie offline znajdziesz w artykule Włączanie danych offline.
Automatyczne ponawianie prób
Pakiety SDK Firebase zajmują się ponawianiem operacji i przywracaniem przerwanych połączeń. Pomaga to uniknąć błędów przejściowych spowodowanych ponownym uruchomieniem serwerów lub problemami z siecią między klientem a bazą danych.
Wybór lokalizacji regionalnych i wieloregionalnych
Wybór między lokalizacjami regionalnymi a wieloregionalnymi wiąże się z kilkoma kompromisami. Główna różnica polega na sposobie replikacji danych. Ma to wpływ na gwarancje dostępności aplikacji. Instancja wieloregionowa zapewnia większą niezawodność obsługi i zwiększa trwałość danych, ale wiąże się z wyższymi kosztami.
Omówienie systemu zapytań w czasie rzeczywistym
Zapytania w czasie rzeczywistym, zwane też odbiornikami zrzutów, umożliwiają aplikacji nasłuchiwanie zmian w bazie danych i otrzymywanie powiadomień o niskim opóźnieniu, gdy tylko dane ulegną zmianie. Aplikacja może uzyskać ten sam wynik, okresowo sprawdzając bazę danych pod kątem aktualizacji, ale często jest to wolniejsze, droższe i wymaga więcej kodu. Przykłady konfigurowania i używania zapytań w czasie rzeczywistym znajdziesz w artykule Otrzymywanie aktualizacji w czasie rzeczywistym. W kolejnych sekcjach znajdziesz szczegółowe informacje o działaniu odbiorników migawek oraz opis sprawdzonych metod skalowania zapytań w czasie rzeczywistym przy zachowaniu wydajności.
Wyobraź sobie 2 użytkowników, którzy łączą się z Cloud Firestore za pomocą aplikacji do przesyłania wiadomości utworzonej przy użyciu jednego z pakietów SDK na urządzenia mobilne.
Klient A zapisuje w bazie danych dokumenty, aby dodać i zaktualizować dokumenty w kolekcji o nazwie chatroom
:
collection chatroom:
document message1:
from: 'Sparky'
message: 'Welcome to Cloud Firestore!'
document message2:
from: 'Santa'
message: 'Presents are coming'
Klient B nasłuchuje aktualizacji w tej samej kolekcji za pomocą narzędzia do nasłuchiwania migawek. Klient B otrzymuje natychmiastowe powiadomienie za każdym razem, gdy ktoś utworzy nową wiadomość. Ten diagram przedstawia architekturę narzędzia do nasłuchiwania migawek:
Gdy klient B połączy z bazą danych odbiornik migawki, nastąpi ta sekwencja zdarzeń:
- Klient B otwiera połączenie z Cloud Firestore i rejestruje odbiorcę, wywołując
onSnapshot(collection("chatroom"))
za pomocą pakietu Firebase SDK. Może on pozostawać aktywny przez wiele godzin. - Cloud Firestore frontend wysyła zapytania do bazowego systemu pamięci masowej, aby zainicjować zbiór danych. Wczytuje cały zbiór wyników pasujących dokumentów. Nazywamy to zapytaniem o stan. Następnie system sprawdza reguły zabezpieczeń Firebase bazy danych, aby potwierdzić, że użytkownik ma dostęp do tych danych. Jeśli użytkownik jest autoryzowany, baza danych zwraca mu dane.
- Zapytanie klienta B przechodzi następnie w tryb nasłuchiwania. Odbiornik rejestruje się w programie obsługi subskrypcji i czeka na aktualizacje danych.
- Klient A wysyła teraz operację zapisu, aby zmodyfikować dokument.
- Baza danych zapisuje zmianę dokumentu w systemie pamięci masowej.
- System zatwierdza tę samą aktualizację w wewnętrznym dzienniku zmian. Dziennik zmian ustala ścisłą kolejność zmian w miarę ich wprowadzania.
- Dziennik zmian z kolei przekazuje zaktualizowane dane do puli modułów obsługi subskrypcji.
- Uruchamia się wyszukiwarka zapytań odwrotnych, aby sprawdzić, czy zaktualizowany dokument pasuje do jakichkolwiek aktualnie zarejestrowanych detektorów migawek. W tym przykładzie dokument pasuje do odbiornika migawek klienta B. Jak sama nazwa wskazuje, dopasowywanie zapytań odwrotnych można traktować jako zwykłe zapytanie do bazy danych, ale wykonywane w odwrotnej kolejności. Zamiast przeszukiwać dokumenty w poszukiwaniu tych, które pasują do zapytania, skutecznie przeszukuje zapytania w poszukiwaniu tych, które pasują do przychodzącego dokumentu. Gdy system znajdzie dopasowanie, przekaże dokument do odbiorców zrzutu. Następnie system sprawdza reguły zabezpieczeń Firebase bazy danych, aby upewnić się, że dane otrzymują tylko autoryzowani użytkownicy.
- System przekazuje aktualizację dokumentu do pakietu SDK na urządzeniu klienta B, a następnie wywoływana jest funkcja zwrotna
onSnapshot
. Jeśli lokalne utrwalanie jest włączone, pakiet SDK zastosuje aktualizację również w pamięci podręcznej.
Kluczowym elementem skalowalności Cloud Firestore jest rozsyłanie informacji z dziennika zmian do modułów obsługi subskrypcji i serwerów frontendu. Rozsyłanie umożliwia wydajne propagowanie pojedynczej zmiany danych w celu obsługi milionów zapytań w czasie rzeczywistym i połączonych użytkowników. Dzięki uruchamianiu wielu replik wszystkich tych komponentów w wielu strefach (lub w wielu regionach w przypadku wdrożenia w wielu regionach) Cloud Firestore osiąga wysoką dostępność i skalowalność.
Warto zauważyć, że wszystkie operacje odczytu wykonywane z pakietów SDK na urządzenia mobilne i do internetu są zgodne z powyższym modelem. W celu zachowania gwarancji spójności wykonują zapytanie o stan, a następnie przechodzą w tryb nasłuchiwania. Dotyczy to również detektorów w czasie rzeczywistym, wywołań służących do pobierania dokumentów i zapytań jednorazowych. Pobieranie pojedynczych dokumentów i zapytania jednorazowe można traktować jako krótkotrwałe odbiorniki zrzutów, które mają podobne ograniczenia dotyczące wydajności.
Stosuj sprawdzone metody skalowania zapytań w czasie rzeczywistym
Aby projektować skalowalne zapytania w czasie rzeczywistym, stosuj te sprawdzone metody.
Analizowanie dużego ruchu zapisu w systemie
Z tej sekcji dowiesz się, jak system reaguje na rosnącą liczbę żądań zapisu.
Cloud FirestoreDzienniki zmian, które obsługują zapytania w czasie rzeczywistym,Cloud Firestore automatycznie skalują się w poziomie wraz ze wzrostem ruchu związanego z zapisem. Gdy szybkość zapisu w bazie danych przekroczy możliwości jednego serwera, dziennik zmian zostanie podzielony na kilka serwerów, a przetwarzanie zapytań zacznie korzystać z danych z kilku modułów obsługi subskrypcji zamiast z jednego. Z perspektywy klienta i pakietu SDK jest to w pełni przejrzyste i nie wymaga żadnych działań ze strony aplikacji w przypadku podziału. Ten diagram pokazuje, jak skalują się zapytania w czasie rzeczywistym:
Automatyczne skalowanie umożliwia zwiększanie ruchu związanego z zapisem bez ograniczeń, ale w miarę wzrostu ruchu system może potrzebować trochę czasu na reakcję. Aby uniknąć tworzenia hotspotu zapisu, postępuj zgodnie z zaleceniami reguły 5-5-5. Key Visualizer to przydatne narzędzie do analizowania punktów zapisu.
Wiele aplikacji ma przewidywalny wzrost liczby bezpłatnych instalacji, który Cloud Firestore może uwzględnić bez podejmowania środków ostrożności. Zadania wsadowe, takie jak importowanie dużego zbioru danych, mogą jednak zbyt szybko zwiększać liczbę zapisów. Podczas projektowania aplikacji pamiętaj, skąd pochodzi ruch związany z zapisem.
Jak interakcje zapisu i odczytu wpływają na siebie
System zapytań w czasie rzeczywistym możesz traktować jako potok łączący operacje zapisu z czytelnikami. Za każdym razem, gdy dokument zostanie utworzony, zaktualizowany lub usunięty, zmiana jest propagowana z systemu pamięci masowej do aktualnie zarejestrowanych odbiorców. Struktura dziennika zmian Cloud Firestore gwarantuje silną spójność, co oznacza, że aplikacja nigdy nie otrzymuje powiadomień o aktualizacjach, które są nieuporządkowane w porównaniu z momentem, w którym baza danych zatwierdziła zmiany danych. Upraszcza to tworzenie aplikacji, ponieważ eliminuje przypadki brzegowe związane ze spójnością danych.
Ten połączony potok oznacza, że operacja zapisu powodująca hotspoty lub rywalizację o blokady może negatywnie wpływać na operacje odczytu. Gdy operacje zapisu nie powiodą się lub zostaną ograniczone, odczyt może się zatrzymać w oczekiwaniu na spójne dane z dziennika zmian. Jeśli taka sytuacja wystąpi w Twojej aplikacji, możesz zauważyć zarówno powolne operacje zapisu, jak i powiązane z nimi powolne czasy odpowiedzi na zapytania. Unikanie hotspotów to klucz do uniknięcia tego problemu.
Zadbaj o to, aby dokumenty i operacje zapisu były małe
Podczas tworzenia aplikacji z użyciem detektorów migawek zwykle chcesz, aby użytkownicy szybko dowiadywali się o zmianach danych. Aby to osiągnąć, staraj się, aby były jak najmniejsze. System może bardzo szybko przetwarzać małe dokumenty z dziesiątkami pól. Przetwarzanie większych dokumentów z setkami pól i dużą ilością danych trwa dłużej.
Podobnie preferuj krótkie i szybkie operacje zatwierdzania i zapisu, aby utrzymać niskie opóźnienie. Duże partie mogą zwiększyć przepustowość z perspektywy modułu zapisującego, ale mogą też wydłużyć czas powiadamiania odbiorców migawek. W porównaniu z innymi systemami baz danych, w których do poprawy wydajności można używać przetwarzania wsadowego, jest to często sprzeczne z intuicją.
Używaj wydajnych detektorów
Wraz ze wzrostem szybkości zapisu w bazie danych usługa Cloud Firestore rozdziela przetwarzanie danych na wiele serwerów. Cloud FirestoreAlgorytm dzielenia na partycje próbuje umieścić dane z tej samej kolekcji lub grupy kolekcji na tym samym serwerze dziennika zmian. System stara się zmaksymalizować możliwą przepustowość zapisu, przy jednoczesnym utrzymaniu jak najmniejszej liczby serwerów zaangażowanych w przetwarzanie zapytania.
Niektóre wzorce mogą jednak nadal prowadzić do nieoptymalnego działania w przypadku słuchaczy migawek. Jeśli na przykład aplikacja przechowuje większość danych w jednej dużej kolekcji, odbiornik może potrzebować połączenia z wieloma serwerami, aby otrzymać wszystkie potrzebne dane. Dzieje się tak nawet wtedy, gdy zastosujesz filtr zapytania. Połączenie z wieloma serwerami zwiększa ryzyko wolniejszych odpowiedzi.
Aby uniknąć wolniejszych odpowiedzi, zaprojektuj schemat i aplikację tak, aby system mógł obsługiwać odbiorców bez konieczności przechodzenia do wielu różnych serwerów. Najlepiej podzielić dane na mniejsze kolekcje o mniejszej częstotliwości zapisu.
Można to porównać do zapytań dotyczących wydajności w relacyjnej bazie danych, które wymagają pełnego skanowania tabeli. W relacyjnej bazie danych zapytanie wymagające skanowania całej tabeli jest odpowiednikiem odbiornika migawek, który monitoruje kolekcję o dużej liczbie zmian. Może działać wolniej niż zapytanie, które baza danych może obsłużyć za pomocą bardziej szczegółowego indeksu. Zapytanie z bardziej szczegółowym indeksem jest podobne do detektora zrzutu, który obserwuje pojedynczy dokument lub kolekcję, która zmienia się rzadziej. Aby jak najlepiej poznać zachowanie i potrzeby w swoim przypadku użycia, przeprowadź test obciążeniowy aplikacji.
Szybkie zapytania odpytujące
Kolejnym kluczowym elementem zapytań w czasie rzeczywistym jest zapewnienie, że zapytanie o dane początkowe jest szybkie i wydajne. Gdy nowy odbiornik migawki po raz pierwszy nawiązuje połączenie, musi wczytać cały zestaw wyników i wysłać go na urządzenie użytkownika. Powolne zapytania sprawiają, że aplikacja działa mniej responsywnie. Obejmuje to na przykład zapytania, które próbują odczytać wiele dokumentów, lub zapytania, które nie używają odpowiednich indeksów.
W pewnych okolicznościach odbiorca może też wrócić ze stanu nasłuchiwania do stanu odpytywania. Dzieje się to automatycznie i jest niewidoczne dla pakietów SDK i Twojej aplikacji. Stan odpytywania może być wywoływany przez te warunki:
- System ponownie równoważy dziennik zmian z powodu zmian obciążenia.
- Hotspoty powodują nieudane lub opóźnione zapisy w bazie danych.
- Przejściowe ponowne uruchomienia serwera tymczasowo wpływają na słuchaczy.
Jeśli zapytania o stan są wystarczająco szybkie, stan ten staje się niewidoczny dla użytkowników aplikacji.
Preferowanie detektorów o długim czasie życia
Otwieranie i utrzymywanie aktywności odbiorników tak długo, jak to możliwe, jest często najbardziej opłacalnym sposobem tworzenia aplikacji korzystającej z Cloud Firestore. Gdy korzystasz z usługi Cloud Firestore, płacisz za dokumenty zwrócone do aplikacji, a nie za utrzymywanie otwartego połączenia. Detektor zrzutu o długim czasie życia odczytuje tylko dane potrzebne do obsługi zapytania przez cały okres jego istnienia. Obejmuje to początkowe odpytywanie, a następnie powiadomienia, gdy dane faktycznie się zmienią. Zapytania jednorazowe ponownie odczytują dane, które mogły nie ulec zmianie od czasu ostatniego uruchomienia zapytania przez aplikację.
W sytuacjach, w których aplikacja musi przetwarzać duże ilości danych, odbiorniki migawek mogą nie być odpowiednie. Jeśli na przykład Twój przypadek użycia wymaga przesyłania wielu dokumentów na sekundę przez połączenie przez dłuższy czas, lepiej jest używać jednorazowych zapytań uruchamianych z mniejszą częstotliwością.
Co dalej
- Dowiedz się, jak korzystać z funkcji nasłuchiwania stanu.
- Dowiedz się więcej o sprawdzonych metodach.