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

Z tego dokumentu dowiesz się, jak w przypadku niepowodzenia ponawiać próby w przypadku asynchronicznych (innych niż HTTPS) funkcji w tle.

Semantyka ponowienia próby

Cloud Functions umożliwia wykonanie funkcji opartej na zdarzeniach co najmniej raz w przypadku każdego zdarzenia generowanego 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 ponawianie prób w funkcji opartej na zdarzeniach, Cloud Functions ponawia próbę wywołania nieudanej funkcji, aż się zakończy lub nie wygaśnie okres ponawiania.

W przypadku funkcji 2 generacji to okno ponawiania kończy się po 24 godzinach. W przypadku funkcji 1 generacji wygasają po 7 dniach. Cloud Functions ponawia próby nowo utworzonych funkcji opartych na zdarzeniach, korzystając ze strategii wykładniczego ponowienia, której czas do ponowienia wzrasta o 10–600 sekund. Ta zasada jest stosowana do nowych funkcji przy pierwszym wdrożeniu. Nie jest stosowana wstecznie do istniejących funkcji, które zostały wdrożone przed wprowadzeniem zmian opisanych w tej informacji o wersji, nawet jeśli ponownie wdrożysz funkcje.

Gdy ponowna próba nie jest włączona w przypadku funkcji, która jest ustawieniem domyślnym, funkcja zawsze informuje, że została wykonana, a w jej logach mogą pojawiać się kody odpowiedzi 200 OK. Dzieje się tak nawet wtedy, gdy funkcja napotkała błąd. Aby jasno określić, kiedy funkcja napotyka błąd, odpowiednio zgłoś błędy.

Dlaczego funkcje oparte na zdarzeniach nie kończą się

W rzadkich przypadkach funkcja może zakończyć się przedwcześnie z powodu błędu wewnętrznego i domyślnie jest ponowiona automatycznie.

Zwykle funkcja sterowana zdarzeniami może nie działać prawidłowo z powodu błędów zgłaszanych w samym kodzie funkcji. Oto kilka możliwych przyczyn:

  • Funkcja zawiera błąd, a środowisko wykonawcze 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 (np. gdy dany parametr nie przejdzie weryfikacji).
  • Funkcja Node.js zwraca odrzuconą obietnicę lub przekazuje do wywołania zwrotnego 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”. Powoduje to, że zdarzenie jest ponawiane wielokrotnie, aż funkcja się zakończy lub nie upłynie czas oczekiwania na ponowną próbę.

Włączanie i wyłączanie ponawiania prób

Konfigurowanie ponownych prób w konsoli

Jeśli tworzysz nową funkcję:

  1. Na ekranie Utwórz funkcję w sekcji Aktywator wybierz typ zdarzenia, które ma aktywować działanie Twojej funkcji.
  2. Zaznacz pole wyboru Ponów próbę w przypadku niepowodzenia, aby włączyć ponawianie prób.

Jeśli aktualizujesz istniejącą funkcję:

  1. Na stronie Przegląd funkcji w Cloud Functions kliknij nazwę funkcji, którą chcesz zaktualizować, aby otworzyć ekran Szczegóły funkcji, a następnie z paska menu wybierz Edytuj, aby wyświetlić panel Aktywator.
  2. Zaznacz lub odznacz pole wyboru Ponów próbę w przypadku niepowodzenia, aby włączyć lub wyłączyć ponawianie prób.

Skonfiguruj ponowne próby na podstawie kodu funkcji

Dzięki Cloud Functions dla Firebase możesz włączyć ponawianie prób w kodzie funkcji. 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 tak jak pokazano, konfiguruje funkcję ponawiania próby w przypadku niepowodzenia.

Sprawdzone metody

W tej sekcji opisano sprawdzone metody korzystania z ponownych prób.

Ponów próbę w celu obsługi błędów przejściowych

Ponieważ funkcja jest ponawiana w sposób ciągły aż do udanego wykonania kodu, przed włączeniem ponownych prób należy wyeliminować z kodu trwałe błędy, takie jak błędy, za pomocą testów. Ponowne próby są używane do radzenia sobie z przejściowymi lub przejściowymi awariami, w przypadku których istnieje duże prawdopodobieństwo rozwiązania problemu przy ponawianiu próby, takich jak niestabilny punkt końcowy usługi lub przekroczenie limitu czasu oczekiwania.

Ustaw warunek końcowy, aby uniknąć nieskończonej pętli ponownych 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 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 sposobem jest odrzucanie zdarzeń z sygnaturami czasowymi starszym niż określony czas. Pomaga to uniknąć nadmiernej liczby wykonań, gdy awarie są trwałe lub trwają dłużej niż powinny.

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żywaj produktu catch w połączeniu z obietnicami

Jeśli w Twojej funkcji włączone są ponawianie prób, każdy nieobsługiwany błąd aktywuje ponawianie. Sprawdź, czy Twój kod rejestruje wszystkie błędy, które nie powinny powodować ponowienia 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);
});

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 przekształcania funkcji jako idempotentnej:

  • Wiele zewnętrznych interfejsów API (np. Stripe) umożliwia dostarczenie klucza idempotentności jako parametru. Jeśli używasz takiego interfejsu API, jako klucza idempotentności użyj identyfikatora zdarzenia.
  • Idempotentność sprawdza się w przypadku co najmniej 1 raza, ponieważ pozwala bezpiecznie ponowić próbę. Sprawdzoną metodą pisania niezawodnego kodu jest więc połączenie idempotentności z ponownymi próbami.
  • 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 rezultatu.
    • Zapytanie o stan bazy danych w transakcji przed zmianą stanu.
    • Upewnij się, że wszystkie efekty uboczne mają charakter idempotentny.
  • Narzucaj kontrolę transakcyjną poza funkcją, niezależnie od kodu. Możesz na przykład zachować stan w miejscu, w którym rejestrowano już, że dany identyfikator zdarzenia został już przetworzony.
  • Radzenie sobie ze zduplikowanymi wywołaniami funkcji poza zakresem. 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 w Cloud Functions możesz skonfigurować zasadę ponawiania próby bezpośrednio. W ten sposób możesz skonfigurować dowolną kombinację tych elementów:

  • Skróć okres ponawiania próby z 7 dni do maksymalnie 10 minut.
  • Zmień minimalny i maksymalny czas do ponowienia w wykładniczej strategii ponawiania.
  • 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 Pub/Sub API, aby utworzyć subskrypcję Pub/Sub, określając adres URL funkcji jako stronę docelową.

Więcej informacji o bezpośrednim konfigurowaniu Pub/Sub znajdziesz w dokumentacji Pub/Sub dotyczącej obsługi błędów.