Blog

NiFi Ingestion Blog Serie. TEIL V - Es geht schnell und einfach, was kann da schon schiefgehen - ein Jahr Geschichte eines bestimmten NiFi-Flows

Tomasz Nazarewicz

Aktualisiert Dezember 5, 2025
8 Minuten

Apache NiFi, eine Big Data Processing Engine mit grafischer WebUI, wurde entwickelt, um Nicht-Programmierern die Möglichkeit zu geben, Datenpipelines schnell und ohne Programmieraufwand zu erstellen und sie von den schmutzigen, textbasierten Implementierungsmethoden zu befreien. Leider leben wir in einer Welt der Kompromisse, und diese Funktionen haben ihren Preis. In unserer Blogserie möchten wir unsere Erfahrungen und Erkenntnisse aus der Arbeit mit produktiven NiFi-Pipelines vorstellen. Dies wird in den folgenden Artikeln geschehen:

Apache NiFi - warum lieben und hassen Dateningenieure es gleichzeitig?

Teil I - Schnelle Entwicklung, mühsame Pflege

Teil II - Wir haben bereitgestellt, aber zu welchem Preis... - CI/CD des NiFi-Flows

Teil III - Kein Programmieren, einfach ziehen und ablegen, was Sie brauchen, aber wenn es nicht da ist... - benutzerdefinierte Prozessoren, Skripte, externe Dienste

Teil IV - Ein Universum aus Flow-Dateien - NiFi-Architektur

Teil V - Es geht schnell und einfach, was kann da schon schiefgehen - ein Jahr Geschichte eines bestimmten NiFi-Flusses

Ich habe nur eine Regel und die lautet ... - Empfehlungen für die Verwendung von Apache NiFi

Wir müssen es einfach halten

Der Anwendungsfall für das Projekt war anfangs sehr einfach dargestellt. Wir mussten die aktuelle Lösung durch eine auf Apache NiFi basierende Pipeline ersetzen und die Anforderung lautete, "Dateien von einem Ort zu nehmen, zu prüfen, ob die darin enthaltenen Daten die Anforderungen erfüllen und sie auf HDFS abzulegen". Wie einer der Ingenieure, die damals mit uns zusammenarbeiteten, sagte, lag der Schwerpunkt darauf, "es einfach zu halten" und da die Aufgabe an sich nicht allzu kompliziert war, haben wir uns darauf eingelassen.

Wir begannen mit einem Proof-of-Concept (PoC), um zu prüfen, ob NiFI das richtige Tool für uns ist. Wir entschieden uns für eine generische Lösung und einen NiFi-Flow, der Hunderte von verschiedenen Dateien mit verschiedenen Verarbeitungsregeln verarbeiten konnte. Nach ein paar Wochen hatten wir die meisten Dinge (die zu diesem Zeitpunkt erforderlich waren) zum Laufen gebracht. Es gab eine einzige Anforderung: "Validierung des Inhalts der eingelesenen Dateien durch benutzerdefinierte Regeln", die wir für NiFi nicht geeignet fanden. Um dies zu lösen, haben wir einen Apache Spark-Job geschrieben und die SparkLauncher-Bibliothek verwendet, um Spark-Jobs aus dem ExecuteGroovyScript-Prozessor heraus auszuführen. Während NiFi gut für generische Datenpipeline-Probleme geeignet ist, ermöglicht Apache Spark die Implementierung von benutzerdefinierter Logik auf eine bessere Art und Weise mit integrierten Unit-Tests.

Unser Fluss nahm Daten in HDFS und HIVE auf, und die andere Anforderung war, dass nicht zwei Datensätze, die eine einzige Hive-Partition betreffen, gleichzeitig verarbeitet werden durften. Dies erforderte einen externen Sperrmechanismus, den wir außerhalb von NiFi implementieren wollten.

Nach ein paar Wochen konnten wir sehen, wie unser Flow auf Probedatensätzen lief. Der PoC war fertig und die Leistungskennzahlen waren im Vergleich zu einem Altsystem um ein Vielfaches besser. Wir wussten, dass uns noch einige wichtige Funktionen fehlten und begannen, sie in den nächsten Sprints zu implementieren. Obwohl wir versucht hatten, die notwendigen Funktionen im Voraus zu identifizieren, gab es immer noch viele Lücken, die beim Vergleich des Outputs unseres Systems mit dem des Altsystems entdeckt wurden. Dies waren die neuen Anforderungen, die ans Licht kamen und umgesetzt werden mussten.

Einfache Funktionen machen das System komplex

Mehrere einfache Funktionen in einem einzigen System machen es komplex. Das Schöne am agilen Vorgehen ist, dass Sie sich immer auf das Wichtigste konzentrieren und nicht auf der Grundlage falscher Annahmen arbeiten, die einige Monate zuvor gemacht wurden. Bedenken Sie jedoch, dass der agile Weg nicht nur die Geschäftsfunktionen betrifft, sondern auch die Architektur und die Codebasis.

Am Anfang haben wir nur NiFI-Prozessoren verwendet, aber irgendwann reichten diese nicht mehr aus, um alle Eckfälle zu bearbeiten, und wir begannen, Groovy-Skripte zu schreiben. Ein paar Zeilen Groovy-Code erledigten die Arbeit, wurden aber unübersichtlich und schwer zu verwalten. Ein gutes Beispiel für den Einsatz von Groovy-Skripten ist die Erstellung komplexer Hive-Abfragen auf der Grundlage der Attribute von Flowfile oder die Auflistung des Verzeichnisses, um die älteste Datei zu finden, die einem bestimmten Regex-Muster entspricht. Obwohl dadurch die Codebasis aufgeteilt wurde, hat sich die Komplexität dadurch nicht verringert: NiFI und Groovy-Skripte waren eng miteinander verbunden. Die Dinge funktionierten zwar, aber wir hatten dennoch das Gefühl, dass der Fluss immer größer wurde und wir das Wachstum stoppen mussten.

Irgendwann haben wir das mit REST-Microservices und der Extraktion der Logik von NiFI in separate Systeme erreicht. REST-Endpunkte entkoppelten die Systeme, da die Kommunikation über klar definierte Anfragen und Antworten erfolgt. Dadurch vergrößerte sich zwar die Codebasis, aber die Logik wurde in kleinere Teile aufgeteilt, die leichter zu handhaben und zu verstehen sind.

Aufteilen und erobern

Das hat eine Zeit lang funktioniert, aber trotzdem hat ein einziger NiFi-Flow alles erledigt und er ist gewachsen, wenn auch nicht mehr so schnell wie früher. Entweder sind Sie es, der die Komplexität verwaltet, oder die Komplexität, die Ihre Architektur verwaltet. Irgendwann wurde uns klar, dass der Fluss wieder zu groß wurde und wir beschlossen, ihn aufzuteilen.

Wir haben dies mit Apache Kafka erreicht. Der Fluss, der die Verarbeitung beendet, veröffentlicht ein Ereignis, das konsumiert wird und den Start des nächsten Flusses auslöst. Obwohl NiFi Prozessoren für den Zugriff auf Kafka bereitstellt, haben wir uns dafür entschieden, dies über Microservices zu tun. Im Projekt ist es nicht unser Team, das Kafka verwaltet und aktualisiert, und wir wollten uns später nicht mit Versionskompatibilitätsproblemen herumschlagen. Wir haben einen REST-Endpunkt erstellt, um Nachrichten in Kafka zu veröffentlichen, und einen Event-Consumer, der Kafka-Ereignisse abfragt und NiFi benachrichtigt, indem er einen Endpunkt in NiFi anfordert, der vom ListenHTTP-Prozessor ausgeführt wird. Diese Form der Kommunikation ist wirklich wichtig, denn sie ermöglicht es unserem Verbraucher, den Kafka-Offset zu bestätigen, nachdem das Ereignis erfolgreich an NiFI übertragen wurde. Die Übergabe erfolgt, nachdem wir 200 Antwortcodes von NiFI erhalten haben. Damit stellen wir sicher, dass eine Flow-Datei erfolgreich erstellt wurde und keine Daten verloren gehen.


Die Aufteilung der Abläufe hat sich aus Sicht der Entwicklung als sehr vorteilhaft erwiesen. Jeder Fluss ist nur halb so groß wie der ursprüngliche und kann von neuen Teammitgliedern leichter verstanden werden. In früheren Beiträgen haben wir einige Einschränkungen von NiFi erwähnt, wie z.B. das Fehlen von Zweigen bei der Arbeit in Entwicklungsumgebungen. Die Aufteilung des Flusses hat dieses Problem entschärft.

Vom Proof-of-Concept zur Produktion

Wiederholen Sie alles, was fehlschlagen kann

In einer Proof-of-Concept-Phase haben wir uns nicht viel um Eckfälle gekümmert. Wenn wir zum Beispiel eine Hive-Abfrage ausführen, haben wir uns nicht um mögliche Wiederholungsversuche gekümmert, wenn ein Fehler auftritt. Das kam erst später, und dann war es notwendig, jedem Prozessor, der mit Systemen von Drittanbietern wie HDFS, Hive, Kafka usw. verbunden ist, Wiederholungen hinzuzufügen: HDFS, Hive, Kafka oder REST-Dienste. Um dieses Problem auf generische Weise zu lösen, haben wir eine Retry-Prozessgruppe erstellt, die aus über 10 Prozessoren bestand. Sie hat genau das getan, was wir brauchten, und wir haben sie an allen Stellen eingesetzt, wo es nötig war. Der Nachteil war, dass sich unser Datenfluss durch den Wiederholungsmechanismus um über 200 Prozessoren vergrößerte. Mit einem Upgrade auf NiFi 1.10 wurde ein RetryFlowFile-Prozessor eingeführt, der fast alles tut, was wir brauchen (außer der Ausbeutezeit, die sich bei den nächsten Wiederholungen nicht ändern kann).

Generieren Sie Daten für die Entwicklungsumgebung

Wir haben viel Zeit damit verbracht, Daten für niedrigere Umgebungen vorzubereiten, und das hat sich ausgezahlt. In vielen Fällen ist dies die einzige Möglichkeit, die Pipeline richtig zu testen, bevor sie in die Produktion geht. Wir haben in NiFi separate Abläufe eingebaut, die Scheindatensätze für die Verarbeitung vorbereiten, und Abläufe, die die Ergebnisse der Verarbeitung löschen, damit Ihnen nie der Speicherplatz ausgeht.

Loggen Sie so viel wie möglich außerhalb des glücklichen Pfades

Protokolle waren unser bester Freund beim Debuggen des Verhaltens der Anwendung. Da NiFi auf mehreren Rechnern läuft, beschlossen wir, alle Protokolle in ElasticSearch zu erfassen und in Kibana darzustellen. NiFi ist eine Java-Anwendung und wir konnten ihre Logback-Konfiguration so ändern, dass sie die Protokolle dorthin sendet, wo sie benötigt werden. So konnten wir Protokolle aus Groovy-Skripten abrufen und auch die mit den Protokollen verbundenen Metriken über MDC (Mapped Diagnostic Context) verarbeiten. Darüber hinaus bietet NiFi einen LogMessage-Prozessor, den wir zum Erstellen von Protokolleinträgen verwendet haben, wenn solche Informationen wichtig waren. Immer, wenn die Flowfile-Verarbeitung mit einem Fehler abbricht, haben wir einen beschreibenden Protokolleintrag erstellt.

Fazit

Was wir geliebt haben? Wir konnten sehr schnell mit neuen Funktionen experimentieren. Die Zeit, bis man die Funktion in Aktion sieht, ist sehr gering, so dass die Beteiligten die Funktionen bereits in einem frühen Stadium testen können. Wenn Sie mit einer Funktion scheitern, werden Sie schnell scheitern, was wirklich gut ist.

Was wir gehasst haben? Die Zeit, in der Sie die Funktion in Aktion sehen, ist NICHT die Zeit bis zur Markteinführung. Es dauert in der Regel länger als bei anderen Datenverarbeitungstechnologien, bis der funktionierende NiFi-Flow produktionsreif ist. Es ist gut, sich das im Voraus klar zu machen.

Verfasst von

Tomasz Nazarewicz

Contact

Let’s discuss how we can support your journey.