Ponów próbę użycia funkcji asynchronicznych

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 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.
  • Podczas próby wykonania funkcji funkcja nie może połączyć się z punktem końcowym usługi lub przekroczono limit czasu.
  • 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 wystąpienia błędu, możesz zmienić domyślną zasadę ponawiania, ustawiając właściwość „Ponów próbę w przypadku niepowodzenia”. 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ę:

  1. Na ekranie Utwórz funkcję w sekcji Reguła wybierz typ zdarzenia, które będzie działać jako reguła dla funkcji.
  2. Zaznacz pole wyboru Ponów próbę w przypadku niepowodzenia, aby włączyć ponowne próby.

Jeśli aktualizujesz istniejącą funkcję:

  1. Na stronie Cloud Functions Przegląd kliknij nazwę funkcji, którą chcesz zaktualizować, aby otworzyć ekran Szczegóły funkcji, a następnie kliknij Edytuj z paska menu, aby wyświetlić panel Aktywator.
  2. 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 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 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. Powtórzenia 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 limit 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 końcowy, zanim funkcja rozpocznie przetwarzanie. Pamiętaj, że ta metoda działa tylko wtedy, gdy funkcja uruchamia się prawidłowo i może ocenić warunek końcowy.

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);
});

Ustaw jako idempotentne funkcje oparte na zdarzeniach z możliwością ponowienia

Funkcje oparte na zdarzeniach, które można powtarzać, 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 użyj 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. 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 przerwy.
  • Zmień strategię ponawiania prób, aby natychmiast spróbować ponownie.
  • Skonfiguruj temat niedostarczonych komunikatów.
  • Ustaw maksymalną i minimalną liczbę prób dostarczenia.

Aby skonfigurować zasadę ponawiania:

  1. napisać funkcję HTTP,
  2. Użyj interfejsu API Pub/Sub, aby utworzyć subskrypcję Pub/Sub, podając jako docelowe adres URL funkcji.

Więcej informacji na temat bezpośredniego konfigurowania usługi Pub/Sub znajdziesz w dokumentacji Pub/Sub dotyczącej obsługi błędów.