Von Janis Ax auf Mittwoch, 15. Dezember 2021
Kategorie: Data Management

Apache NiFi: Penalization vs. Yielding

Jeder Prozessor in Apache NiFi verfügt über die beiden oben genannten Optionen, doch nur selten werden sie eingestellt oder überhaupt beachtet.
Richtig konfiguriert und genutzt können beide jedoch sehr mächtig und hilfreich sein. In diesem Blogartikel wollen wir die beiden Optionen Penalization und Yielding genauer betrachten und ihr Verhalten an einigen Beispielen veranschaulichen.

Theoretisch betrachtet …

Zunächst betrachten wir beide Einstellungen in der Theorie, bevor wir sie uns an einem Beispiel anschauen.

Zu Beginn müssen wir klären, wann die Einstellungen in Kraft treten:

Beide Optionen sind nur für einen Fehlerfall relevant, das heißt, wenn ein FlowFile bei der Verarbeitung einen Error produziert und nach „failure" geroutet wird. Hierbei unterscheidet NiFi Fehler in zwei Kategorien:

  1. Es gibt eine Chance, dass das FlowFile im nächsten Versuch abgearbeitet werden kann (bspw. Fehler durch temporäre Netzwerkprobleme)
  2. Es kann sich auch um ein schwereres Problem handeln und das FlowFile wird auch im nächsten Versuch nicht prozessiert.

Im ersten Fall, wenn also ein temporärer Fehler aufgetreten ist, wendet NiFi die „Penalization" Einstellung an. Im zweiten Fall, wenn ein schwerwiegender Fehler auftritt, wendet NiFi die „Yielding" Einstellung an. Mit diesem Wissen können wir uns anschauen, was mit einem FlowFile bzw. einem Prozessor passiert, wenn NiFi „Penalization" oder „Yielding" anwendet.

Grundsätzlich versteht NiFi unter „Penalization" die Zeit, in der ein FlowFile nach einem temporären Fehler nicht mehr von diesem Prozessor verarbeitet wird. Das bedeutet: Wenn beispielsweise der PutFTP-Prozessor einen Error produziert, da die Zieldatei schon existiert und die „Penalization"-Zeit auf 5 Minuten steht, so wird dieses FlowFile in den nächsten 5 Minuten nicht mehr von dem Prozessor verarbeitet. Nach dieser Zeit wird der Prozessor das FlowFile wieder aufnehmen und erneut versuchen zu verarbeiten. Hierbei handelt es sich um einen temporären Fehler, weil der Dateiname meist dynamisch pro FlowFile gesetzt ist. Dementsprechend kann es sein, dass das nächste FlowFile in der Queue keinen Fehler produziert.

Tritt ein schwerwiegender Fehler auf, beispielsweie weil NiFi einen Host nicht auflösen kann, der fest im Prozessor konfiguriert ist, dann geht NiFi nicht davon aus, dass es sich dabei um einen temporären Fehler handelt. Es wird „Yielding" angewendet. „Yielding" wirkt sich nicht auf ein FlowFile sondern auf einen Prozessor aus. Die „Yielding" Zeit definiert, wie lange der gesamte Prozessor keine weiteren FlowFiles bearbeitet. Das bedeutet, dass auch keine anderen FlowFiles durch diesen Prozessor transferiert werden.

Wann ist ein Fehler schwerwiegend?

Mit dem Wissen, dass NiFi-Fehler während der Verarbeitung in Schweregrade einteilt, stellt sich unweigerlich die Frage, anhand welcher Kriterien die Einteilung erfolgt. Wann ist ein Fehler schwerwiegend?

Die Kategorisierung und damit die Entscheidung, ob "Penalization" oder "Yielding" angewendet werden soll, treffen die Entwickler:innen des jeweiligen Prozessors.
Tritt eine Exception auf, haben sie die Möglichkeit, entweder die Methode penalize(FlowFile) auf ein FlowFile oder aber die Methode yield auf den gesamten Prozessor anzuwenden.

Damit trifft also nicht NiFi die Entscheidung, sondern eigentlich der Prozessor. Daher variiert das Verhalten der Prozessoren auch. Die einfachste Möglichkeit für die DataFlow-Entwickler:innen ist es, die Einstellungen anhand vergangener Erfahrungswerte vorzunehmen. Weiterhin gibt es natürlich die Option, sich den Quellcode der Prozessoren direkt anzuschauen.

Was heißt das in der Praxis?

Um uns das Verhalten in der Praxis besser anschauen zu können, haben wir einen Beispiel-Flow erstellt.

In diesem Blogartikel gehen wir von folgendem Szenario aus:

Die Datenquellen werden über die drei „GenerateFlowFile"-Prozessoren realisiert und das Kopieren der Dateien übernimmt der PutFTP-Prozessor.

Die Konfiguration des PutFTP-Prozessors erfolgt dynamisch über die Attribute der ankommenden FlowFiles. Dadurch ist es möglich, dass bei einer Datenquelle ein Hostname unbekannt sein kann (fehlerhaftes Attribut), wohingegen die anderen einen korrekten Hostnamen hinterlegt haben.

Starten wir nun den linken Prozessor (orange), – „Generate TestFile with wrong name" – entsteht der Fehler, dass die Datei schon existiert und der Prozessor aktiviert für das FlowFile die Penalty-Duration. 

Dies kann man noch besser sehen, wenn ein zweites FlowFile generiert wird. Man sieht, dass ein FlowFile um 18:56:20 Uhr bearbeitet und dann genau 30 Sekunden später, um 18:56:50 Uhr erneut verarbeitet wurde (siehe uuid). Das zweite FlowFile wurde jeweils eine Sekunde später, um 18:56:20 Uhr und um 18:56:51 Uhr bearbeitet. Beide FlowFiles wurden, nachdem die Fehler aufgetreten sind, für je 30 Sekunden in den Penalty-Zustand versetzt.

Möchten wir nun auch Yielding veranschaulichen, starten wir den rechten Prozessor (rot) „Generate TestFile with wrong host". Dieser ist mit einem für NiFi unbekannten Hostnamen konfiguriert.

Sobald das FlowFile von dem Prozessor verarbeitet wird, entsteht, wie erwartet, der Fehler „UnknownHostException" und der Prozessor versetzt sich selbst in den Yield-Zustand.

Für den PutFTP-Prozessor ist die Yielding-Duration auf 5 Minuten eingestellt, in dieser Zeit wird also kein weiteres FlowFile mehr verarbeitet.

In der Zwischenzeit sind weitere FlowFiles in der Queue angekommen, die bearbeitet werden, sobald die Yield-Duration abgelaufen ist. 

Nach 5 Minuten beginnt NiFi mit der weiteren Verarbeitung. Dabei wurden einige FlowFiles aus der Datenquelle mit dem doppelten Dateinamen, aber auch ein FlowFile aus der richtigen Quelle (siehe success) verarbeitet.

Zusammenfassung

Der Einsatz beider Einstellungen kann in bestimmten Flows und Umgebungen sinnvoll sein. Generell lässt sich festhalten, dass die "Penalty"-Einstellung insgesamt einen kleineren "Effekt" auf die Ausführung von Flows hat, da sie die Ausführung einzelner FlowFiles im schlimmsten Fall nur verzögert, aber nicht ganze Prozessoren zum Stillstand bringt.

Für die meisten Flows sind die Standartwerte völlig ausreichend. Dennoch gibt es Umstände, bei denen ein Tuning der Werte sinnig ist. Wird bspw. der FTP-Prozessor genutzt und die Verbindung zum Remote-Host ist immer wieder Unterbrechungen ausgesetzt, kann darüber nachgedacht werden, den Wert zu erhöhen. Dies wird die Ressourcen des NiFi-Clusters schonen.

Die Yield-Duration sollte etwas vorsichtiger betrachtet werden. Sie greift härter in den DataFlow ein. Ist der Wert zu hoch, hält ein gestoppter Prozessor mitunter den ganzen DataFlow auf, nur weil einzelne FlowFiles problematisch sind. Der Wert sollte aber auch nicht zu niedrig gesetzt werden, da sonst unnötige Log-Dateien mit wiederkehrenden Fehlermeldungen geschrieben werden und das Cluster unnötiger Last ausgesetzt ist.

Kommentare hinterlassen