Z tego dokumentu dowiesz się, jak w przypadku niepowodzenia żądać ponownego wykonania asynchronicznych funkcji działających w tle (nieużywających protokołu HTTPS).
Dlaczego funkcje reagujące na zdarzenia nie mogą się zakończyć
W rzadkich przypadkach funkcja może zostać przedwcześnie zakończona z powodu błędu wewnętrznego. Domyślnie funkcja może być automatycznie ponawiana lub nie.
Zwykle jednak funkcja wywoływana przez zdarzenie może nie zostać wykonana z powodu błędów w jej kodzie. Może to wynikać z tych przyczyn:
- Funkcja zawiera błąd, a środowisko wykonawcze zgłasza wyjątek.
- Funkcja nie może połączyć się z punktem końcowym usługi lub upłynął limit czasu podczas próby połączenia.
- Funkcja celowo zgłasza wyjątek (np. gdy weryfikacja parametru zakończy się niepowodzeniem).
- Funkcja Node.js zwraca odrzuconą obietnicę lub przekazuje do wywołania zwrotnego wartość inną niż
null
.
W każdym z powyższych przypadków funkcja przestanie działać i zwróci błąd. Wywołania zdarzeń generujące wiadomości mają zasady ponawiania, które możesz dostosować do potrzeb swojej funkcji.
Semantyka ponawiania
Cloud Functions zapewnia co najmniej jednokrotne wykonanie funkcji opartej na zdarzeniach w przypadku każdego zdarzenia wyemitowanego przez źródło zdarzeń. Sposób konfiguracji ponownych prób zależy od tego, jak została utworzona funkcja:
- Funkcje utworzone w konsoli Google Cloud lub za pomocą Cloud Runinterfejsu Admin API wymagają oddzielnego tworzenia i zarządzania wyzwalaczami zdarzeń. Wywołania mają domyślne zachowania ponawiania, które możesz dostosować do potrzeb funkcji.
- Funkcje utworzone za pomocą Cloud Functions API w wersji 2 będą niejawnie tworzyć niezbędne aktywatory zdarzeń, np. tematy Pub/Sub lub aktywatory Eventarc. Domyślnie ponawianie prób jest wyłączone w przypadku tych aktywatorów. Można je ponownie włączyć za pomocą interfejsu Cloud Functions API w wersji 2.
Funkcje sterowane zdarzeniami utworzone za pomocą Cloud Run
Funkcje utworzone w konsoli Google Cloud lub za pomocą interfejsu Cloud RunAdmin API wymagają oddzielnego tworzenia i zarządzania wyzwalaczami zdarzeń. Zdecydowanie zalecamy zapoznanie się z domyślnym działaniem każdego typu wyzwalacza:
- Eventarc zasady ponawiania mają domyślny okres przechowywania wiadomości wynoszący 24 godziny ze wzrastającym czasem do ponowienia. Więcej informacji znajdziesz w Eventarcdokumentacji dotyczącej zdarzeń ponawiania.
- Domyślnie w przypadku wszystkich subskrypcji używana jest zasada natychmiastowego ponownego dostarczenia.Pub/Sub Zapoznaj się z Pub/Sub dokumentacją na temat obsługi błędów wiadomości i ponawiania próśb.
Funkcje oparte na zdarzeniach utworzone za pomocą interfejsu Cloud Functions API w wersji 2
Funkcje utworzone za pomocą Cloud Functions API w wersji 2, na przykład za pomocą Cloud Functions gcloud CLI, interfejsu REST API lub Terraform, będą tworzyć aktywatory zdarzeń i zarządzać nimi w Twoim imieniu. 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 ponawianie w funkcji opartej na zdarzeniach, Cloud Functionsponawia ona nieudaną próbę wywołania funkcji, dopóki nie zostanie ona zakończonaCloud Functionspomyślnie lub nie upłynie okres ponawiania.
Jeśli ponawianie nie jest włączone w przypadku funkcji (jest to ustawienie domyślne), funkcja zawsze zgłasza, że została wykonana prawidłowo, a w jej dziennikach mogą się pojawiać kody odpowiedzi 200 OK
. Dzieje się tak nawet wtedy, gdy funkcja napotka błąd. Aby było jasne, kiedy funkcja napotka błąd, pamiętaj o odpowiednim zgłaszaniu błędów.
Włączanie i wyłączanie ponownych prób
Konfigurowanie ponownych prób w kodzie funkcji
Za pomocą Cloud Functions for Firebase możesz włączyć ponawianie w kodzie funkcji. Aby to zrobić w przypadku funkcji w tle, takiej jak functions.foo.onBar(myHandler);
, użyj kodu runWith
i skonfiguruj zasady dotyczące błędów:
functions.runWith({failurePolicy: true}).foo.onBar(myHandler);
Ustawienie true
jak w przykładzie powoduje, że funkcja ponawia działanie w przypadku błędu.
Okres ponownej próby
W przypadku funkcji 2 generacji ten okres ponawiania prób wygasa po 24 godzinach. W przypadku funkcji 1 generacji wygasa po 7 dniach. Cloud Functions ponawia wywołanie nowo utworzonych funkcji opartych na zdarzeniach, stosując strategię wzrastającego czasu do ponowienia z coraz dłuższym czasem oczekiwania, który wynosi od 10 do 600 sekund. Te zasady są stosowane do nowych funkcji podczas pierwszego wdrożenia. Nie jest ona stosowana wstecznie do istniejących funkcji, które zostały wdrożone po raz pierwszy przed wejściem w życie zmian opisanych w tych informacjach o wersji, nawet jeśli ponownie wdrożysz te funkcje.Sprawdzone metody
W tej sekcji opisujemy sprawdzone metody korzystania z ponownych prób.
Używanie ponawiania do obsługi błędów przejściowych
Funkcja jest ponawiana do momentu pomyślnego wykonania, dlatego przed włączeniem ponawiania prób należy wyeliminować z kodu trwałe błędy, takie jak błędy w kodzie, przeprowadzając testy. Ponawianie najlepiej sprawdza się w przypadku sporadycznych lub przejściowych błędów, które z dużym prawdopodobieństwem zostaną rozwiązane po ponowieniu próby, np. w przypadku niestabilnego punktu końcowego usługi lub przekroczenia limitu czasu.
Ustaw warunek zakończenia, aby uniknąć nieskończonych pętli ponawiania
Podczas korzystania z ponownych prób warto zabezpieczyć funkcję przed ciągłym zapętleniem. Możesz to zrobić, uwzględniając dobrze zdefiniowany warunek zakończenia przed rozpoczęciem przetwarzania przez funkcję. Pamiętaj, że ta technika działa tylko wtedy, gdy funkcja zostanie uruchomiona i będzie w stanie ocenić warunek zakończenia.
Prostym, ale skutecznym podejściem jest odrzucanie zdarzeń ze znacznikami czasu starszymi niż określony czas. Pomaga to uniknąć nadmiernej liczby wykonań, gdy błędy są trwałe lub trwają dłużej niż oczekiwano.
Na przykład 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
z obiektami Promise
Jeśli funkcja ma włączone ponawianie, każdy nieobsłużony błąd spowoduje ponowienie próby. Upewnij się, że kod wychwytuje błędy, które nie powinny powodować ponownej próby.
Oto przykład, co należy zrobić:
return doFooAsync().catch((err) => {
if (isFatal(err)) {
console.error(`Fatal error ${err}`);
}
return Promise.reject(err);
});
Zapewnianie idempotentności funkcji reagujących na zdarzenia, które można ponawiać
Funkcje reagujące na zdarzenia, które można ponownie uruchomić, muszą być idempotentne. Oto kilka ogólnych wskazówek dotyczących tworzenia funkcji idempotentnych:
- 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 użyj identyfikatora zdarzenia.
- Idempotentność dobrze współpracuje z dostarczaniem co najmniej raz, ponieważ umożliwia bezpieczne ponawianie prób. Dlatego ogólną sprawdzoną metodą pisania niezawodnego kodu jest łączenie idempotentności z ponawianiem.
- Upewnij się, że Twój kod jest wewnętrznie idempotentny. Na przykład:
- Upewnij się, że mutacje mogą wystąpić więcej niż raz bez zmiany wyniku.
- Wykonywanie zapytań o stan bazy danych w transakcji przed zmianą stanu.
- Upewnij się, że wszystkie efekty uboczne są idempotentne.
- Wprowadź kontrolę transakcyjną poza funkcją, niezależnie od kodu. Możesz na przykład zapisać stan w miejscu, w którym odnotowujesz, że dany identyfikator zdarzenia został już przetworzony.
- Obsługuj zduplikowane wywołania funkcji poza pasmem. Możesz na przykład mieć osobny proces czyszczenia, który usuwa duplikaty wywołań funkcji.
Konfigurowanie zasady ponawiania
W zależności od potrzeb funkcji możesz skonfigurować bezpośrednio zasady ponawiania. Dzięki temu możesz skonfigurować dowolną kombinację tych opcji:
- Skróć okno ponawiania z 7 dni do zaledwie 10 minut.
- Zmień minimalny i maksymalny czas oczekiwania w przypadku strategii ponawiania z wykładniczym czasem oczekiwania.
- Zmień strategię ponawiania na natychmiastowe ponawianie.
- Skonfiguruj temat niedostarczonych komunikatów.
- Ustaw maksymalną i minimalną liczbę prób dostarczenia.
Aby skonfigurować zasady ponawiania:
- Napisz funkcję HTTP.
- Użyj interfejsu Pub/Sub API, aby utworzyć subskrypcję Pub/Sub, podając adres URL funkcji jako miejsce docelowe.
Więcej informacji o bezpośrednim konfigurowaniu Pub/Sub znajdziesz w dokumentacji Pub/Sub dotyczącej obsługi błędów.