Self-Hosting

Ein Blick in die Execution-Engine von n8n: So funktioniert der Workflow-Scheduler wirklich

Eine technische Analyse des internen Ausführungsmodells von n8n, einschließlich serialisierbarer Run-Objekte, Scheduling-Logik und Queue-Architektur für selbst gehostete Automatisierungen.

Illustration von Datenfluss durch Workflow-Knoten auf einem Server
Für diesen Artikel erstellte Illustration

Automatisch aus dem englischen Original übersetzt.

n8n hat als selbst gehostete Alternative zu kommerziellen Automatisierungsplattformen erheblich an Bedeutung gewonnen, doch seine internen Mechanismen bleiben für viele Nutzer undurchsichtig. Eine aktuelle technische Analyse zeigt, dass die Plattform auf einem einzigen serialisierbaren Ausführungsobjekt und einer deterministischen Schleife basiert, anstatt auf komplexem Thread-Management. Das Verständnis dieser Architektur hilft Ingenieuren dabei, Workflows effektiv zu debuggen und Deployments zu skalieren.

Was passiert ist

Der Artikel bietet eine tiefgehende Einblicke in den Kern-Engine von n8n, insbesondere unter Untersuchung der in TypeScript geschriebenen Klasse WorkflowExecute. Er erklärt, dass das System beim Auslösen eines Workflows durch einen Benutzer keine individuellen Threads für jeden Knoten startet. Stattdessen wird ein umfassendes Zustandsobjekt namens IRunExecutionData konstruiert. Dieses Objekt enthält den gesamten Kontext des Laufs, einschließlich des Stacks der zur Ausführung wartenden Knoten, einer Map zur Handhabung von Multi-Input-Joins sowie der historischen Ergebnisse abgeschlossener Schritte.

Dieses Zustandsobjekt ist so konzipiert, dass es portabel ist. Es wandert von der Editor-Oberfläche zum Server und potenziell in eine Redis-Queue für Worker-Prozesse. Die Engine verarbeitet dieses Objekt in einer Schleife, indem sie Knoten vom Ausführungsstack verschiebt, ausführt, deren Ausgabe aufzeichnet und alle nachgelagerten Abhängigkeiten in die Warteschlange stellt. Dieser lineare Ansatz vereinfacht das mentale Modell für Entwickler, da er die Notwendigkeit eliminiert, über versteckte Thread-Pools oder asynchrone Race Conditions innerhalb des Graphen nachzudenken.

Wichtige Details

  • Serialisierbarer Zustand: Das Objekt IRunExecutionData trägt den gesamten Laufzeit-Zustand, wodurch Ausführungen pausiert, fortgesetzt oder zwischen Prozessen verschoben werden können, ohne den Kontext zu verlieren.
  • Einstellungen zur Ausführungsreihenfolge: Benutzer können zwischen v0 (Breitensuche) und v1 (Tiefensuche) Scheduling wählen. Dies bestimmt, ob die Engine priorisiert, alle Geschwisterknoten auf einer Ebene abzuschließen, oder einen einzelnen Zweig bis zur Vollendung zu verfolgen.
  • Wartende Map für Joins: Knoten mit mehreren Eingaben führen ihre Aktion erst aus, wenn alle erforderlichen Upstream-Daten verfügbar sind. Teilweise Daten werden in einer Wartenden Map geparkt, bis jeder notwendige Slot gefüllt ist.
  • Zweigbeendigung: Wenn ein Knoten leere Daten zurückgibt, stoppt der nachgelagerte Zweig, es sei denn, das Flag alwaysOutputData ist gesetzt. Dies zwingt die Engine dazu, ein leeres Element zu generieren, um den Fluss am Leben zu erhalten.
  • Architektur im Queue-Modus: In Produktionsumgebungen übernimmt der Hauptprozess UI und Webhooks, während zustandslose Worker Jobs aus Redis abrufen, dieselbe Engine-Schleife ausführen und die Ergebnisse in PostgreSQL schreiben.
  • Fair-Code-Lizenz: n8n nutzt die Sustainable Use License, die kostenlose interne Geschäftsnutzung und Modifikation erlaubt, aber den Weiterverkauf als konkurrierendes gehostetes SaaS-Produkt untersagt.

Hintergrund

Um das Design von n8n zu verstehen, hilft es, zwischen Graph-Traversierung und Task-Scheduling zu unterscheiden. Viele visuelle Automatisierungstools abstrahieren die Reihenfolge der Operationen, was zu unvorhersehbarem Verhalten führt, wenn Zweige zusammengeführt oder geteilt werden. n8n legt diese Logik durch seine Einstellungen zur Ausführungsreihenfolge offen. Breitensuche-Ausführung stellt sicher, dass alle parallelen Aufgaben in einer gegebenen Tiefe abgeschlossen sind, bevor tiefer gegangen wird, was für Batch-Verarbeitung nützlich ist. Tiefensuche-Ausführung folgt einem Pfad vollständig, bevor sie zurückverfolgt, was den Speicherverbrauch bei langen Ketten reduzieren kann.

Das Konzept des "Fair-Code" ist ebenfalls zentral für die Adoption von n8n. Im Gegensatz zu reinen Open-Source-Lizenzen erlaubt Fair-Code Unternehmen, die Software frei für ihre eigenen internen Abläufe zu nutzen und zu modifizieren. Es schränkt jedoch Entitäten ein, die Software als Managed Service für Dritte anzubieten. Dieses Modell unterstützt eine lebendige Community von Selbsthostern, während es die kommerziellen Interessen der Kern-Maintainer schützt.

Warum es wichtig ist

Für Teams, die ihre eigene Infrastruktur betreiben, ist Vorhersagbarkeit wertvoller als reine Geschwindigkeit. Zu wissen, dass n8n für jede Ausführung eine Single-Threaded-Schleife verwendet, bedeutet, dass Debugging deterministisch ist. Wenn ein Workflow fehlschlägt, erfasst das Zustandsobjekt genau, was in jedem Schritt passiert ist. Ingenieure können die runData inspizieren, um Eingabe und Ausgabe jedes Knotens zu sehen, was es einfacher macht, zu identifizieren, wo Datentransformationen fehlgeschlagen sind. Diese Sichtbarkeit fehlt oft bei Black-Box-SaaS-Alternativen.

Skalierbarkeit ist ein weiterer kritischer Faktor. Da der Ausführungsstatus serialisierbar ist, kann n8n horizontal über den Queue-Modus skaliert werden. Der Hauptanwendungsserver bleibt leichtgewichtig und bearbeitet nur API-Anfragen und Webhook-Eingänge, während dedizierte Worker-Prozesse die schwere Arbeit der Workflow-Ausführung übernehmen. Diese Trennung ermöglicht es DevOps-Teams, Ressourcen basierend auf der Queue-Tiefe abzustimmen, statt zu raten, wie viel CPU der Hauptprozess benötigt. Sie verhindert auch, dass hochvolumiger Webhook-Traffic die Benutzeroberfläche blockiert.

Was Sie tun können

  • Ausführungsreihenfolge prüfen: Überprüfen Sie Ihre komplexen Workflows und wechseln Sie zwischen den Ausführungsordnungen v0 und v1, um zu sehen, ob sich Leistung oder Logik für spezifische Anwendungsfälle verbessern.
  • Leere Zweige behandeln: Setzen Sie explizit alwaysOutputData: true bei Knoten, bei denen nachgelagerte Aktionen erfolgen müssen, auch wenn der vorherige Schritt keine Ergebnisse liefert.
  • Queue-Tiefe überwachen: Wenn Sie den Queue-Modus verwenden, richten Sie Warnmeldungen für die Länge der Redis-Queue ein, um Worker-Pods automatisch mittels Kubernetes HPA oder KEDA zu skalieren.
  • Run Data inspizieren: Nutzen Sie den integrierten Execution Viewer, um die pairedItem-Linie zu untersuchen, wenn Sie Datenzuordnungsfehler in komplexen Joins debuggen.
  • Lizenzkonformität verifizieren: Stellen Sie sicher, dass Ihre Nutzung mit der Sustainable Use License übereinstimmt, insbesondere wenn Sie benutzerdefinierte Automatisierungen für externe Kunden erstellen.
  • Webhook-Resilienz testen: Simulieren Sie High-Throughput-Webhook-Ereignisse, um zu überprüfen, dass Ihre dedizierten Webhook-Processor nicht den Main-UI-Thread blockieren.

Weitere News

Alle News