Introduktion
Det kom til at ske, at jeg på mit nuværende arbejdssted måtte blive bekendt med denne teknologi. Jeg vil starte med en lille baggrundshistorie. Ved et møde fik vores team at vide, at vi skulle skabe en integration med et kendt system. Integrationen betød, at dette kendte system ville sende os anmodninger via HTTP til en bestemt endpoint, og vi, mærkeligt nok, ville sende svar tilbage i form af et SOAP-besked. Det virker som om, det er enkelt og trivielt. Det følger, at vi skal...
Regler for godkendelse af merge-requests
Oprette 3 tjenester. Den første af dem er Databaseopdateringstjenesten. Denne tjeneste opdaterer data i databasen ved modtagelse af nye data fra det eksterne system og genererer en fil i CSV-format til overførsel til det næste system. Endpointet for den anden tjeneste — Transporttjeneste via FTP, aktiveres, som modtager den overførte fil, validerer den, og placerer den i filopbevaringen via FTP. Den tredje tjeneste — Dataoverførselstjenesten til forbrugeren, arbejder asynkront med de to første. Den modtager en anmodning fra et eksternt system om at få den fil, vi tidligere har nævnt, tager den færdige svarfil, modificerer den (opdaterer felterne id, description, linkToFile) og sender svaret i form af en SOAP-besked. Så den samlede situation er som følger: de første to tjenester begynder deres arbejde, når der kommer data til opdatering. Den tredje tjeneste arbejder konstant, da der er mange informationsforbrugere, omkring 1000 anmodninger om data pr. minut. Tjenesterne er tilgængelige konstant, og deres instanser er placeret i forskellige miljøer, såsom test, demo, preprod og prod. Nedenfor er der præsenteret et diagram over arbejdet for disse tjenester. Jeg vil straks forklare, at nogle detaljer er forenklet for at undgå unødig kompleksitet.

Teknisk forklaring
Når man planlægger at løse en opgave, besluttede man først at lave applikationer i Java med brug af Spring framework, en balanceringsløsning Nginx, en database Postgres og diverse tekniske og mindre tekniske ting. Da tiden til at arbejde på den tekniske løsning tillod at overveje andre tilgange til at løse denne opgave, faldt blikket på den populære teknologi Apache NIFI, som er kendt i bestemte kredse. Jeg vil straks sige, at denne teknologi gjorde det muligt for os at identificere disse 3 tjenester. Denne artikel vil beskrive udviklingen af en filtransporttjeneste og en dataoverførselstjeneste til modtageren. Men hvis artiklen vækker interesse, vil jeg skrive om tjenesten til opdatering af data i databasen.
Hvad er det?
NIFI repræsenterer en distribueret arkitektur til hurtig parallel loading og behandling af data, med et stort antal plugins til kilder og transformationer, versionskontrol for konfigurationer og meget mere. En behagelig bonus er, at det er meget nemt at bruge. Trivielle processer som getFile, sendHttpRequest og andre kan præsenteres som firkanter. Hver firkant repræsenterer en proces, hvis interaktion kan ses på billedet nedenfor. Mere detaljeret dokumentation om interaktioner og opsætning af processerne er skrevet , for dem der taler russisk — . I dokumentationen er det fremragende beskrevet, hvordan man pakker ud og kører NIFI samt hvordan man opretter processer, som også er firkanter.
Idéen om at skrive en artikel opstod efter langvarige søgninger og strukturering af den indsamlede information i noget meningsfuldt, samt ønsket om at lette livet for fremtidige udviklere.
Eksempel
Et eksempel på, hvordan kvadrater interagerer med hinanden er blevet gennemgået. Den overordnede skema er ganske enkelt: Vi modtager en HTTP-anmodning (teoretisk set med en fil i anmodningens krop. For at demonstrere NIFIs muligheder starter anmodningen i dette eksempel processen med at hente en fil fra det lokale filsystem), hvorefter vi sender et svar tilbage om, at anmodningen er modtaget; samtidig startes processen med at hente filen fra filsystemet og derefter flytning af den via FTP til filsystemet. Det skal bemærkes, at processerne interagerer med hinanden via såkaldte flowFiles. Dette er en grundlæggende enhed i NIFI, der gemmer attributterne og indholdet. Indholdet er de data, der præsenteres som en streamfil. Med andre ord, hvis du har fået en fil fra et kvadrat og overfører den til et andet, vil indholdet være din fil.

Som du kan se, viser dette billede den generelle proces. HandleHttpRequest modtager anmodninger, ReplaceText genererer indholdet af svaret, HandleHttpResponse giver svaret videre. FetchFile henter en fil fra filopbevaringen og sender den til kvadratet PutSftp, som lægger denne fil på FTP til den angivne adresse. Lad os besigtige denne proces nærmere.
I dette tilfælde er anmodningen alt. Lad os se på dens konfigurationsparametre.

Her er alt ret trivielt, bortset fra StandartHttpContextMap - dette er en slags service, der gør det muligt at sende og modtage anmodninger. Du kan se mere detaljeret og endda med eksempler -
Vi ser nu på konfigurationsparametrene for ReplaceText-kvadratet. Her skal vi være opmærksomme på ReplacementValue - det er det, der vil blive returneret til brugeren som svar. I indstillingerne kan niveauet for logføring reguleres, og logfiler kan ses {hvor vi har pakket nifi}/nifi-1.9.2/logs; her er der også parametre for failure/success - baseret på disse parametre kan vi regulere processen som helhed. Det vil sige, i tilfælde af vellykket behandling af teksten, vil processen til at sende et svar til brugeren blive kaldt, mens i et andet tilfælde vil vi blot logge den mislykkede proces.

Der er ikke rigtig noget interessant i egenskaberne for HandleHttpResponse undtagen status ved vellykket oprettelse af svaret.

Vi har nu set på anmodningen og svaret - lad os gå videre til at hente filen og placere den på FTP-serveren. FetchFile henter filen fra den angivne sti i indstillingerne og sender den videre til den næste proces.

Og derefter placerer kvadratet PutSftp filen i filopbevaringen. Konfigurationsparametrene kan ses nedenfor.

Det er værd at bemærke, at hver kvadrat er en separat proces, der skal startes. Vi har gennemgået det simpleste eksempel, som ikke kræver nogen kompleks tilpasning. Lad os nu se på en lidt mere kompleks proces, hvor vi skriver lidt i groovy.
Et mere komplekst eksempel
Dataoverførselstjenesten til forbrugeren blev lidt mere kompleks på grund af SOAP-beskedmodifikationsprocessen. Den overordnede proces er præsenteret på tegningen nedenfor.

Her er ideen heller ikke særlig kompleks: vi modtog en anmodning fra forbrugeren om, at han har brug for data, sendte et svar om, at vi har modtaget beskeden, startede processen med at hente svarfilen, redigerede den derefter med en bestemt logik, og til sidst sendte vi filen til forbrugeren som en SOAP-besked til serveren.
Jeg mener, at det ikke er nødvendigt at beskrive de kvadrater, vi har set ovenfor igen - lad os straks gå videre til nye. Hvis du skal redigere en fil, og de almindelige kvadrater som ReplaceText ikke er egnede, skal du skrive dit eget script. Dette kan gøres ved hjælp af kvadratet ExecuteGroogyScript. Dens indstillinger præsenteres nedenfor.

Der er to måder at indlæse scriptet i denne firkant på. Den første er ved at uploade en fil med scriptet. Den anden er ved at indsætte scriptet i scriptBody. Så vidt jeg ved understøtter firkanten executeScript flere programmeringssprog — et af dem er groovy. Jeg må skuffe Java-udviklere — det er ikke muligt at skrive scripts i sådanne firkanter med Java. For dem, der virkelig ønsker det — skal man oprette sin egen brugerdefinerede firkant og tilføje den til NIFI-systemet. Hele denne proces involverer ret langvarige forberedelser, som vi ikke vil beskæftige os med i denne artikel. Jeg har valgt sproget groovy. Nedenfor præsenteres et testscript, der blot opdaterer id'et inkrementelt i SOAP-beskeden. Det er vigtigt at bemærke, at man tager filen fra flowFile, opdaterer den, og husker at lægge den tilbage, når den er opdateret. Det skal også bemærkes, at ikke alle biblioteker er tilgængelige. Det kan ske, at du alligevel skal importere et af bibliotekerne. En ulempe er også, at scriptet i denne firkant er ret svært at debugge. Der er en måde at tilslutte sig NIFI JVM'en og starte debug-processen. Personligt har jeg kørt en lokal applikation og simuleret modtagelsen af en fil fra en session. Jeg har også udført debugging lokalt. Fejlen, der opstår ved indlæsning af scriptet, er ret nemme at finde på Google og bliver registreret af NIFI i loggen.
import org.apache.commons.io.IOUtils
import groovy.xml.XmlUtil
import java.nio.charset.*
import groovy.xml.StreamingMarkupBuilder
def flowFile = session.get()
if (!flowFile) return
try {
flowFile = session.write(flowFile, { inputStream, outputStream ->
String result = IOUtils.toString(inputStream, "UTF-8");
def recordIn = new XmlSlurper().parseText(result)
def element = recordIn.depthFirst().find {
it.name() == 'id'
}
def newId = Integer.parseInt(element.toString()) + 1
def recordOut = new XmlSlurper().parseText(result)
recordOut.Body.ClientMessage.RequestMessage.RequestContent.content.MessagePrimaryContent.ResponseBody.id = newId
def res = new StreamingMarkupBuilder().bind { mkp.yield recordOut }.toString()
outputStream.write(res.getBytes(StandardCharsets.UTF_8))
} as StreamCallback)
session.transfer(flowFile, REL_SUCCESS)
}
catch(Exception e) {
log.error("Fejl under behandlingen af validate.groovy", e)
session.transfer(flowFile, REL_FAILURE)
}Faktisk slutter tilpasningen af firkanten her. Den opdaterede fil overføres til firkanten, der håndterer sendingen af filen til serveren. Nedenfor vises indstillingerne for denne firkant.

Vi beskriver metoden, hvormed SOAP-beskeden vil blive sendt. Vi angiver hvorhen. Derudover skal vi angive, at dette netop er SOAP.

Vi tilføjer nogle egenskaber som værtsadresse og handling (soapAction). Vi gemmer, kontrollerer. For mere om, hvordan man sender SOAP-anmodninger, kan du se her.
Vi har gennemgået flere måder at bruge NIFI-processerne på. Hvordan de interagerer, og hvilken reel nytte de har. De nævnte eksempler er testeksempler og adskiller sig lidt fra det, der faktisk bruges i produktion. Jeg håber, at denne artikel vil være til lidt hjælp for udviklere. Tak for opmærksomheden. Hvis der er nogle spørgsmål, så skriv. Jeg vil gøre mit bedste for at svare.
Kilde: habr.com
