Ein­lei­tung

In der heu­ti­gen schnell­le­bi­gen Daten­land­schaft ste­hen Unter­neh­men vor der Her­aus­for­de­rung, eine wach­sende Flut von Daten aus ver­schie­de­nen Quel­len effi­zi­ent zu inte­grie­ren. Aller­dings ver­langt die Kom­ple­xi­tät von Cloud-basier­ten Lösun­gen und diver­sen Daten­for­ma­ten nach fle­xi­blen und effi­zi­en­ten Ansät­zen für den Geschäfts­er­folg. Hier bie­ten meta­da­ten­ge­trie­bene Pipe­lines in Data Fac­tory (ADF), ein zen­tra­ler Cloud-basierte Daten­in­te­gra­ti­ons­dienst, eine viel­ver­spre­chende Lösung.

Aber wie kann man die Daten­in­te­gra­tion nicht nur bewäl­ti­gen, son­dern auch so gestal­ten, dass sie zukunfts­si­cher, wart­bar und ska­lier­bar ist? In die­sem Blog­bei­trag ent­hül­len wir einen Ansatz, der in einem unse­rer Kun­den­pro­jekte beacht­li­che Erfolge erzielt hat. Unser Ziel war es, die Arte­fakte in Azure Data Fac­tory so gene­risch und wie­der ver­wend­bar wie mög­lich zu gestal­ten, um die Hand­ha­bung zu ver­ein­fa­chen und gleich­zei­tig die Auto­ma­ti­sie­rung und Effi­zi­enz zu maxi­mie­ren. Ent­de­cken Sie mit uns, wie eine meta­da­ten­ge­trie­bene Stra­te­gie in Azure Data Fac­tory nicht nur tech­ni­sche Hür­den über­win­det, son­dern auch die Effi­zi­enz, Wart­bar­keit und Ska­lier­bar­keit Ihrer Daten­in­te­gra­ti­ons­pro­zesse grund­le­gend transformiert.

Grund­la­gen der dyna­mi­schen Daten­in­te­gra­tion in Azure Data Factory

Azure Data Fac­tory bie­tet ver­schie­dene Mög­lich­kei­ten, Arte­fakte wie Lin­ked Ser­vices, Data Sets, Acti­vi­ties und Pipe­lines gene­ri­scher und wie­der­ver­wend­ba­rer zu machen. Dies eröff­net neue Wege für eine fle­xi­ble Daten­in­te­gra­tion, die weit über starre, manu­ell kon­fi­gu­rierte Pro­zesse hinausgeht. 

Gene­ri­scher Lin­ked Service

Als ers­tes ein­fa­ches Bei­spiel neh­men wir einen Lin­ked Ser­vice der sich zu einem Azure Data Lake Sto­rage Gen2 (ADLS) ver­bin­den kann. In dem Screen­shot unten lässt sich fest­stel­len, dass alle wich­ti­gen Infor­ma­tio­nen aus einem dyna­mi­schen Inhalt kom­men. Keine Infor­ma­tio­nen wer­den kon­kret ange­ge­ben. Für den dyna­mi­schen Inhalt bie­tet Azure Data Fac­tory eine eigene Spra­che, die soge­nannte Expres­sion Lan­guage. In unse­rem Bei­spiel wird die URL des Sto­rage Accounts, zu dem man sich ver­bin­den möchte, über die Con­cat-Funk­tion mit Hilfe des Para­me­ters par_storageAccount erstellt. 

Das Resul­tat ist, dass die Azure Data Fac­tory nun die­sen einen Lin­ked Ser­vice benut­zen kann, um sich mit jedem Sto­rage Account zu ver­bin­den. Dar­auf­hin muss man ledig­lich den Namen des Sto­rage Accounts als Para­me­ter mit­ge­ben. Eine wei­tere Vor­aus­set­zung ist, dass die Mana­ged Iden­tity der Data Fac­tory die nötige Berech­ti­gung auf dem Sto­rage Account hat. 

Somit hat man ein wie­der ver­wend­ba­res ADF Arte­fakt, statt jeweils einen Lin­ked Ser­vice pro Sto­rage Account. Die­ses Prin­zip wer­den wir jetzt auf alle wei­te­ren Arte­fakte und Fea­tures der Daten­in­te­gra­tion mit Azure Data Fac­tory anwenden.

Gene­ri­scher Data Set

Wir haben nun ein Data Set, wel­ches eine CSV Datei auf einem Sto­rage Account beschreibt. Die­ses Bei­spiel baut auf dem vor­he­ri­gen auf, weil für die Ver­bin­dung zu die­sem Sto­rage Account der Lin­ked Ser­vice aus dem ers­ten Bei­spiel benutzt wird. Wir wol­len hier jedoch noch nicht den Namen des Sto­rage Accounts fest ange­ben. Daher wird ein Data Set-Para­me­ter defi­niert, der den Namen des Sto­rage Accounts an den Lin­ked Ser­vice wei­ter gibt. 

Eine wei­tere wich­tige Infor­ma­tion ist, wo genau sich die CSV Datei auf unse­rem Sto­rage Account befin­det und wie sie heißt. Diese Infor­ma­tion wird über die Para­me­ter par_container, par_directory und par_filename bestimmt. Diese Infor­ma­tio­nen sind für alle Dateien auf einem Sto­rage Account relevant.

Es gibt aber auch For­mat spe­zi­fi­sche Para­me­ter, die nur für eine CSV Datei ange­ge­ben wer­den müs­sen. Da wir unse­ren Data Set für alle mög­li­chen unter­schied­li­chen CSV Dateien ver­wen­den wol­len, müs­sen wir auch hier­für Para­me­ter defi­nie­ren. So kann zum Bei­spiel eine CSV Datei mit Komma als Trenn­zei­chen mit dem sel­ben Data Set beschrie­ben wer­den wie eine CSV Datei mit Semi­ko­lon. Lei­der ist es nicht mög­lich ein Schema dyna­misch anzu­ge­ben. Wenn man ein Data Set mit einem spe­zi­fi­schen Schema benö­tigt, muss man einen neues Data Set erstellen.

Gene­ri­sche Pipelines

Möchte ich nun das gene­ri­sche Data Set aus dem letz­ten Bei­spiel benut­zen, um eine CSV Datei mit Azure Data Fac­tory aus einer belie­bi­gen Quelle auf einen Sto­rage Account zu kopie­ren, muss ich bei der Ver­wen­dung ledig­lich alle nöti­gen Infor­ma­tio­nen unter den Data Set Para­me­tern ange­ben. Wenn man diese Infor­ma­tio­nen hier fest­legt, hat man jedoch keine gene­ri­sche Pipe­line, die für alle ähn­li­chen Sze­na­rien wie­der­ver­wen­det wer­den kann. Die nöti­gen Infor­ma­tio­nen zum Aus­füh­ren einer bestimm­ten Auf­gabe müs­sen der Pipe­line erst zum Start mit­ge­ge­ben wer­den. Um meta­da­ten­ge­trie­bene Pipe­lines in Data Fac­tory zu ermög­li­chen, benö­tigt man ein geeig­ne­tes Meta­da­ten Konzept.

Der Ansatz: Meta­da­ten­ge­trie­bene Pipe­lines in Data Factory

Eine gene­ri­sche meta­da­ten­ge­trie­bene Pipe­line in Data Fac­tory ist wie ein Tem­p­late, das als Blau­pause für das Voll­rich­ten einer bestimm­ten Auf­gabe dient. Diese Auf­gabe ist meis­tens die Daten­über­tra­gung von einer defi­nier­ten Quelle zu einem bestimm­ten Ziel, aber es kann sich zum Bei­spiel auch um eine Über­prü­fung der Daten­qua­li­tät han­deln. Hier eine Liste von aus­ge­wähl­ten Bei­spie­len aus unse­rem Kun­den­pro­jekt wofür wir meta­da­ten­ge­trie­bene Pipe­lines ent­wi­ckelt haben:

  • Auf­ru­fen einer belie­bi­gen API mit oder ohne Bea­rer-Token als Auto­ri­sie­rung und abspei­chern der Daten als Datei auf einem Sto­rage Account (auch für meh­rere APIs mög­lich, die die selbe Base URL teilen)
  • Kopie­ren von Daten von einem exter­nen SFTP Ser­ver auf einen Sto­rage Account
  • Schrei­ben von Daten in einer CSV Datei in eine Azure Post­gres Tabelle mit dyna­mi­schem Map­ping und auto­ma­ti­schen Erstel­len der Tabelle bei ers­ter Ausführung
  • Extra­hie­ren von Daten von SAP via CDC Kon­nek­tor von Azure Data Fac­tory in ein bestimm­tes Daten­for­mat wie csv oder par­quet. Siehe unse­ren Blog­ar­ti­kel zu SAP Konek­to­ren von Azure Data Fac­tory: https://saracus.com/synvert-saracus-blog/sap-konnektoren-von-azure-data-factory/
  • Aus­füh­ren eines belie­bi­gen Dat­ab­ricks Note­books für kom­ple­xere Busi­ness Logik, mit Über­gabe von defi­nier­ten Parametern
  • Schema Vali­die­rung und Map­ping von Dateien wie csv, txt, parquet

Die Beson­der­heit die­ser Pipe­lines liegt darin, dass die Pipe­line ledig­lich eine Job-ID als Para­me­ter erhält. Alle wei­te­ren not­wen­di­gen Infor­ma­tio­nen bezieht sie aus einer oder meh­re­ren Meta­da­ten-Kon­fi­gu­ra­ti­ons­da­teien. Diese Dateien ent­hal­ten alle essen­zi­el­len Details über die Daten­quelle, das Ziel und das zu über­tra­gende Daten­ob­jekt sowie wei­tere Para­me­ter für bestimmte Zusatz­fea­tures einer Pipeline.

Vor­teile des meta­da­ten­ge­trie­be­nen Ansatzes

Ein zen­tra­ler Vor­teil des meta­da­ten­ge­trie­be­nen Ansat­zes in Azure Data Fac­tory liegt in der Ent­wick­lung einer uni­ver­sel­len Pipe­line, die umfas­send wie­der­ver­wend­bar ist. Diese Fle­xi­bi­li­tät ermög­licht es, bestimmte Funk­tio­nen durch Meta­da­ten zu ergän­zen, zu modi­fi­zie­ren oder weg­zu­las­sen, um die Anfor­de­run­gen spe­zi­fi­scher Daten­ver­ar­bei­tungs­auf­ga­ben zu erfül­len. Ein sol­ches Sys­tem ver­ein­facht nicht nur das Tes­ten und die War­tung signi­fi­kant, son­dern för­dert auch eine ein­heit­li­che Stan­dar­di­sie­rung. Die Kon­fi­gu­ra­tion über Meta­da­ten erlaubt zudem eine schnelle und effi­zi­ente Anpas­sung oder Erwei­te­rung der Funk­tio­na­li­tä­ten. Das ist beson­ders vor­teil­haft bei der Ver­wal­tung zahl­rei­cher, ähn­li­cher Daten­in­te­gra­ti­ons­pro­zesse. Bei­spiels­weise kön­nen ver­schie­dene Extrak­tio­nen aus SAP BW durch eine ein­zige Pipe­line abge­wi­ckelt wer­den, die ledig­lich unter­schied­li­che Meta­da­ten­kon­fi­gu­ra­tio­nen erhält.

Nach­teile des meta­da­ten­ge­trie­be­nen Ansatzes

Ein poten­zi­el­ler Nach­teil liegt in der Kom­ple­xi­tät der Pipe­lines, die ten­den­zi­ell mehr Akti­vi­tä­ten umfas­sen kön­nen. Dies resul­tiert anfangs in einem höhe­ren Ent­wick­lungs­auf­wand, da das Meta­da­ten­mo­dell auf die Pro­jekt­spe­zi­fi­ka­tio­nen abge­stimmt und gepflegt wer­den muss. Trotz­dem rela­ti­viert sich die­ser Auf­wand über die Zeit, da die Wie­der­ver­wend­bar­keit der Pipe­lines und Meta­da­ten für ver­schie­dene Pro­jekte und Kun­den die Not­wen­dig­keit umfang­rei­cher Neu­ent­wick­lun­gen mini­miert. Meist genü­gen kleine Anpas­sun­gen, um die Sys­teme an neue Anfor­de­run­gen anzupassen.

Obwohl der meta­da­ten­ge­trie­bene Ansatz viele Vor­teile bie­tet, las­sen sich nicht alle Sze­na­rien voll­stän­dig gene­ra­li­sie­ren. Ins­be­son­dere bei kom­ple­xe­ren Logi­ken sto­ßen gene­ri­sche Lösun­gen an ihre Gren­zen. Jedoch kön­nen auch hier durch die Über­gabe spe­zi­fi­scher Para­me­ter bestimmte War­tungs- und Effi­zi­enz­vor­teile rea­li­siert wer­den, was die Hand­ha­bung erleich­tert und die Fle­xi­bi­li­tät erhöht.

Meta­da­ten­kon­zept für gene­ri­sche ADF pipelines

Im fol­gen­den wird das Meta­da­ten­kon­zept für die meta­da­ten­ge­trie­be­nen gene­ri­schen ADF pipe­lines beschrie­ben, wel­ches wir für einen unse­rer Kun­den ent­wi­ckelt haben. Die­ses Kon­zept ist bereits mit leich­ten Abwand­lun­gen bei wei­te­ren Pro­jek­ten im Ein­satz. Um das Kon­zept zu ver­ste­hen, ist es hilf­reich zuerst auf die Pro­jekt­an­for­de­run­gen einzugehen.

In unse­rem Kun­den­pro­jekt bil­det unsere Azure Platt­form das zen­trale Ner­ven­sys­tem, das den Daten­fluss unter­schied­li­cher Dateien zwi­schen vie­len ver­schie­de­nen Sys­te­men sicher stellt. Ein bestimm­ter Daten­fluss von einem Quell- zu einem Ziel-Sys­tem wird als Inter­face bezeich­net. Dabei kann es sein, dass die Part­ner­sys­teme die Daten schi­cken oder abho­len, aber meis­tens geschieht das Über­tra­gen von Daten durch eine unse­rer gene­ri­schen Pipe­lines. Weil auch noch eine Viel­zahl an ver­schie­de­nen Pro­to­kol­len und Datei­for­ma­ten vor­kommt, macht es Sinn ein Inter­face aus klei­nen wie­der ver­wend­ba­ren Tei­len zu erstellen.

Unter­tei­lung der Metadaten

Daher haben wir uns ent­schie­den, die Meta­da­ten hori­zon­tal und ver­ti­kal auf­zu­tei­len. Hori­zon­tal gibt es drei ver­schie­dene Arten von Jobs, wobei ein Job immer einer gene­ri­schen ADF Pipe­line ent­spricht. Als ers­tes wer­den in der Inges­tion-Phase Daten vom Quell­sys­tem abge­holt und auf unse­rem Inbound Sto­rage Account gespei­chert. Dann fin­den in der Pro­ces­sing-Phase alle not­wen­di­gen Map­pings, Trans­for­ma­tio­nen oder Daten­qua­li­täts­checks statt. Schließ­lich wer­den die Daten in der Deli­very-Phase an das Ziel­sys­tem gesen­det und dabei nicht mehr verändert.

Ver­ti­kal gese­hen haben wir ver­schie­dene Meta­da­ten­ta­bel­len. Sie star­ten auf der höchs­ten Ebene sehr all­ge­mein und wer­den in den tie­fe­ren Ebe­nen immer spe­zi­fi­scher. Als ers­tes wird auf dem Inter­face-Level das gesamte Inter­face an sich beschrie­ben. Die Stan­dard­in­for­ma­tio­nen für jeden ein­zel­nen Job befin­den sich in der Job­ta­belle. Weil jeder Job auch sehr spe­zi­fi­sche Para­me­ter ent­hal­ten kann, wird auf dem Job­pa­ra­me­ter-Level hier­für in Form von Key-Value Paa­ren Platz geboten.

Über­sicht über Meta­da­ten mit Beispielen

Im fol­gen­den Schau­bild sind alle not­wen­di­gen Meta­da­ten. Weil wir man­che Para­me­ter je nach Umge­bung oder im Eng­li­schen Envi­ron­ment (DEVL, INTG, PROD) anpas­sen müs­sen, wer­den diese hier ent­spre­chend klas­si­fi­ziert. Als nächste Ebene im Schau­bild wer­den die Tabel­len­na­men und deren Rela­tion ange­ge­ben. Danach wer­den kurz ver­schie­dene Para­me­ter Typen klas­si­fi­ziert, auf die ich in den Bei­spie­len noch näher ein­ge­hen werde. Schließ­lich beschreibt die unterste Ebene den phy­si­schen Spei­cher­ort der Meta­da­ten, sodass diese auch aktiv genutzt wer­den können.

Für jeden ein­zel­nen Job wer­den die not­wen­di­gen Meta­da­ten aus den drei bereits genann­ten Tabel­len genom­men und in eine ein­zelne JSON Con­fig Datei abge­spei­chert. Diese jobId.json Datei wird auf den Meta­da­ten Sto­rage Account abge­legt und kann mit der Angabe der Job ID von einer gene­ri­schen ADF Pipe­line ein­ge­le­sen wer­den. Meis­tens wer­den auch wei­tere Meta­da­ten wie zum Bei­spiel eine Schema Datei, eine Map­ping Datei oder auch eine Envi­ron­ment abhän­gige Sys­tem Datei benö­tigt. Diese Dateien kön­nen mit Hilfe der Infor­ma­tio­nen in der jobId.json Datei refe­ren­ziert und zusätz­lich gela­den wer­den. Am bes­ten lässt sich alles an kon­kre­ten Bei­spie­len erläutern.

Fea­ture Information

Ein Fea­ture erle­digt eine meis­tens optio­nale kleine Teil­auf­gabe einer Pipe­line. Ein Bei­spiel ist die Archi­vie­rung einer Datei. Ist der ent­spre­chende Para­me­ter aus­ge­füllt, wird eine Kopie der Quell- oder Ziel­da­tei an die gewünschte Stelle archi­viert. Falls der Para­me­ter nicht aus­ge­füllt ist, pas­siert nichts. Für viele Fea­tures wie zum Bei­spiel die dyna­mi­sche Namens­ge­bung der Ziel­da­tei nimmt die Data Fac­tory Expres­sion Lan­guage eine zen­trale Rolle ein: https://learn.microsoft.com/de-de/azure/data-factory/how-to-expression-language-functions.

Pro­ces­sing

Diese Para­me­ter kon­trol­lie­ren die Pro­ces­sing Power einer Copy-Akti­vi­tät. Ein Bei­spiel ist wie stark der Pro­zess par­al­le­li­siert wer­den soll. Je nach Größe der Daten­men­gen und Anfor­de­run­gen an Lauf­zeit und Kos­ten, kann man hier ent­spre­chend hoch oder run­ter gehen. Die Stan­dard­werte wer­den als glo­bale Para­me­ter abge­spei­chert, so dass man diese Infor­ma­tion nicht über­all ange­ben muss.

For­mat

Diese Para­me­ter haben wir schon wei­ter oben in unse­rem CSV Data Set ken­nen gelernt. Diese Para­me­ter beschrei­ben alle for­mat­ab­hän­gi­gen Para­me­ter für die Quell- und/oder Ziel­da­tei. Es ist wich­tig diese fle­xi­bel anpas­sen zu kön­nen, weil jedes Sys­tem andere Anfor­de­run­gen hat.

Con­nec­tor

Diese Para­me­ter wer­den in der Job Para­me­ter Tabelle defi­niert, weil sie spe­zi­fisch für gewisse Kon­nek­to­ren sind. Bei dem SAP CDC Kon­nek­tor kann man hier zum Bei­spiel ange­ben, wel­che Spal­ten man extra­hie­ren möchte oder einen Fil­ter auf die Daten defi­nie­ren. Für einen API Auf­ruf kann man zusätz­li­che Hea­der oder die Request Methode (GET, POST) festlegen.

Glo­bal Parameters

Glo­bale Para­me­ter kön­nen in Azure Data Fac­tory gesetzt und von allen Pipe­lines benutzt aber nicht ver­än­dert wer­den. Man­che glo­bale Para­me­ter sind Envi­ron­ment spe­zi­fisch. Sie kön­nen wäh­rend eines Deploy­ments ver­än­dert wer­den. Das wich­tigste Bei­spiel ist der Para­me­ter par_environment, der mir angibt, ob ich mich auf der Entwicklungs‑, Inte­gra­ti­ons- oder Pro­duk­ti­ons­um­ge­bung befinde. Diese Infor­ma­tion wird an vie­len Stel­len benötigt. 

Ange­nom­men ich möchte den Namen mei­nes Archiv Sto­rage Accounts in den glo­ba­len Para­me­tern abspei­chern. Die­ser soll archiv[ENVIRONMENT] hei­ßen. Dann spei­chere den Sto­rage Account Namen als „archiv“ ab. Anschlie­ßend nutze ich die Expres­sion Lan­guage, um mit par_environment den rich­ti­gen Namen für jede Envi­ron­ment zu erstellen.

Sys­tem Con­nec­tor und Azure Key Vault Secrets

Hier wer­den alle Envi­ron­ment abhän­gi­gen Para­me­ter für ein bestimm­tes exter­nes Sys­tem abge­spei­chert. Jedes Sys­tem bekommt ein Kür­zel, das in der jobId.json datei refe­ren­ziert wird. Zusam­men mit dem par_environment Para­me­ter wird dann die rich­tige Datei eingelesen. 

In die­sen Dateien ste­hen alle nöti­gen Infor­ma­tio­nen, um sich mit dem jewei­li­gen Sys­tem zu ver­bin­den. Zusätz­lich kön­nen noch wei­tere Envi­ron­ment und Sys­tem abhän­gige Para­me­ter defi­niert wer­den. Ein gutes Bei­spiel sind die Infor­ma­tio­nen, um sich mit einem SFTP Ser­ver zu ver­bin­den. Hier wird der Host Name, der Port und die Daten zum Anmel­den benö­tigt. Sen­si­tive Infor­ma­tio­nen wie Pass­wör­ter wer­den als Secrets in einem Azure Key Vault ver­wal­tet. Hier wird ledig­lich das Secret refe­ren­ziert. Anschlie­ßend wird das Secret erst zur Lauf­zeit von der Pipe­line aus dem Key Vault extrahiert.

Fazit

Das vor­ge­stellte Meta­da­ten­kon­zept für gene­ri­sche meta­da­ten­ge­trie­bene Pipe­lines in Data Fac­tory hebt die Bedeu­tung einer struk­tu­rier­ten Ver­wen­dung von Meta­da­ten her­vor, um Daten­flüsse effi­zi­ent und fle­xi­bel zu gestal­ten. Durch die hori­zon­tale und ver­ti­kale Auf­tei­lung der Meta­da­ten ermög­licht unser Ansatz eine ein­fa­che Wie­der­ver­wend­bar­keit und Anpass­bar­keit von Pipe­lines, was die Ent­wick­lungs­auf­wände erheb­lich redu­ziert und gleich­zei­tig die Wart­bar­keit verbessert.

Die­ses Kon­zept beweist, dass mit einem gut durch­dach­ten Meta­da­ten­an­satz kom­plexe Daten­in­te­gra­ti­ons­pro­zesse nicht nur ver­ein­facht, son­dern auch ska­lier­bar und zukunfts­si­cher gemacht wer­den kön­nen. Unter­neh­men pro­fi­tie­ren von einer gestei­ger­ten Effi­zi­enz bei der Daten­ver­ar­bei­tung und legen damit den Grund­stein für Inno­va­tio­nen und die Anpas­sung an neue Technologien.

Kurz gesagt, das Meta­da­ten­kon­zept für meta­da­ten­ge­trie­bene Pipe­lines in Data Fac­tory ist ein Schlüs­sel­ele­ment für die Rea­li­sie­rung agi­ler und effi­zi­en­ter Daten­pipe­line-Pro­jekte, das die Tür zu einer opti­mier­ten Daten­ver­ar­bei­tung weit öffnet.