Delen via


De prestaties en betrouwbaarheid van Azure Functions verbeteren

Dit artikel bevat richtlijnen voor het verbeteren van de prestaties en betrouwbaarheid van uw serverloze functie-apps. Zie best practices voor Azure Functions voor een meer algemene set best practices voor Azure Functions.

Hier volgen de aanbevolen procedures voor het bouwen en ontwerpen van serverloze oplossingen met behulp van Azure Functions.

Vermijd langlopende functies

Grote, langlopende functies kunnen onverwachte time-outproblemen veroorzaken. Voor meer informatie over de time-out voor een bepaald hostingabonnement, zie time-outduur van de functie-app.

Een functie kan groot worden vanwege veel Node.js afhankelijkheden. Het importeren van afhankelijkheden kan ook leiden tot hogere laadtijden die leiden tot onverwachte time-outs. Afhankelijkheden worden zowel expliciet als impliciet geladen. Een enkele module die door uw code wordt geladen, kan een eigen extra module laden.

Herstructureer zo mogelijk grote functies in kleinere functiesets die samenwerken en antwoorden snel retourneren. Een webhook- of HTTP-triggerfunctie kan bijvoorbeeld een bevestigingsreactie binnen een bepaalde tijdslimiet vereisen; Het is gebruikelijk dat webhooks een onmiddellijke reactie vereisen. U kunt de payload van de HTTP-trigger doorgeven aan een wachtrij om dit te laten verwerken door een wachtrijtriggerfunctie. Met deze aanpak kunt u de werkelijke hoeveelheid werk uitstellen en een onmiddellijke reactie retourneren.

Controleren of achtergrondtaken zijn voltooid

Wanneer uw functie enige taken, callbacks, threads of processen start, moeten ze worden voltooid voordat uw functiecode eindigt. Omdat deze achtergrondthreads niet door Functions worden bijgehouden, kan het afsluiten van sites plaatsvinden, ongeacht de status van de achtergrondthread, wat onbedoeld gedrag in uw functies kan veroorzaken.

Als een functie bijvoorbeeld een achtergrondtaak start en een geslaagd antwoord retourneert voordat de taak is voltooid, beschouwt de Functions-runtime de uitvoering als voltooid, ongeacht het resultaat van de achtergrondtaak. Als deze achtergrondtaak essentiële werkzaamheden uitvoert, kan deze worden onderbroken door het afsluiten van de site, waardoor dat werk in een onbepaalde toestand blijft.

Communicatie tussen functies

Durable Functions en Azure Logic Apps zijn gebouwd om statusovergangen en communicatie tussen meerdere functies te beheren.

Als u Durable Functions of Logic Apps niet gebruikt om te integreren met meerdere functies, kunt u het beste opslagwachtrijen gebruiken voor communicatie tussen functies. De belangrijkste reden is dat opslagwachtrijen goedkoper en veel eenvoudiger kunnen worden ingericht dan andere opslagopties.

Afzonderlijke berichten in een opslagwachtrij zijn beperkt tot 64 kB. Als u grotere berichten tussen functies moet doorgeven, kan een Azure Service Bus-wachtrij worden gebruikt voor het ondersteunen van berichtgrootten tot 256 kB in de Standard-laag en maximaal 100 MB in de Premium-laag.

Service Bus-onderwerpen zijn handig als u berichtfiltering nodig hebt voordat u deze verwerkt.

Event Hubs zijn handig voor ondersteuning van communicatie met grote volumes.

Ontwikkel functies die stateless zijn

Functies moeten staatloos en idempotent zijn, indien mogelijk. Koppel alle vereiste statusgegevens aan uw gegevens. Een order die wordt verwerkt, heeft bijvoorbeeld waarschijnlijk een gekoppeld state lid. Een functie kan een volgorde verwerken op basis van die status, terwijl de functie zelf staatloos blijft.

Idempotente functies worden vooral aanbevolen bij gebruik met timer-triggers. Als u bijvoorbeeld iets hebt dat absoluut één keer per dag moet worden uitgevoerd, schrijft u het zodat het op elk gewenst moment tijdens de dag kan worden uitgevoerd met dezelfde resultaten. De functie kan afsluiten wanneer er geen werk is voor een bepaalde dag. Als een vorige uitvoering niet kon worden voltooid, zou de volgende uitvoering moeten doorgaan vanaf het punt waar het was gebleven. Dit is met name belangrijk voor op berichten gebaseerde bindingen die opnieuw proberen bij fouten. Zie Azure Functions ontwerpen voor identieke invoer voor meer informatie.

Defensieve functies schrijven

Stel dat uw functie op elk gewenst moment een uitzondering kan tegenkomen. Ontwerp uw functies met de mogelijkheid om door te gaan vanaf een eerder failpunt tijdens de volgende uitvoering. Overweeg een scenario waarvoor de volgende acties zijn vereist:

  1. Query's uitvoeren op 10.000 rijen in een database.
  2. Maak voor elk van deze rijen een wachtrijbericht om verderop in het proces te verwerken.

Afhankelijk van hoe complex uw systeem is, hebt u mogelijk: betrokken downstreamservices gedragen zich slecht, netwerkstoringen of quotumlimieten bereikt, enzovoort. Al deze kunnen op elk gewenst moment van invloed zijn op uw functie. U moet uw functies ontwerpen om ervoor te worden voorbereid.

Hoe reageert uw code als er een fout optreedt na het invoegen van 5000 items in een wachtrij voor verwerking? Items bijhouden in een set die u hebt voltooid. Anders kunt u ze de volgende keer opnieuw invoegen. Deze dubbele invoeging kan een ernstige invloed hebben op uw werkstroom, dus zorg ervoor dat uw functies idempotent zijn.

Als een wachtrijitem al is verwerkt, kunt u uw functie als een no-opgebruiken.

Profiteer van defensieve maatregelen die al beschikbaar zijn voor onderdelen die u gebruikt in het Azure Functions-platform. Zie Bijvoorbeeld Het verwerken van gifwachtrijberichten in de documentatie voor Azure Storage Queue-triggers en -bindingen.

Voor HTTP-functies kunt u strategieën voor API-versiebeheer overwegen met Azure API Management. Als u bijvoorbeeld uw op HTTP gebaseerde functie-app moet bijwerken, implementeert u de nieuwe update in een afzonderlijke functie-app en gebruikt u API Management-revisies of -versies om clients naar de nieuwe versie of revisie te leiden. Zodra alle clients de versie of revisie gebruiken en er geen uitvoeringen meer worden uitgevoerd in de vorige functie-app, kunt u de inrichting van de vorige functie-app ongedaan maken.

Best practices voor functie-organisatie

Als onderdeel van uw oplossing kunt u meerdere functies ontwikkelen en publiceren. Deze functies worden vaak gecombineerd tot één functie-app, maar ze kunnen ook worden uitgevoerd in afzonderlijke functie-apps. In Premium- en dedicated (App Service) hostingabonnementen kunnen meerdere functie-apps ook dezelfde resources delen door binnen hetzelfde abonnement te draaien. Hoe u uw functies en functie-apps groeperen, kan van invloed zijn op de prestaties, schaalaanpassing, configuratie, implementatie en beveiliging van uw algehele oplossing. Er zijn geen regels die van toepassing zijn op elk scenario, dus houd rekening met de informatie in deze sectie bij het plannen en ontwikkelen van uw functies.

Functies organiseren voor prestaties en schaalbaarheid

Elke functie die u maakt, heeft een geheugenvoetafdruk. Hoewel deze footprint meestal klein is, kan het hebben van te veel functies binnen een functie-app ertoe leiden dat uw app langzamer wordt opgestart op nieuwe exemplaren. Dit betekent ook dat het totale geheugengebruik van uw functie-app mogelijk hoger is. Het is moeilijk te zeggen hoeveel functies in één app moeten zijn, wat afhankelijk is van uw specifieke workload. Als uw functie echter veel gegevens in het geheugen opslaat, kunt u overwegen om minder functies in één app te hebben.

Als u meerdere functie-apps uitvoert in één Premium-abonnement of toegewezen (App Service)-abonnement, delen deze apps allemaal dezelfde resources die aan het plan zijn toegewezen. Als u één functie-app hebt met een veel hogere geheugenvereiste dan de andere, gebruikt deze een onevenredige hoeveelheid geheugenbronnen op elk exemplaar waarop de app wordt geïmplementeerd. Omdat dit minder geheugen beschikbaar kan laten voor de andere apps op elk exemplaar, kunt u een functie-app die veel geheugen gebruikt, zoals deze, in een eigen hostingabonnement uitvoeren.

Opmerking

Wanneer u het Verbruiksabonnement gebruikt, wordt u aangeraden elke app altijd in een eigen abonnement te plaatsen, omdat apps toch onafhankelijk worden geschaald. Zie Meerdere apps in hetzelfde abonnement voor meer informatie.

Overweeg of u functies wilt groeperen met verschillende belastingprofielen. Als u bijvoorbeeld een functie hebt die vele duizenden wachtrijberichten verwerkt en een andere functie die alleen af en toe wordt aangeroepen, maar hoge geheugenvereisten heeft, wilt u ze mogelijk implementeren in afzonderlijke functie-apps, zodat ze hun eigen sets resources krijgen en ze onafhankelijk van elkaar schalen.

Functies organiseren voor configuratie en implementatie

Functie-apps hebben een host.json bestand dat wordt gebruikt om geavanceerd gedrag van functietriggers en de Azure Functions-runtime te configureren. Wijzigingen in het host.json bestand zijn van toepassing op alle functies in de app. Als u bepaalde functies hebt die aangepaste configuraties nodig hebben, kunt u deze verplaatsen naar hun eigen functie-app.

Alle functies in uw lokale project worden samen geïmplementeerd als een set bestanden voor uw functie-app in Azure. Mogelijk moet u afzonderlijke functies afzonderlijk implementeren of functies zoals implementatiesites gebruiken voor sommige functies en niet voor andere. In dergelijke gevallen moet u deze functies (in afzonderlijke codeprojecten) implementeren in verschillende functie-apps.

Functies organiseren op basis van machtigingen

Verbindingsreeksen en andere referenties die zijn opgeslagen in toepassingsinstellingen, geven alle functies in de functie-app dezelfde set machtigingen in de bijbehorende resource. Overweeg het aantal functies met toegang tot specifieke referenties te minimaliseren door functies te verplaatsen die deze referenties niet gebruiken naar een afzonderlijke functie-app. U kunt altijd technieken zoals functieketens gebruiken om gegevens door te geven tussen functies in verschillende functie-apps.

Best practices voor schaalbaarheid

Er zijn een aantal factoren die van invloed zijn op hoe exemplaren van uw functieapplicatie opschalen. De details vindt u in de documentatie voor het schalen van functies. Hier volgen enkele aanbevolen procedures om een optimale schaalbaarheid van een functie-app te garanderen.

Verbindingen delen en beheren

Gebruik waar mogelijk verbindingen met externe resources opnieuw. Meer informatie over het beheren van verbindingen in Azure Functions.

Vermijd het delen van opslagaccounts

Wanneer u een functie-app maakt, moet u deze koppelen aan een opslagaccount. De verbinding met het opslagaccount wordt onderhouden in de toepassingsinstelling AzureWebJobsStorage.

Gebruik een afzonderlijk opslagaccount voor elke functie-app om de prestaties te maximaliseren. Deze aanpak is met name belangrijk wanneer u Durable Functions of Event Hubs geactiveerde functies hebt, die beide een groot aantal opslagtransacties genereren. Wanneer uw toepassingslogica communiceert met Azure Storage, direct (met behulp van de opslag-SDK) of via een van de opslagbindingen, moet u een speciaal opslagaccount gebruiken. Als u bijvoorbeeld een door event hub geactiveerde functie hebt die bepaalde gegevens naar blobopslag schrijft, gebruikt u twee opslagaccounts: een voor de functie-app en een andere voor de blobs die door de functie worden opgeslagen.

Gebruik geen test- en productiecode in dezelfde functie-app

Functies binnen een functie-app delen hulpbronnen. Geheugen wordt bijvoorbeeld gedeeld. Als u een functie-app in productie gebruikt, voegt u geen testfuncties en resources eraan toe. Dit kan onverwachte overhead veroorzaken tijdens het uitvoeren van productiecode.

Wees voorzichtig met wat u laadt in uw productiefunctie-apps. Het geheugen wordt gemiddeld voor elke functie in de app.

Als u een gedeelde assembly hebt waarnaar wordt verwezen in meerdere .NET-functies, plaatst u deze in een gemeenschappelijke gedeelde map. Anders kunt u per ongeluk meerdere versies van hetzelfde binaire bestand implementeren dat zich anders gedraagt tussen functies.

Gebruik geen uitgebreide logboekregistratie in productiecode, wat een negatieve invloed heeft op de prestaties.

Gebruik asynchrone code maar vermijd het blokkeren van oproepen

Asynchrone programmering is een aanbevolen best practice, met name wanneer I/O-bewerkingen worden geblokkeerd.

Vermijd in C# altijd om te verwijzen naar de Result eigenschap of om de Wait methode aan te roepen op een Task exemplaar. Deze aanpak kan leiden tot threaduitputting.

Aanbeveling

Als u van plan bent om de HTTP- of WebHook-bindingen te gebruiken, plan dan om uitputting van de poort te voorkomen. Dat kan worden veroorzaakt door onjuiste instantie-instellingen van HttpClient. Raadpleeg Verbindingen beheren in Azure Functions voor meer informatie.

Meerdere werkprocessen gebruiken

Standaard maakt elke hostinstantie voor Functions gebruik van één werkproces. Als u de prestaties wilt verbeteren, met name bij runtimes met één thread, zoals Python, gebruikt u de FUNCTIONS_WORKER_PROCESS_COUNT om het aantal werkprocessen per host (maximaal 10) te verhogen. Vervolgens probeert Azure Functions gelijktijdige functieaanroepen gelijkmatig over deze werkrollen te verdelen.

De FUNCTIONS_WORKER_PROCESS_COUNT is van toepassing op elke host die functies maakt wanneer u uw toepassing uitschaalt om aan de vraag te voldoen.

Ontvang berichten waar mogelijk in batch

Sommige triggers, zoals Event Hub, maken het mogelijk om een batch berichten te ontvangen voor één aanroep. Het batchen van berichten heeft veel betere prestaties. U kunt de maximale batchgrootte in het host.json bestand configureren zoals beschreven in de referentiedocumentatie vanhost.json

Voor C#-functies kunt u het type wijzigen in een sterk getypte array. In plaats van EventData sensorEvent de methodehandtekening kan dit bijvoorbeeld zijn EventData[] sensorEvent. Voor andere talen moet u de eigenschap kardinaliteit expliciet instellen van function.json naar many om batchverwerking in te schakelen, zoals hier getoond.

Hostgedrag configureren voor een betere afhandeling van gelijktijdigheid

Het host.json bestand in de functie-app maakt configuratie van het gedrag van de hostruntime en trigger mogelijk. Naast batchgedrag kunt u gelijktijdigheid voor een aantal triggers beheren. Door de waarden in deze opties aan te passen, kan elke instantie op de juiste wijze worden geschaald voor de vereisten van de aangeroepen functies.

Instellingen in het bestand host.json zijn van toepassing op alle functies in de app, binnen één exemplaar van de functie. Als u bijvoorbeeld een functie-app met twee HTTP-functies en maxConcurrentRequests aanvragen hebt ingesteld op 25, wordt een aanvraag voor een HTTP-trigger meegeteld voor de gedeelde 25 gelijktijdige aanvragen. Wanneer deze functie-app wordt geschaald naar 10 exemplaren, staan de tien functies in feite 250 gelijktijdige aanvragen toe (10 exemplaren * 25 gelijktijdige aanvragen per exemplaar).

Andere opties voor hostconfiguratie vindt u in het host.json configuratieartikel.

Volgende stappen

Zie de volgende bronnen voor meer informatie: