Data Engineering mit Talend

Im letzten Jahr haben wir hier im Blog beschrieben, wie in der Azure Data Factory Java Code bzw. JARs ausgeführt werden können. Wie das Java-zentrierte Data Integration Tool von Talend dies bewerkstelligt, ist problemlos ohne Tutorial verständlich und daher keinen ganzen Blogbeitrag wert. Stattdessen soll hier eine Idee vermittelt werden, was Talend für weitere Möglichkeiten bietet und außerdem, an welchen Stellen sich Fallstricke verstecken können. Der Fokus dieses Beitrags liegt auf dem klassischen Data Integration Tool.

Feel free!

Talend bietet für die einzelnen Produkte, wie beispielsweise Data Integration (DI), Big Data (BD), Enterprise Service Bus (ESB), Data Catalog oder Data Preparation, nicht nur kostenlose “Open Studio” Versionen zum Download an, sondern veröffentlicht auch deren Source Code. Einem ersten Einblick steht also nichts im Wege. Jedes Tool lässt sich direkt auf dem Laptop installieren und ausprobieren, Voraussetzung ist lediglich die passend installierte Java Laufzeitumgebung.

Ähnlich offen sind die selbst entwickelten Talend DI Jobs gestrickt: Die Entwicklung der Datenstrecken erfolgt größtenteils grafisch, indem einzelne Komponenten verbunden werden. Diese grafische Darstellung der Datenstrecke lässt sich per Knopfdruck in nativen Java-Code übersetzen. Das ist nicht nur für neugierige Entwickler sinnvoll, die wissen wollen wie Talend intern den Job übersetzt, sondern auch wichtig, um beispielsweise schnell herauszufinden, wo die Ursachen für Kompilierungsfehler liegen. In diesem Sinne verhält sich Talend wie ein Java-Code-Generator. Dieser Code lässt sich theoretisch auf beliebigen Servern deployen und ausführen. Dieses Prinzip ist Kennern des mittlerweile abgelösten Oracle Warehouse Builders (OWB), der aus der grafischen Darstellung der Datenstrecke per Knopfdruck ein Oracle PL/SQL Paket generiert, geläufig.

Dem Aufbau der Talend Jobs sind ebenfalls kaum Einschränkungen gesetzt. Es gibt keine strikte Trennung zwischen orchestrierenden und verarbeitenden Abläufen wie man es zum Beispiel von Informatica (workflow vs. mapping) oder DataStage (sequences vs. jobs) kennt. Ein einzelner Talend Job kann beliebig viele weitere eigenständige Jobs sequenziell oder parallel aufrufen. Weiterhin kann ein Talend Job mehrere interne Subjobs (zusammenhängende Komponenten) enthalten, die ebenfalls sequenziell oder parallel bearbeitet werden. Schließlich stellt Talend DI die kleine bzw. integrierbare Version von Jobs zur Verfügung: Joblets. Diese sind nur innerhalb eines Jobs ausführbar und können einen Datenfluss Ein- und Ausgang besitzen.

Schema eines Talend Jobdesigns
Talend Jobdesign: Jeder Job (Rechtecke) besteht aus verknüpften Komponenten (Kreise). Diese können zum Beispiel Daten aus einer Datenbank, einer Datei oder REST Schnittstelle laden, bearbeiten, wegschreiben oder ähnliches. Weiterhin lassen sich andere Jobs oder Joblets (gestricheltes Rechteck) einbinden. Hierbei können die Jobs entweder in der gleichen jvm Umgebung gestartet werden oder in einer separaten und somit unabhängigen jvm. Paralleles Ausführen von Komponenten oder Jobs (gestrichelte Pfeile) ist ebenfalls möglich.

Freiheit durch Generik: Bei Talend DI ist man nicht durch etwaige Unterschiede in Tabellenschemata gezwungen, für jede Tabelle einen eigenen Job zu schreiben, sondern kann einen einzelnen Job mit Hilfe eines dynamischen Schemas wiederverwenden. Es ist also möglich eine Vielzahl von Tabellen mit nur einem Job, Joblet oder einer Jobkette zu laden. Sollten doch mehrere Jobs nötig sein, können diese immerhin durch einen einzelnen dynamischen Jobaufruf komfortabel zusammengefasst werden. Während der Laufzeit ist es außerdem möglich zu entscheiden, ob alle oder nur ein Teil der Jobs ausgeführt werden soll.

Wie werden Parameter verwendet? Ganz so wie man möchte! Es gibt zahlreiche Möglichkeiten Konzepte für Parameter zu erstellen, wodurch eine optimale Passung an Projekt und die (Unternehmens-) Umgebung sichergestellt werden kann. Grundsätzlich können in einem Standard Talend DI Job sogenannte Kontextparameter definiert werden. Diese Parameter lassen sich unter frei wählbaren Kontexten (Umgebungen) verschieden definieren. Beispielsweise könnte man die Umgebungen „Entwicklung“, „Test“ und „Produktion“ definieren und für den Parameter „datenbank_benutzer“ in jeder Umgebung einen separaten Wert eintragen. Mit solch einem Ansatz sind die Werte dem Parameter pro Umgebung fest zugewiesen. Die Umgebung lässt sich anschließend beim Programmaufruf frei wählen.
Ein Überschreiben der definierten Parameter ist jederzeit beim Programmaufruf über das Talend Administration Center (TAC) oder per CLI bzw. MetaServlet möglich.
Ein implizites Laden der Kontextparameter stellt eine Erweiterung zu dem festen Eintragen im Job dar: In den Jobeinstellungen lässt sich eine Datei oder eine Datenbanktabelle angeben, aus der bei jedem Programmstart die Parameter geladen werden. Diese überschreiben dann die eventuell schon gesetzten Werte im Job.
Sollte dieses noch nicht ausreichen, können mit Hilfe eines selbst gebauten Talend Jobs die Parameter auch explizit geladen werden. So lassen sich die Parameter beispielsweise aus einer hierarchischen Datei wie xml oder json laden. Soll die Parameterdatei beim Programmstart direkt aus dem Git mit einem definierten Git-tag oder aus einer firmeninternen REST-Schnittstelle geladen werden? Kein Problem. Hierzu könnte man beispielsweise ein Joblet entwickeln und dieses in jedem Job zu Beginn einbinden.

Java-Code lässt sich direkt im Job mit Hilfe einer Auswahl von drei Komponenten einbinden:

  1. Soll der Code nur einmal ausgeführt werden? Hierzu ist die primitive tJava-Komponente zu verwenden. Anwendungsbeispiele sind das Setzen von Triggerpunkten, Abzweigungspunkte für if-then-else Anweisungen oder schnelle Debug-Ausgaben.
  2. Soll der Java-Code für jede Zeile im Datenstrom angewendet werden? Hierzu kann die tJavaRow-Komponente verwendet werden. Im Gegensatz zu tMap ist tJavaRow sehr flexibel einsetzbar und für gewisse Aufgaben auch übersichtlicher und besser wartbar.
  3. Die dritte Komponente verbindet 1. und 2.: In der tJavaFlex lässt sich für den Start und für das Ende eine Art tJava und für den mittleren Teil eine tJavaRow in einer Komponente verbinden. Beispielsweise lassen sich so zum Start Parameter einmalig initialisieren und zum Ende Logs schreiben.

Komplexer bzw. wiederverwendbarer Java-Code lässt sich in einem global erreichbaren Ort im Talend Repository ablegen. Hier lassen sich Java-Klassen definieren und überall mittels Funktionsaufruf einbinden. Über die tLibraryload-Komponente lässt sich direkt im Job eine JAR einbinden und direkt nutzen. Für klickbare UI-Liebhaber lassen sich eigene Komponenten erstellen. Eventuell hat die Talend Community schon eine Komponente auf der Talend Exchange Plattform zum Download bereitgestellt.

Monitoring: Auch beim Monitoring sind dem Entwickler keine Grenzen gesetzt. Standardmäßig wird nur wenig geloggt und der Logger gibt nicht viel mehr als Job Start- und Endzeit, sowie dem return code preis. Es lassen sich aber auch ausgewählte Datenströme überwachen, indem die mitgelieferte Activity Monitoring Console (AMC) verwendet wird. Über die AMC lassen sich verschiedene Auswertungen fahren und so zum Beispiel die Historie der letzten Jobläufe (Laufzeiten oder Datenmengen) grafisch darstellen. Darüber hinaus lässt sich natürlich auch ein custom Monitoring aufbauen, welches alle relevanten Informationen wegschreibt und komfortabel auswerten lässt.

Zum Thema Continuous Integration / Continuous Delivery sei an dieser Stelle auf unsere Whitepaper verwiesen. Talend bietet jedoch durch Verwendung des MetaServlets und Git-Integration optimale Bedingungen, um Code automatisiert zu mocken, deployen und testen.

Sei gewarnt!

Große Datenmengen im Batch zu verarbeiten ist prinzipiell sehr gut möglich, man muss sich jedoch Gedanken um das Speichermanagement machen. Eines der ersten doings offizieller Talend Tutorials besteht aus dem Erhöhen des maximal zuweisbaren Speichers und das nicht ohne Grund. Eine derartige Erhöhung ist solange unkritisch, bis der physische Arbeitsspeicher insgesamt nicht mehr ausreicht. Auch hier gibt es Abhilfe: Die meisten Komponenten, die eine Gesamtsicht auf die Daten benötigen, müssen die Datenmenge nicht zwingend im Arbeitsspeicher vorhalten, sondern können Daten auf der Platte auslagern. Die andere Möglichkeit ist auf eine sortierte Eingangsdatenmenge zu setzen und dann lediglich Vorgänger und Nachfolger zu vergleichen. Hierfür gibt es zum einen native Komponenten, wie zum Beispiel tAggregateSortedRow, und zum anderen kann auch auf Java-Komponenten gesetzt werden.

Vorsicht ist immer geboten, wenn ein Tool sehr viele Freiheiten bietet. Ohne klare Konzepte, zum Beispiel zur Namenskonvention von Jobs, ist nicht direkt ersichtlich, welcher Job denn nun der zu startende Job ist. Weiterhin ist die Fehlersuche bei langen Jobketten unter Umständen sehr komplex. Es ist immer abzuwägen, wie generisch/komplex oder simpel die Jobs gebaut werden, um für möglichst viele Bereiche, wie zum Beispiel Entwicklung, Wartung, Fehlersuche oder Deployment, eine komfortable und zukunftsorientierte Lösung zu bieten.

Eine Migration oder eine Teilmigration aus einem anderen ETL-Tool kann bei einem Talend Projektstart meistens eine Hilfe liefern. Hierbei stößt man jedoch schnell an die Grenzen der Möglichkeit eines 1:1 Nachbaus des Jobdesigns. Das heißt i.d.R. nicht, dass die Logik nicht abbildbar ist, sondern dass eine andere Herangehensweise entwickelt werden muss, wie in einem früheren Blogbeitrag am Beispiel des Aufteilens und Zusammenführens des Datenstroms schon gezeigt wurde.

Zusammengefasst bietet Talend eine offene und flexible ETL/ELT-Entwicklungsumgebung. Eine Vielzahl von nativen Komponenten und Konnektoren können mit Hilfe eigener Java-Komponenten einfach erweitert und schließlich durch Verknüpfung und Orchestration zu hochperformanten Datenstrecken aufgebaut werden, die perfekt auf das eigene Projekt bzw. die Firmenstruktur angepasst sind.