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 Azure Functions best practices voor een meer algemene set best practices voor Azure Functions.

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

Langdurige functies voorkomen

Grote, langlopende functies kunnen onverwachte time-outproblemen veroorzaken. Zie Time-outduur van functie-app voor meer informatie over de time-outs voor een bepaald hostingabonnement.

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

Herstructureer waar mogelijk grote functies in kleinere functiesets die samenwerken en snel antwoorden retourneren. Een webhook- of HTTP-triggerfunctie kan bijvoorbeeld een bevestigingsreactie vereisen binnen een bepaalde tijdslimiet; Het is gebruikelijk dat webhooks onmiddellijk een reactie vereisen. U kunt de nettolading van de HTTP-trigger doorgeven aan een wachtrij die moet worden verwerkt door een wachtrijtriggerfunctie. Met deze benadering kunt u het werkelijke werk uitstellen en onmiddellijk een reactie retourneren.

Zorg ervoor dat achtergrondtaken zijn voltooid

Wanneer uw functie taken, callbacks, threads en processen start, moeten deze worden voltooid voordat de functiecode wordt geretourneerd. Omdat Functions deze achtergrondthreads niet bijhoudt, kan de site worden afgesloten, 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 essentieel werk uitvoert, kan de site worden uitgeschakeld, waardoor het werk in een onbekende status 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 zijn en veel eenvoudiger zijn in te richten dan andere opslagopties.

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

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

Event Hubs zijn handig voor de ondersteuning van communicatie met een hoog volume.

Functies schrijven om staatloos te zijn

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

Idempotente functies worden vooral aanbevolen met timertriggers. Als u bijvoorbeeld iets hebt dat absoluut één keer per dag moet worden uitgevoerd, schrijft u het zodat het op elk gewenst moment van de dag met dezelfde resultaten kan worden uitgevoerd. De functie kan worden afgesloten wanneer er geen werk is voor een bepaalde dag. Als een eerdere uitvoering niet kan worden voltooid, moet de volgende uitvoering verdergaan waar deze is gebleven. Dit is met name belangrijk voor op berichten gebaseerde bindingen die opnieuw proberen te mislukken. Zie Ontwerpen van Azure Functions 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 storingspunt 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 een wachtrijbericht voor elk van deze rijen om verderop in de regel te verwerken.

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

Hoe reageert uw code als er een fout optreedt na het invoegen van 5000 van deze 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 maak uw functies idempotent.

Als een wachtrijitem al is verwerkt, staat u toe dat uw functie een no-op is.

Profiteer van defensieve maatregelen die al zijn voorzien voor onderdelen die u in het Azure Functions-platform gebruikt. Zie bijvoorbeeld Gifwachtrijberichten verwerken in de documentatie voor Azure Storage-wachtrijtriggers en -bindingen.

Voor OP HTTP gebaseerde functies kunt u strategieën voor API-versiebeheer overwegen met Azure API Management. Als u bijvoorbeeld uw HTTP-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 zijn op de vorige functie-app, kunt u de inrichting van de vorige functie-app ongedaan maken.

Best practices voor functieorganisatie

Als onderdeel van uw oplossing kunt u meerdere functies ontwikkelen en publiceren. Deze functies worden vaak gecombineerd in één functie-app, maar ze kunnen ook worden uitgevoerd in afzonderlijke functie-apps. In Premium- en toegewezen (App Service) hostingabonnementen kunnen meerdere functie-apps ook dezelfde resources delen door in hetzelfde abonnement uit te voeren. Hoe u uw functies en functie-apps groepeer, 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 schalen

Elke functie die u maakt, heeft een geheugenvoetafdruk. Hoewel deze footprint meestal klein is, kan het hebben van te veel functies in een functie-app leiden tot een tragere start van uw app op nieuwe exemplaren. Dit betekent ook dat het algehele geheugengebruik van uw functie-app mogelijk hoger is. Het is moeilijk om te zeggen hoeveel functies er 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), delen deze apps allemaal dezelfde resources die aan het plan zijn toegewezen. Als u een functie-app hebt die een veel hogere geheugenbehoefte heeft dan de andere, gebruikt deze een onevenredige hoeveelheid geheugenresources voor elk exemplaar waarin de app wordt geïmplementeerd. Omdat hierdoor minder geheugen beschikbaar kan zijn voor de andere apps op elk exemplaar, kunt u een functie-app met veel geheugengebruik uitvoeren in een eigen afzonderlijk hostingabonnement.

Notitie

Wanneer u het verbruiksabonnement gebruikt, raden we u aan 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 met verschillende belastingprofielen wilt groepeer. Als u bijvoorbeeld een functie hebt die vele duizenden wachtrijberichten verwerkt en een functie die slechts af en toe wordt aangeroepen, maar hoge geheugenvereisten heeft, kunt u deze in afzonderlijke functie-apps implementeren, zodat ze hun eigen sets resources krijgen en onafhankelijk van elkaar worden geschaald.

Functies organiseren voor configuratie en implementatie

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

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

Functies organiseren op bevoegdheid

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 die deze referenties niet gebruiken naar een afzonderlijke functie-app te verplaatsen. U kunt altijd technieken zoals functiekoppeling 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 de schaal van exemplaren van uw functie-app. De details vindt u in de documentatie voor functieschalen. Hier volgen enkele aanbevolen procedures om optimale schaalbaarheid van een functie-app te garanderen.

Verbindingen delen en beheren

Hergebruik verbindingen met externe resources waar mogelijk. Zie verbindingen beheren 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. Dit is vooral belangrijk wanneer u Durable Functions of door Event Hub 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 voor de blobs die door de functie worden opgeslagen.

Test- en productiecode niet combineren in dezelfde functie-app

Functies in een functie-app delen resources. Het geheugen wordt bijvoorbeeld gedeeld. Als u een functie-app in productie gebruikt, voegt u er geen testgerelateerde functies en resources aan 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 er in meerdere .NET-functies naar een gedeelde assembly wordt verwezen, plaatst u deze in een gedeelde map. Anders kunt u per ongeluk meerdere versies van hetzelfde binaire bestand implementeren die zich anders gedragen tussen functies.

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

Gebruik asynchrone code, maar voorkom dat aanroepen worden geblokkeerd

Asynchrone programmering is een aanbevolen best practice, met name wanneer het blokkeren van I/O-bewerkingen betrokken zijn.

Vermijd in C# altijd te verwijzen naar de Result eigenschap of het aanroepen van Wait de methode voor een Task exemplaar. Deze aanpak kan leiden tot threaduitputting.

Tip

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 elk hostexemplaar voor Functions gebruik van één werkproces. Als u de prestaties wilt verbeteren, met name met runtimes met één thread zoals Python, gebruikt u de FUNCTIONS_WORKER_PROCESS_COUNT om het aantal werkprocessen per host te verhogen (maximaal 10). Azure Functions probeert vervolgens 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.

Berichten indien mogelijk in batch ontvangen

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

Voor C#-functies kunt u het type wijzigen in een sterk getypte matrix. In plaats van EventData sensorEvent de methode kan handtekening bijvoorbeeld zijn EventData[] sensorEvent. Voor andere talen moet u de eigenschap kardinaliteit in uw function.json expliciet instellen op om many batchverwerking in te schakelen , zoals hier wordt weergegeven.

Hostgedrag configureren voor een betere afhandeling van gelijktijdigheid

Het host.json bestand in de functie-app maakt configuratie van hostruntime- en triggergedrag mogelijk. Naast batchgedrag kunt u gelijktijdigheid voor een aantal triggers beheren. Door de waarden in deze opties aan te passen, kan elk exemplaar vaak op de juiste manier worden geschaald op basis van 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 hebt met twee HTTP-functies en maxConcurrentRequests aanvragen die zijn ingesteld op 25, telt een aanvraag voor een van beide HTTP-triggers mee voor de gedeelde 25 gelijktijdige aanvragen. Wanneer die functie-app wordt geschaald naar 10 exemplaren, staan de tien functies effectief 250 gelijktijdige aanvragen toe (10 exemplaren * 25 gelijktijdige aanvragen per exemplaar).

Andere opties voor hostconfiguratie vindt u in het artikel host.json-configuratie.

Volgende stappen

Zie de volgende resources voor meer informatie: