Wiederholen Sie asynchrone Funktionen

In diesem Dokument wird beschrieben, wie Sie asynchrone Hintergrundfunktionen (nicht HTTPS) anfordern können, um bei einem Fehler einen erneuten Versuch zu unternehmen.

Semantik der Wiederholung

Cloud Functions garantiert die mindestens einmalige Ausführung einer ereignisgesteuerten Funktion für jedes von einer Ereignisquelle ausgegebene Ereignis. Wenn jedoch ein Funktionsaufruf mit einem Fehler beendet wird, wird die Funktion standardmäßig nicht erneut aufgerufen und das Ereignis wird verworfen. Wenn Sie Wiederholungen für eine ereignisgesteuerte Funktion aktivieren, wiederholt Cloud Functions einen fehlgeschlagenen Funktionsaufruf, bis er erfolgreich abgeschlossen wird oder das Wiederholungsfenster (standardmäßig 7 Tage) abläuft.

Warum ereignisgesteuerte Funktionen nicht abgeschlossen werden

In seltenen Fällen kann eine Funktion aufgrund eines internen Fehlers vorzeitig beendet werden, und standardmäßig kann die Funktion automatisch wiederholt werden oder nicht.

Typischerweise kann eine ereignisgesteuerte Funktion aufgrund von Fehlern im Funktionscode selbst nicht erfolgreich abgeschlossen werden. Einige der Gründe, warum dies passieren könnte, sind folgende:

  • Die Funktion enthält einen Fehler und die Laufzeit löst eine Ausnahme aus.
  • Die Funktion kann einen Dienstendpunkt nicht erreichen oder es kommt zu einer Zeitüberschreitung beim Versuch, den Endpunkt zu erreichen.
  • Die Funktion löst absichtlich eine Ausnahme aus (z. B. wenn die Validierung eines Parameters fehlschlägt).
  • Wenn in Node.js geschriebene Funktionen ein abgelehntes Promise zurückgeben oder einen Nicht- null -Wert an einen Callback übergeben.

In jedem der oben genannten Fälle stoppt die Funktion standardmäßig die Ausführung und das Ereignis wird verworfen. Wenn Sie die Funktion wiederholen möchten, wenn ein Fehler auftritt, können Sie die standardmäßige Wiederholungsrichtlinie ändern, indem Sie die Eigenschaft "Wiederholen bei Fehler" festlegen . Dadurch wird das Ereignis bis zu mehreren Tagen wiederholt wiederholt, bis die Funktion erfolgreich abgeschlossen wird.

Aktivieren und Deaktivieren von Wiederholungen

Verwenden der GCP Console

Sie können Wiederholungen in der GCP Console wie folgt aktivieren oder deaktivieren:

  1. Rufen Sie in der Cloud Platform-Konsole die Seite „Cloud Functions-Übersicht“ auf.

  2. Klicken Sie auf Funktion erstellen . Klicken Sie alternativ auf eine vorhandene Funktion, um zu ihrer Detailseite zu gehen, und klicken Sie auf Bearbeiten .

  3. Füllen Sie die erforderlichen Felder für Ihre Funktion aus.

  4. Stellen Sie sicher, dass das Feld Trigger auf einen ereignisbasierten Triggertyp wie Cloud Pub/Sub oder Cloud Storage eingestellt ist.

  5. Erweitern Sie die erweiterten Einstellungen, indem Sie auf Mehr klicken.

  6. Aktivieren oder deaktivieren Sie das Kontrollkästchen Bei Fehler wiederholen .

Im Funktionscode

Mit Cloud Functions for Firebase können Sie Wiederholungen im Code für eine Funktion aktivieren. Um dies für eine Hintergrundfunktion wie beispielsweise functions.foo.onBar(myHandler); , verwenden runWith und konfigurieren Sie eine Fehlerrichtlinie:

functions.runWith({failurePolicy: true}).foo.onBar(myHandler);

Wenn Sie wie gezeigt true festlegen, wird eine Funktion so konfiguriert, dass sie bei einem Fehler erneut versucht.

Empfohlene Vorgehensweise

In diesem Abschnitt werden Best Practices für die Verwendung von Wiederholungen beschrieben.

Verwenden Sie Wiederholung, um vorübergehende Fehler zu behandeln

Da Ihre Funktion bis zur erfolgreichen Ausführung kontinuierlich wiederholt wird, sollten dauerhafte Fehler wie Bugs durch Tests aus Ihrem Code entfernt werden, bevor Sie Wiederholungen aktivieren. Wiederholungen werden am besten verwendet, um zeitweilige/vorübergehende Fehler zu behandeln, die bei Wiederholungsversuchen mit hoher Wahrscheinlichkeit behoben werden, wie z. B. ein fehlerhafter Dienstendpunkt oder eine Zeitüberschreitung.

Legen Sie eine Endbedingung fest, um endlose Wiederholungsschleifen zu vermeiden

Es empfiehlt sich, Ihre Funktion bei der Verwendung von Wiederholungen vor Dauerschleifen zu schützen. Sie können dies tun, indem Sie eine wohldefinierte Endbedingung einfügen, bevor die Funktion mit der Verarbeitung beginnt. Beachten Sie, dass diese Technik nur funktioniert, wenn Ihre Funktion erfolgreich gestartet wird und die Endbedingung auswerten kann.

Ein einfacher, aber effektiver Ansatz besteht darin, Ereignisse mit Zeitstempeln zu verwerfen, die älter als eine bestimmte Zeit sind. Dies trägt dazu bei, übermäßige Ausführungen zu vermeiden, wenn Fehler entweder dauerhaft oder länger andauern als erwartet.

Dieses Code-Snippet verwirft beispielsweise alle Ereignisse, die älter als 10 Sekunden sind:

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

Verwenden Sie catch mit Promises

Wenn für Ihre Funktion Wiederholungen aktiviert sind, löst jeder nicht behandelte Fehler eine Wiederholung aus. Stellen Sie sicher, dass Ihr Code alle Fehler erfasst, die nicht zu einer Wiederholung führen sollten.

Hier ist ein Beispiel dafür, was Sie tun sollten:

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

Machen Sie wiederholbare ereignisgesteuerte Funktionen idempotent

Ereignisgesteuerte Funktionen, die wiederholt werden können, müssen idempotent sein. Hier sind einige allgemeine Richtlinien, um eine solche Funktion idempotent zu machen:

  • Bei vielen externen APIs (z. B. Stripe) können Sie einen Idempotenzschlüssel als Parameter angeben. Wenn Sie eine solche API verwenden, sollten Sie die Ereignis-ID als Idempotenzschlüssel verwenden.
  • Idempotenz funktioniert gut mit der mindestens einmaligen Zustellung, weil es sicher ist, es erneut zu versuchen. Eine allgemeine bewährte Methode zum Schreiben zuverlässigen Codes besteht also darin, Idempotenz mit Wiederholungen zu kombinieren.
  • Stellen Sie sicher, dass Ihr Code intern idempotent ist. Beispielsweise:
    • Stellen Sie sicher, dass Mutationen mehr als einmal auftreten können, ohne das Ergebnis zu ändern.
    • Fragen Sie den Datenbankstatus in einer Transaktion ab, bevor Sie den Status ändern.
    • Stellen Sie sicher, dass alle Nebenwirkungen selbst idempotent sind.
  • Erzwingen Sie eine Transaktionsprüfung außerhalb der Funktion, unabhängig vom Code. Halten Sie beispielsweise irgendwo fest, dass eine bestimmte Ereignis-ID bereits verarbeitet wurde.
  • Behandeln Sie doppelte Funktionsaufrufe out-of-band. Verwenden Sie beispielsweise einen separaten Bereinigungsprozess, der nach doppelten Funktionsaufrufen bereinigt.