Z tego dokumentu dowiesz się, jak możesz poprosić o powtórzenie nieudanej funkcji tlenowej (nie korzystającej z protokołu HTTPS).
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 wywołana ponownie, a zdarzenie zostanie odrzucone. Gdy włączysz powtórzenia w przypadku funkcji wywoływanej przez zdarzenie, Cloud Functions będzie ona powtarzać nieudane wywołanie funkcji, dopóki nie zakończy się ono pomyślnie lub nie upłynie czas oczekiwania na powtórzenie.
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, z coraz dłuższymi przerwami od 10 do 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 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 odrzuconą obietnicę lub przekazuje do funkcji wywołania zwrotnego wartość inną niż
null
.
W każdym z tych przypadków funkcja przestaje się wykonywać, a zdarzenie zostaje odrzucone. Aby ponownie uruchomić funkcję w przypadku błędu, możesz zmienić domyślną zasadę próbowania ponownie, 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 połączenia z poziomu kodu funkcji
Za pomocą funkcji Cloud Functions for Firebase możesz włączyć w kodzie funkcję prób ponownych. Aby to zrobić w przypadku funkcji tła, takiej jak functions.foo.onBar(myHandler);
, użyj funkcji runWith
i skonfiguruj zasady postępowania w przypadku błędu:
functions.runWith({failurePolicy: true}).foo.onBar(myHandler);
Ustawienie true
w taki sposób 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. Ponowne próby są najbardziej przydatne w przypadku sporadycznych lub przejściowych awarii, które mają dużą szansę na rozwiązanie po ponownym próbie, takich jak niestabilny punkt końcowy usługi lub przekroczenie limitu czasu.
Ustaw warunek zakończenia, aby uniknąć nieskończonej pętli prób.
Dobrą praktyką jest ochrona funkcji przed ciągłym pętlą podczas prób ponownego wykonania. 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. Upewnij się, że Twój kod rejestruje wszystkie błędy, które nie powinny powodować ponownego 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 tworzenia idempotentnych funkcji:
- 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.
- Idempotency works well with at-least-once delivery, because it makes it safe to retry. 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 jego zmianą.
- 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 fakt, że dany identyfikator zdarzenia został już przetworzony.
- Rozwiązywanie problemu z duplikatami wywołań funkcji poza pasmem. Możesz na przykład utworzyć osobny proces czyszczenia, który będzie działał po wywołaniu duplikatów funkcji.
Konfigurowanie 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 przerwy w przypadku strategii ponownego próbowania z wzrostem wartości w eksponencjalnie rosnącej sekwencji.
- Zmień strategię powtarzania na „ponów 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.