Z tego dokumentu dowiesz się, jak w przypadku niepowodzenia ponawiać próby w przypadku asynchronicznych (innych niż HTTPS) funkcji w tle.
Semantyka ponownej próby
Cloud Functions zapewnia co najmniej jednokrotne wykonanie funkcji sterowanej zdarzeniami w przypadku każdego zdarzenia wyemitowanego przez źródło zdarzeń. Domyślnie, jeśli wywołanie funkcji zakończy się błędem, funkcja nie zostanie ponownie wywołana, a zdarzenie zostanie usunięte. Gdy włączysz powtórzenia funkcji wywoływanej przez zdarzenie, Cloud Functions powtórzy ona nieudane wywołanie funkcji, aż do momentu jej pomyślnego zakończenia lub wygaśnięcia okna powtórzeń.
W przypadku funkcji 2 generacji to okno próby ponownego wykonania kończy się po 24 godzinach. W przypadku funkcji 1 generacji wygasa ona po 7 dniach. Cloud Functions powtarza nowo utworzone funkcje wywoływane przez zdarzenia, stosując strategię wzrastającego czasu do ponowienia, w ramach 10–600 sekund. Ta zasada jest stosowana do nowych funkcji podczas ich pierwszego wdrożenia. Nie ma ona zastosowania do istniejących funkcji, które zostały wdrożone przed wprowadzeniem zmian opisanych w tych informacjach o wersji, nawet jeśli funkcje te zostaną ponownie wdrożone.Jeśli w przypadku funkcji nie są włączone ponowne próby (co jest domyślnym ustawieniem), funkcja zawsze raportuje, że została wykonana pomyślnie, a w jej dziennikach mogą się pojawić kody odpowiedzi 200 OK
. Dzieje się tak nawet wtedy, gdy funkcja napotkała błąd. Aby wyraźnie określić, kiedy funkcja napotka błąd, odpowiednio zgłaszaj błędy.
Dlaczego funkcje reagujące na zdarzenia nie są wykonywane
W rzadkich przypadkach funkcja może zostać przerwana z powodu błędu wewnętrznego. Domyślnie funkcja może lub nie może zostać automatycznie wykonana ponownie.
Zwykle funkcja wywoływana przez zdarzenie może się nie uruchomić z powodu błędów w jej kodzie. Oto możliwe przyczyny:
- Funkcja zawiera błąd, a czas wykonywania zgłasza wyjątek.
- Funkcja nie może dotrzeć do punktu końcowego usługi lub upłynie limit czasu podczas próby wykonania tej operacji.
- Funkcja celowo zgłasza wyjątek (na przykład, gdy parametr nie przechodzi walidacji).
- Funkcja Node.js zwraca odrzucone obietnice lub przekazuje do funkcji wywołującej wartość inną niż
null
.
W każdym z tych przypadków domyślnie funkcja przestaje wykonywać, a zdarzenie jest odrzucane. Aby ponownie uruchomić funkcję w przypadku błędu, możesz zmienić domyślną zasadę prób ponownego połączenia, ustawiając właściwość „powtórz próbę w przypadku błędu”. Spowoduje to wielokrotne powtarzanie próby wykonania zdarzenia, aż funkcja zostanie uruchomiona pomyślnie lub upłynie limit czasu ponownego próby.
Włączanie i wyłączanie prób ponownych.
Konfigurowanie prób ponownego połączenia w konsoli
Jeśli tworzysz nową funkcję:
- Na ekranie Utwórz funkcję w sekcji Reguła wybierz typ zdarzenia, które będzie działać jako reguła dla funkcji.
- Zaznacz pole wyboru Ponów próbę w przypadku niepowodzenia, aby włączyć ponowne próby.
Jeśli aktualizujesz istniejącą funkcję:
- Na stronie Cloud Functions Przegląd kliknij nazwę funkcji, którą aktualizujesz, aby otworzyć ekran Szczegóły funkcji. Następnie na pasku menu kliknij Edytuj, aby wyświetlić panel Wyzwalacz.
- Zaznacz lub odznacz pole wyboru Ponów próbę w przypadku niepowodzenia, aby włączyć lub wyłączyć ponowne próby.
Konfigurowanie prób ponownego wykonania z kodu funkcji
Za pomocą funkcji Cloud Functions for Firebase możesz włączyć w kodzie funkcję ponownych prób. Aby to zrobić w przypadku funkcji w tle, takiej jak functions.foo.onBar(myHandler);
, użyj polecenia runWith
i skonfiguruj zasadę błędu:
functions.runWith({failurePolicy: true}).foo.onBar(myHandler);
Ustawienie true
w sposób pokazany na ilustracji powoduje, że funkcja będzie ponownie próbować wykonać działanie w przypadku błędu.
Sprawdzone metody
W tej sekcji znajdziesz sprawdzone metody korzystania z powtórnych prób.
Ponowne próby w przypadku błędów przejściowych
Funkcja jest nieustannie powtarzana, dopóki nie zostanie wykonana pomyślnie, dlatego przed włączeniem prób ponownego wykonania należy wyeliminować z kodu trwałe błędy, takie jak błędy w programie. Ponawianie prób stosuje się w przypadku tymczasowych lub przejściowych awarii, które z dużym prawdopodobieństwem mogą rozwiązać problem przy ponawianiu próby, takich jak niestabilny punkt końcowy usługi lub przekroczenie limitu czasu oczekiwania.
Ustaw warunek zakończenia, aby uniknąć nieskończonej pętli prób.
Sprawdzoną metodą jest ochrona funkcji przed ciągłym zapętlaniem podczas ponownych prób. Możesz to zrobić, dodając dobrze zdefiniowany warunek zakończenia przed rozpoczęciem przetwarzania funkcji. Pamiętaj, że ta metoda działa tylko wtedy, gdy funkcja uruchamia się prawidłowo i może ocenić warunek zakończenia.
Prostym, ale skutecznym podejściem jest odrzucanie zdarzeń z danymi czasowymi starszymi niż określony czas. Pomaga to uniknąć nadmiernego wykonywania, gdy błędy są trwałe lub trwają dłużej niż oczekiwano.
Ten fragment kodu odrzuca wszystkie zdarzenia starsze niż 10 sekund:
const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
callback();
return;
}
Używanie catch
w ramach obietnic
Jeśli w przypadku funkcji włączone jest ponawianie, każda nieprzetworzona obsługa błędu spowoduje ponowne wykonanie funkcji. Sprawdź, czy Twój kod rejestruje wszystkie błędy, które nie powinny powodować ponowienia próby.
Oto przykład tego, co należy zrobić:
return doFooAsync().catch((err) => {
if (isFatal(err)) {
console.error(`Fatal error ${err}`);
}
return Promise.reject(err);
});
uczynić funkcje reagujące na zdarzenia idempotentnymi,
Funkcje reagujące na zdarzenia, które można ponownie uruchomić, muszą być idempotentne. Oto kilka ogólnych wskazówek dotyczących przekształcania funkcji jako idempotentnej:
- Wiele zewnętrznych interfejsów API (np. Stripe) umożliwia podanie klucza idempotentności jako parametru. Jeśli używasz takiego interfejsu API, jako klucza idempotentności należy użyć identyfikatora zdarzenia.
- Idempotencyczność sprawdza się w przypadku dostarczania co najmniej raz, ponieważ umożliwia bezpieczne ponowne próby. Dlatego ogólną sprawdzoną metodą pisania niezawodnego kodu jest połączenie idempotencji z powtórzeniami.
- Upewnij się, że kod jest idempotentny wewnętrznie. Na przykład:
- Upewnij się, że mutacje mogą wystąpić więcej niż raz bez zmiany wyniku.
- Zapytanie stanu bazy danych w ramach transakcji przed zmianą stanu.
- Upewnij się, że wszystkie efekty uboczne są idempotentne.
- Zaimplementuj kontrolę transakcji poza funkcją, niezależnie od kodu. Możesz na przykład zapisać stan, w którym jest zapisany identyfikator zdarzenia, które zostało już przetworzone.
- Rozwiązywanie problemu z duplikowaniem wywołań funkcji poza pasmem. Na przykład masz oddzielny proces czyszczenia, który usuwa dane po zduplikowanych wywołaniach funkcji.
Skonfiguruj zasadę ponawiania
W zależności od potrzeb funkcji możesz skonfigurować bezpośrednio zasady ponownych prób. Dzięki temu możesz skonfigurować dowolną kombinację tych opcji:
- Skrócenie okna prób ponownego połączenia z 7 dni do zaledwie 10 minut.
- Zmień minimalny i maksymalny czas do ponowienia w wykładniczej strategii ponawiania.
- Zmień strategię ponownego próbowania na „Natychmiast”.
- Skonfiguruj temat niedostarczonych komunikatów.
- Ustaw maksymalną i minimalną liczbę prób dostarczenia.
Aby skonfigurować zasadę ponawiania:
- napisać funkcję HTTP,
- Użyj interfejsu API Pub/Sub, aby utworzyć subskrypcję Pub/Sub, podając jako docelowe adres URL funkcji.
Więcej informacji o konfigurowaniu Pub/Sub znajdziesz w dokumentacji Pub/Sub na temat obsługi błędów.