Delen via


Ontwerp van Resilient Event Hubs en Functions

Foutafhandeling, ontwerpen voor idempotentie en het beheren van gedrag voor opnieuw proberen zijn enkele van de kritieke maatregelen die u kunt nemen om ervoor te zorgen dat door Event Hubs geactiveerde functies tolerant zijn en grote hoeveelheden gegevens kunnen verwerken. In dit artikel worden deze cruciale concepten behandeld en worden aanbevelingen voor serverloze oplossingen voor gebeurtenisstreaming uitgevoerd.

Azure biedt drie belangrijke berichtenservices die kunnen worden gebruikt met Azure Functions ter ondersteuning van een breed scala aan unieke, gebeurtenisgestuurde scenario's. Vanwege het gepartitioneerde consumentenmodel en de mogelijkheid om gegevens met een hoge snelheid op te nemen, wordt Azure Event Hubs vaak gebruikt voor scenario's voor gebeurtenisstreaming en big data. Zie Kiezen tussen Azure Messaging-services - Event Grid, Event Hubs en Service Bus voor een gedetailleerde vergelijking van Azure-berichtenservices.

Streamingvoordelen en uitdagingen

Als u de voordelen en nadelen van streams begrijpt, kunt u waarderen hoe een service zoals Event Hubs werkt. U hebt deze context ook nodig bij het nemen van impactvolle beslissingen over de architectuur, het oplossen van problemen en het optimaliseren van prestaties. Houd rekening met de volgende belangrijke concepten over oplossingen met zowel Event Hubs als Functions:

  • Streams zijn geen wachtrijen: Event Hubs, Kafka en andere vergelijkbare aanbiedingen die zijn gebouwd op het gepartitioneerde consumentenmodel ondersteunen geen enkele van de belangrijkste functies in een berichtenbroker zoals Service Bus. Misschien is de grootste indicator van deze verschillen het feit dat leesbewerkingen niet-destructief zijn. Dit zorgt ervoor dat de gegevens die door de Functions-host worden gelezen, later beschikbaar blijven. In plaats daarvan zijn berichten onveranderbaar en blijven andere consumenten lezen, inclusief mogelijk dezelfde consument die het opnieuw leest. Daarom kunnen oplossingen die patronen implementeren, zoals concurrerende consumenten , beter worden bediend met een berichtenbroker zoals Service Bus.

  • Er ontbreekt inherente ondersteuning voor dode letters: een kanaal met dode letters is geen systeemeigen functie in Event Hubs of Kafka. Vaak is het concept van dead-lettering geïntegreerd in een streamingoplossing om rekening te houden met gegevens die niet kunnen worden verwerkt. Deze functionaliteit is opzettelijk geen innate element in Event Hubs en wordt alleen toegevoegd aan de consumentenzijde om een vergelijkbaar gedrag of effect te produceren. Als u ondersteuning voor dead-letter nodig hebt, moet u mogelijk uw keuze voor een streamingberichtservice bekijken.

  • Een werkeenheid is een partitie: In een traditionele berichtenbroker is een werkeenheid één bericht. In een streamingoplossing wordt een partitie vaak beschouwd als de werkeenheid. Als elke gebeurtenis in een Event Hub wordt behandeld als een afzonderlijk bericht waarvoor orderverwerking of financiële transactieafhandeling is vereist, wordt een kans voorgesteld om een meer geschikte berichtenservice te verkennen voor optimale prestaties of verwerking.

  • Geen filters aan de serverzijde: Een van de redenen waarom Event Hubs in staat is om enorme schaal te kunnen schalen en de doorvoer is te wijten aan de lage overhead van de service zelf. Functies zoals filteren aan de serverzijde, indexen en coördinatie tussen brokers maken geen deel uit van de architectuur van Event Hubs. Functies worden af en toe gebruikt om gebeurtenissen te filteren door ze te routeren naar andere Event Hubs op basis van de inhoud in de hoofdtekst of header. Deze benadering is gebruikelijk bij het streamen van gebeurtenissen, maar wordt geleverd met het voorbehoud dat de initiële functie elke gebeurtenis leest en evalueert.

  • Elke lezer moet alle gegevens lezen: omdat filteren aan de serverzijde niet beschikbaar is, leest een consument alle gegevens in een partitie sequentieel. Dit omvat gegevens die mogelijk niet relevant zijn of zelfs ongeldig kunnen zijn. Er kunnen verschillende opties en strategieën worden gebruikt om deze uitdagingen te compenseren, die verderop in deze sectie worden behandeld.

Deze belangrijke ontwerpbeslissingen stellen Event Hubs in staat om te doen wat het beste doet: ondersteuning bieden voor een aanzienlijke toestroom van gebeurtenissen en bieden een robuuste en tolerante service voor consumenten om van te lezen. Elke consumententoepassing wordt belast met de verantwoordelijkheid voor het onderhouden van hun eigen offsets aan de clientzijde of cursor voor deze gebeurtenissen. De lage overhead maakt Event Hubs een betaalbare en krachtige optie voor gebeurtenisstreaming.

Idempotentie

Een van de kernten van Azure Event Hubs is het concept van ten minste één levering. Deze aanpak zorgt ervoor dat gebeurtenissen altijd worden afgeleverd. Het betekent ook dat gebeurtenissen meer dan één keer, zelfs herhaaldelijk, kunnen worden ontvangen door consumenten zoals een functie. Daarom is het belangrijk dat een door event hub geactiveerde functie het idempotente consumentenpatroon ondersteunt.

Werken onder de veronderstelling van ten minste één levering, met name binnen de context van een gebeurtenisgestuurde architectuur, is een verantwoorde benadering voor het betrouwbaar verwerken van gebeurtenissen. Uw functie moet idempotent zijn, zodat het resultaat van het verwerken van dezelfde gebeurtenis meerdere keren hetzelfde is als het één keer verwerken.

Dubbele gebeurtenissen

Er zijn verschillende scenario's die ertoe kunnen leiden dat dubbele gebeurtenissen aan een functie worden geleverd:

  • Controlepunten: als de Azure Functions-host vastloopt of de drempelwaarde die is ingesteld voor de frequentie van het batchcontrolepunt niet wordt voldaan, wordt er geen controlepunt gemaakt. Als gevolg hiervan is de offset voor de consument niet geavanceerd en de volgende keer dat de functie wordt aangeroepen, wordt deze hervat vanaf het laatste controlepunt. Het is belangrijk om te weten dat controlepunten plaatsvinden op partitieniveau voor elke consument.

  • Dubbele gebeurtenissen gepubliceerd: veel technieken kunnen de kans verminderen dat dezelfde gebeurtenis naar een stream wordt gepubliceerd, maar de consument is nog steeds verantwoordelijk voor het afhandelen van duplicaten idempotent.

  • Ontbrekende bevestigingen: in sommige situaties kan een uitgaande aanvraag voor een service zijn geslaagd, maar een bevestiging (ACK) van de service wordt nooit ontvangen. Deze perceptie kan ertoe leiden dat de uitgaande aanroep is mislukt en een reeks nieuwe pogingen of andere resultaten van de functie initieert. Uiteindelijk kunnen dubbele gebeurtenissen worden gepubliceerd of wordt er geen controlepunt gemaakt.

Ontdubbelingstechnieken

Het ontwerpen van uw functies voor identieke invoer moet de standaardbenadering zijn wanneer deze is gekoppeld aan de Event Hub-triggerbinding. Houd rekening met de volgende technieken:

  • Zoeken naar duplicaten: voordat u deze verwerkt, moet u de benodigde stappen uitvoeren om te valideren dat de gebeurtenis moet worden verwerkt. In sommige gevallen is hiervoor een onderzoek vereist om te bevestigen dat het nog geldig is. Het kan ook mogelijk zijn dat het verwerken van de gebeurtenis niet meer nodig is vanwege de nieuwheid van gegevens of logica die de gebeurtenis ongeldig maakt.

  • Ontwerp gebeurtenissen voor idempotentie: Door aanvullende informatie op te geven binnen de nettolading van de gebeurtenis, is het mogelijk om ervoor te zorgen dat de verwerking ervan meerdere keren geen nadelige gevolgen heeft. Neem het voorbeeld van een gebeurtenis die een bedrag bevat dat moet worden uitgetrokken van een bankrekening. Als het niet op verantwoorde wijze wordt afgehandeld, is het mogelijk dat het saldo van een rekening meerdere keren wordt afgebroken. Als dezelfde gebeurtenis echter het bijgewerkte saldo op de rekening bevat, kan het worden gebruikt om een upsert-bewerking uit te voeren op het bankrekeningsaldo. Deze aanpak voor overdracht van gebeurtenissen vereist af en toe coördinatie tussen producenten en consumenten en moet worden gebruikt wanneer het zinvol is voor deelnemende diensten.

Foutafhandeling en nieuwe pogingen

Foutafhandeling en nieuwe pogingen zijn een paar van de belangrijkste kwaliteiten van gedistribueerde, gebeurtenisgestuurde toepassingen en Functies zijn geen uitzondering. Voor oplossingen voor gebeurtenisstreaming is de noodzaak van de juiste ondersteuning voor foutafhandeling cruciaal, omdat duizenden gebeurtenissen snel kunnen worden omgezet in een gelijk aantal fouten als ze niet correct worden verwerkt.

Richtlijnen voor foutafhandeling

Zonder foutafhandeling kan het lastig zijn om nieuwe pogingen te implementeren, runtime-uitzonderingen te detecteren en problemen te onderzoeken. Elke functie moet ten minste een bepaald niveau of foutafhandeling hebben. Enkele aanbevolen richtlijnen zijn:

  • Application Insights gebruiken: Application Insights inschakelen en gebruiken om fouten te registreren en de status van uw functies te bewaken. Houd rekening met de configureerbare samplingopties voor scenario's die een groot aantal gebeurtenissen verwerken.

  • Voeg gestructureerde foutafhandeling toe: Pas de juiste constructies voor foutafhandeling toe voor elke programmeertaal om verwachte en niet-verwerkte uitzonderingen in uw functiecode vast te leggen, te registreren en te detecteren. Gebruik bijvoorbeeld een try/catch-blok in C#, Java en JavaScript en profiteer van de poging en behalve blokken in Python om uitzonderingen af te handelen.

  • Logboekregistratie: Het vangen van een uitzondering tijdens de uitvoering biedt een mogelijkheid om kritieke informatie te registreren die kan worden gebruikt om problemen betrouwbaar te detecteren, reproduceren en op te lossen. Registreer de uitzondering, niet alleen het bericht, maar de hoofdtekst, interne uitzondering en andere nuttige artefacten die later nuttig zijn.

  • Uitzonderingen niet ondervangen en negeren: een van de slechtste dingen die u kunt doen, is een uitzondering ondervangen en er niets mee doen. Als u een algemene uitzondering onderscheppen, moet u deze ergens registreren. Als u geen fouten vastlegt, is het lastig om fouten te onderzoeken en problemen te melden.

Nieuwe pogingen

Het implementeren van logica voor opnieuw proberen in een gebeurtenisstreamingarchitectuur kan complex zijn. Het ondersteunen van annuleringstokens, tellingen van nieuwe pogingen en exponentieel uitstelstrategieën zijn slechts een paar van de overwegingen die het lastig maken. Gelukkig biedt Functions beleid voor opnieuw proberen dat kan bestaan uit veel van deze taken die u doorgaans zelf codeert.

Enkele belangrijke factoren die moeten worden overwogen bij het gebruik van het beleid voor opnieuw proberen met de Event Hub-binding, zijn onder andere:

  • Vermijd onbeperkte nieuwe pogingen: wanneer de instelling voor het maximum aantal nieuwe pogingen is ingesteld op -1, wordt de functie voor onbepaalde tijd opnieuw geprobeerd. Over het algemeen moeten onbeperkte nieuwe pogingen spaarzaam worden gebruikt met Functions en bijna nooit met de Event Hub-triggerbinding.

  • Kies de juiste strategie voor opnieuw proberen: een strategie voor vaste vertraging kan optimaal zijn voor scenario's die terugdruk van andere Azure-services ontvangen. In deze gevallen kan de vertraging helpen om beperking en andere beperkingen van deze services te voorkomen. De strategie voor exponentieel uitstel biedt meer flexibiliteit voor vertragingsintervallen voor opnieuw proberen en wordt vaak gebruikt bij het integreren met services van derden, REST-eindpunten en andere Azure-services.

  • Houd intervallen en aantallen nieuwe pogingen laag: probeer, indien mogelijk, een interval voor opnieuw proberen korter dan één minuut te behouden. Houd ook het maximum aantal nieuwe pogingen tot een redelijk laag getal. Deze instellingen zijn met name relevant wanneer ze worden uitgevoerd in het Functions Consumption-abonnement.

  • Patroon circuitonderbreker: een tijdelijke foutfout van tijd tot tijd wordt verwacht en een natuurlijke use-case voor nieuwe pogingen. Als er echter een aanzienlijk aantal fouten of problemen optreedt tijdens de verwerking van de functie, kan het zinvol zijn om de functie te stoppen, de problemen op te lossen en later opnieuw op te starten.

Een belangrijk aandachtspunt voor het beleid voor opnieuw proberen in Functions is dat het een best effort-functie is voor het opnieuw verwerken van gebeurtenissen. Het vervangt niet de noodzaak voor foutafhandeling, logboekregistratie en andere belangrijke patronen die tolerantie bieden voor uw code.

Strategieën voor fouten en beschadigde gegevens

Er zijn verschillende opmerkelijke benaderingen die u kunt gebruiken om te compenseren voor problemen die optreden als gevolg van fouten of slechte gegevens in een gebeurtenisstroom. Enkele fundamentele strategieën zijn:

  • Stoppen met verzenden en lezen: als u het onderliggende probleem wilt oplossen, pauzeert u het lezen en schrijven van gebeurtenissen. Het voordeel van deze aanpak is dat gegevens niet verloren gaan en bewerkingen kunnen worden hervat nadat een oplossing is geïmplementeerd. Voor deze benadering is mogelijk een circuitonderbrekeronderdeel in de architectuur vereist en mogelijk een melding voor de betreffende services om een onderbreking te bereiken. In sommige gevallen kan het stoppen van een functie nodig zijn totdat de problemen zijn opgelost.

  • Berichten verwijderen: Als berichten niet belangrijk zijn of als niet-bedrijfskritiek worden beschouwd, kunt u overwegen om door te gaan en deze niet te verwerken. Deze aanpak werkt niet voor scenario's waarvoor een sterke consistentie is vereist, zoals het opnemen van bewegingen in een schaakwedstrijd of financiële transacties. Foutafhandeling binnen een functie wordt aanbevolen voor het vangen en verwijderen van berichten die niet kunnen worden verwerkt.

  • Opnieuw proberen: er zijn veel situaties waarin het opnieuw verwerken van een gebeurtenis kan worden gerechtvaardigd. Het meest voorkomende scenario is een tijdelijke fout die optreedt bij het aanroepen van een andere service of afhankelijkheid. Netwerkfouten, servicelimieten en beschikbaarheid en sterke consistentie zijn mogelijk de meest voorkomende gebruiksvoorbeelden die het opnieuw verwerken van pogingen rechtvaardigen.

  • Dode letter: Het idee hier is om de gebeurtenis te publiceren naar een andere Event Hub, zodat de bestaande stroom niet wordt onderbroken. De perceptie is dat het van hete pad wordt verplaatst en later of door een ander proces kan worden behandeld. Deze oplossing wordt vaak gebruikt voor het verwerken van vergiftigde berichten of gebeurtenissen. Elke functie die is geconfigureerd met een andere consumentengroep, ondervindt nog steeds slechte of beschadigde gegevens in hun stream en moet deze op verantwoorde wijze afhandelen.

  • Nieuwe poging en dode letter: De combinatie van talloze nieuwe pogingen voordat uiteindelijk wordt gepubliceerd naar een dode letterstream zodra aan een drempelwaarde is voldaan, is een andere bekende methode.

  • Een schemaregister gebruiken: een schemaregister kan worden gebruikt als een proactief hulpprogramma om consistentie en gegevenskwaliteit te verbeteren. Het Azure Schema Registry kan de overgang van schema's ondersteunen, samen met versiebeheer en verschillende compatibiliteitsmodi naarmate schema's zich ontwikkelen. Het schema fungeert als een contract tussen producenten en consumenten, waardoor de kans op ongeldige of beschadigde gegevens die naar de stream worden gepubliceerd, kan worden verminderd.

Uiteindelijk is er geen perfecte oplossing en moeten de gevolgen en compromissen van elk van de strategieën grondig worden onderzocht. Op basis van de vereisten kan het gebruik van verschillende van deze technieken samen de beste aanpak zijn.

Medewerkers

Dit artikel wordt onderhouden door Microsoft. De tekst is oorspronkelijk geschreven door de volgende Inzenders.

Hoofdauteur:

Als u niet-openbare LinkedIn-profielen wilt zien, meldt u zich aan bij LinkedIn.

Volgende stappen

Voordat u verdergaat, kunt u de volgende gerelateerde artikelen bekijken: