Tech Talk: Oplossingen voor intensieve werkbelasting bouwen met Azure's functie-app, verwachtingen en beperkingen
Bedrijven kiezen steeds vaker voor cloudservices vanwege het gebruiksgemak en de flexibele kosten. U kunt het platform, de infrastructuur of zelfs de runtime van de omgeving eenvoudig delegeren aan uw cloudprovider. Al deze verschillende niveaus van services zijn populairder geworden en staan bekend als PaaS, IaaS en FaaS.
Bedrijven kunnen zich nu richten op hun bedrijfslogica zonder dat ze een sterke IT-capaciteit hoeven op te bouwen en te beheren. Dit geldt vooral voor startups die met behulp van hun cloudprovider snel de markt op kunnen.
Hier op Agilytic testen en implementeren we graag proof-of-concept met nieuwe opkomende technologieën om de kosten voor het technisch beheer van veel aspecten van een project te verlagen. Dit artikel laat een experiment zien dat we hebben uitgevoerd in ons Azure lab met Azure Function App. We hebben geprobeerd een intensieve werklastapplicatie te implementeren met behulp van nieuwe beheerde cloudservices om het technisch beheer tot een maximum te beperken. Het doel was om de technische beperking in termen van functies en schaalbaarheid en de kosten in vergelijking met andere klassieke cloudimplementaties te observeren.
In ons lab zal ik je een intensieve werkbelastingstoepassing laten zien die PDF-documenten analyseert. De analyse bestaat uit vier verschillende stappen over een aantal geavanceerde verwerkingen van optische tekenherkenning tot tekstclassificatie. Op een enkele vCPU hebben we geschat dat de verwerkingstijd gemiddeld 1 minuut duurt voor de vier stappen.
De architectuur van de Azure Function App
In een IaaS-systeem zou het eerste idee zijn om virtuele machines en processen te spawnen om het eigenlijke werk uit te voeren. We kunnen de oplossing uitbreiden door meer VM's en processen te spawnen. De belangrijkste nadelen hiervan zijn het systeembeheer en de administratieve overhead. We moeten het besturingssysteem, updates, enzovoort beheren. We moeten ook de architectuur van de applicatie beheren en de workflow synchroniseren, vooral als deze gedistribueerd is.
Het idee was om te experimenteren met het ontwikkelen van zo'n applicatie bovenop Platform as a service (PaaS) in plaats van Infrastructure as a service (IaaS). Door gebruik te maken van de Azure Function App gaan we zelfs verder dan wat we een Function as a service (FaaS) noemen. In een dergelijke FaaS wordt de beheeroverhead tot een maximum beperkt omdat we noch het platform, noch de applicatiearchitectuur hoeven te beheren. We kunnen ons concentreren op dat deel van de code dat directe bedrijfswaarde biedt, terwijl we het beheer en de potentiële kosten minimaliseren. De keuze voor een dergelijke oplossing heeft ook nadelen zoals vendor lock-in. Het experiment hier richt zich op het voordeel en de toegevoegde waarde vanuit een technisch perspectief in plaats van zakelijke voorkeuren.
We hebben besloten om voor de Azure Function App te kiezen, waarbij elke App Function instance één verwerkingsstap implementeert. Azure Service Bus Queue voert de communicatie tussen de stappen uit. Op deze manier hebben we geen beheeroverhead. Een blob storage slaat alle documenten op.
De workflow gaat in volgorde van de ene fase naar de andere door gebruik te maken van uitgewisselde berichten via de Azure Service Bus Queue, waardoor de belasting tussen de Function Apps wordt verdeeld. Omdat de Function Apps stateless zijn, kun je ze eenvoudig verwerken, distribueren en schalen. Als bijvoorbeeld een fase klaar is met het uitvoeren van een taak, wordt er een bericht via de Service Bus naar de volgende fase gestuurd om de verwerking voort te zetten.
De architectuur van Azure bestaat uit:
Functie App - Onze code uitvoeren.
Service Bus Queue - Workflow sequentieel doorgeven van de ene stap naar de andere.
DataLake opslag - Om resultaten op te slaan.
Blobopslag - Om documenten op te slaan.
De verschillende stadia zijn:
Dispatcher - Een zeer lichte component die de verschillende taken genereert die moeten worden uitgevoerd.
Zoeken & downloaden - Zoek en download documenten die zijn opgeslagen in de Azure blob storage voor verwerking.
Tekst extraheren - Combinatie van Postscript-interpretatie en Optische tekenherkenning om tekstgegevens uit de PDF te extraheren.
NLP - Natuurlijke taalverwerking voor tekstclassificatie uit de geëxtraheerde tekst.
De code achter de Azure Function App
Elke stap is verantwoordelijk voor één specifieke taak. Dankzij de Azure Service Bus Queue kunnen we een At-Least-Once leveringsgarantie out of the box bereiken zonder extra inspanning. Op deze manier zorgen we ervoor dat we geen executies kwijtraken in geval van storing. Met de Azure Function App kun je je bedrijfslogica implementeren zonder directe interactie met de Service Bus Queue. De Azure Function App verpakt je bedrijfslogica in zijn eigen consumer-producer patroon. Door deze manier van werken kunnen we ons richten op de bedrijfslogica zonder te worstelen met integratieproblemen. Azure onderhoudt en ondersteunt alles behalve onze bedrijfslogica. Dit is eigenlijk het belangrijkste voordeel van het gebruik van FaaS boven PaaS.
De configuratie van de Azure Function App is eenvoudig. Je moet het type invoer en uitvoer opgeven, de naam van de wachtrijen en de naam van de omgevingsvariabele die de verbindingsstring bevat om een veilige verbinding te maken met de Service Bus. Afhankelijk van het type invoer en uitvoer kunnen andere parameters nodig zijn.
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "msgIn",
"type": "serviceBusTrigger",
"direction": "in",
"queueName": "inputqueue",
"connection": "InputBusQueueConnectionString"
},
{
"name": "msgOut",
"type": "serviceBus",
"direction": "out",
"queueName": "outputqueue",
"connection": "OutputBusQueueConnectionString",
}
]
}import json
import business
import azure.functions as func
def main(msgIn: func.ServiceBusMessage, msgOut: func.Out[str]):
input_data = json.loads(msgIn.get_body())
output_data = business.process(input_data)
msgOut.set(json.dumps(output_data))
Zo eenvoudig is het. Onze business logic code zal overdraagbaar zijn omdat het onafhankelijk blijft van de rest van de code. De implementatie van deze hoofdfunctie stelt ons in staat om een voorkeurs serialisatiemethode te kiezen. Later zijn we vrij om onze architectuur te veranderen en de Azure Function App te vervangen door een andere service zonder onze business logica opnieuw te implementeren of te heractualiseren.
Deze architectuur is vergelijkbaar met wat Apache Storm kan bieden.
De voordelen
Deze architectuur biedt meerdere voordelen:
Real-time resultaten. Elk document wordt zo snel mogelijk verwerkt zonder extra technische kosten.
De algemene architectuur is fouttolerant en consistent. Als een enkele Function App crasht, gaat de rest van de verwerking onafhankelijk verder. De gecrashte verwerkingsstap zal ook opnieuw worden geprobeerd dankzij de Azure Service Bus Queue en Peek-lock modus. Het opnieuw proberen zal beperkt blijven tot de mislukte stap, niet over alle stappen.
De architectuur is volledig schaalbaar op een fijnkorrelig niveau. We zouden een specifieke stap kunnen uitschalen als dat de bottleneck is. We zullen later zien dat deze schaalbaarheid enkele beperkingen heeft.
Er is absoluut geen beheeroverhead. Zowel de Azure Function App als de Azure Service Bus Queue zijn volledig beheerde services.
De beperkingen
De architectuur biedt een groot voordeel op het gebied van schaalbaarheid, zoals we hebben gezien. De schaalbaarheid van de Azure Function App heeft echter enkele beperkingen. Verschillende serviceplannen staan toe om app functies verticaal te schalen tot 4 cores. Dit kan ons proces met een factor vier versnellen als we besluiten om een multi-threading Azure Function App te beheren. Helaas kunnen we niet hoger gaan dan vier cores per functie-instantie in het premium serviceplan.
De initiële architectuur die hier is gepresenteerd kan gemakkelijk worden opgeschaald vanwege de stateloze aard en het gebruik van de Service Bus Queue. Er is echter ook een horizontale limiet op hoeveel we een functie-app horizontaal kunnen schalen. We kunnen een enkele Function App namelijk alleen schalen tot 100 instanties in het Premium serviceplan of 200 instanties in het Consumption plan. Dit geeft ons een maximum van (100 × 4) 400 vCPU's per fase in onze verwerking.
Ervan uitgaande dat één document 1 minuut nodig heeft om alle stappen opeenvolgend te doorlopen, is het maximum dat we kunnen bereiken 400 documenten per minuut of 6,66/s.
De kosten
Als we aannemen dat we minstens 6,66 documenten per seconde willen verwerken, hebben we 100 instances met 4 vCPU's nodig in het premium serviceplan.
Op dit moment zou een dergelijke opstelling maandelijkse kosten van ongeveer $185.759,74 met zich meebrengen. Ter vergelijking: een alternatief waarbij alleen VM's worden gebruikt, zou slechts $31.220,69 per maand kosten.
Conclusie
Ondanks het feit dat deze architectuur veel interessante voordelen biedt, kunnen we het financiële aspect niet verwaarlozen. We zouden zeker niet aanraden om een dergelijke architectuur te gebruiken voor intensieve werkbelasting, voornamelijk vanwege de schaalbaarheidsbeperkingen en de kosten. De Azure Function App is in eerste instantie gericht op de ontwikkeling van een eenvoudig API-eindpunt dat de rest van de Azure-infrastructuur bedient. Dit past natuurlijk niet bij de use case die hier wordt gepresenteerd.
De Azure Function App is nog steeds goed en zou geschikt zijn voor een event-gebaseerde functie die niet gericht is op een intensieve hoeveelheid berekeningen per seconde. De hier gepresenteerde architectuur is nog steeds zinvol en zou beter geïmplementeerd kunnen worden met andere componenten zoals Azure Container Instance. Voor het specifieke doel van dit artikel denken we dat de Azure batch zeker een veel betere keuze zou zijn.