Dela via


Förbättra prestanda och tillförlitlighet för Azure Functions

Den här artikeln innehåller vägledning för att förbättra prestanda och tillförlitlighet för dina serverlösa funktionsappar. En mer allmän uppsättning metodtips för Azure Functions finns i Metodtips för Azure Functions.

Följande är metodtips för hur du skapar och utformar dina serverlösa lösningar med hjälp av Azure Functions.

Undvik tidskrävande funktioner

Stora, långvariga funktioner kan orsaka oväntade timeout-problem. Mer information om tidsgränser för en viss värdplan finns i funktionsappens tidsgräns.

En funktion kan bli stor på grund av många Node.js beroenden. Import av beroenden kan också orsaka ökade inläsningstider som resulterar i oväntade timeouter. Beroenden läses in både explicit och implicit. En enskild modul som har laddats av din kod kan ladda sina egna ytterligare moduler.

När det är möjligt omstrukturerar du stora funktioner till mindre funktionsuppsättningar som fungerar tillsammans och returnerar svar snabbt. En webhook- eller HTTP-utlösarfunktion kan till exempel kräva ett bekräftelsesvar inom en viss tidsgräns. det är vanligt att webhooks kräver ett omedelbart svar. Du kan skicka HTTP-utlösarens nyttolast till en kö som ska bearbetas av en köutlösarfunktion. Med den här metoden kan du skjuta upp det faktiska arbetet och returnera ett omedelbart svar.

Kontrollera att bakgrundsaktiviteterna har slutförts

När funktionen startar några uppgifter, återanrop, trådar, processer måste de slutföras innan funktionskoden returneras. Eftersom Functions inte spårar dessa bakgrundstrådar kan webbplatsavstängning ske oavsett bakgrundstrådsstatus, vilket kan orsaka oavsiktligt beteende i dina funktioner.

Om en funktion till exempel startar en bakgrundsaktivitet och returnerar ett lyckat svar innan aktiviteten slutförs, anser Functions-körningen att körningen har slutförts, oavsett resultatet av bakgrundsaktiviteten. Om den här bakgrundsaktiviteten utför nödvändigt arbete kan det avbrytas av nedstängning av platsen, vilket gör att arbetet är i ett okänt tillstånd.

Kommunikation mellan funktioner

Durable Functions och Azure Logic Apps är byggda för att hantera tillståndsövergångar och kommunikation mellan flera funktioner.

Om du inte använder Durable Functions eller Logic Apps för att integrera med flera funktioner är det bäst att använda lagringsköer för kommunikation mellan funktioner. Den främsta orsaken är att lagringsköer är billigare och mycket enklare att etablera än andra lagringsalternativ.

Enskilda meddelanden i en lagringskö är begränsade till 64 KB. Om du behöver skicka större meddelanden mellan funktioner kan en Azure Service Bus-kö användas för att stödja meddelandestorlekar på upp till 256 kB på standardnivån och upp till 100 MB på Premium-nivån.

Service Bus-ämnen är användbara om du behöver meddelandefiltrering innan du bearbetar.

Händelsehubbar är användbara för att stödja kommunikation med stora volymer.

Skriv funktioner som är tillståndslösa

Funktionerna ska vara tillståndslösa och idempotenta om möjligt. Associera all nödvändig tillståndsinformation med dina data. Till exempel skulle en order som bearbetas sannolikt ha en associerad state komponent. En funktion kan bearbeta en ordning baserat på det tillståndet medan själva funktionen förblir tillståndslös.

Idempotent-funktioner rekommenderas särskilt med timerutlösare. Om du till exempel har något som absolut måste köras en gång om dagen skriver du det så att det kan köras när som helst under dagen med samma resultat. Funktionen kan avslutas när det inte finns något arbete under en viss dag. Om en tidigare körning inte kunde slutföras bör nästa körning fortsätta där den slutade. Detta är särskilt viktigt för meddelandebaserade bindningar som försöker igen vid fel. Mer information finns i Designa Azure Functions för identiska indata.

Skriva defensiva funktioner

Anta att funktionen kan stöta på ett undantag när som helst. Utforma dina funktioner med möjlighet att fortsätta från en tidigare felpunkt under nästa körning. Tänk dig ett scenario som kräver följande åtgärder:

  1. Fråga efter 10 000 rader i en databas.
  2. Skapa ett kömeddelande för var och en av dessa rader för att bearbeta längre ned på linjen.

Beroende på hur komplext systemet är kan det bero på att nedströmstjänster beter sig dåligt, nätverksstopp eller att kvotgränser har nåtts osv. Alla dessa kan påverka din funktion när som helst. Du måste utforma dina funktioner för att vara förberedda för det.

Hur reagerar koden om ett fel inträffar efter att 5 000 av dessa objekt har infogats i en kö för bearbetning? Spåra artiklar i en samling som du har slutfört. Annars kan du infoga dem igen nästa gång. Den här dubbelinfogning kan ha en allvarlig inverkan på ditt arbetsflöde, så gör dina funktioner idempotenta.

Om ett köobjekt redan har bearbetats kan du låta funktionen vara en no-op.

Dra nytta av de defensiva åtgärder som redan finns för komponenter som du använder i Azure Functions-plattformen. Se till exempel Hantera meddelanden om giftköer i dokumentationen för Azure Storage Queue-utlösare och bindningar.

För HTTP-baserade funktioner bör du överväga api-versionshanteringsstrategier med Azure API Management. Om du till exempel måste uppdatera din HTTP-baserade funktionsapp distribuerar du den nya uppdateringen till en separat funktionsapp och använder API Management-revisioner eller -versioner för att dirigera klienter till den nya versionen eller revisionen. När alla klienter använder versionen eller uppdateringen och inga fler körningar finns kvar i den tidigare funktionsappen, kan du avveckla den tidigare funktionsappen.

Metodtips för funktionsorganisation

Som en del av din lösning kan du utveckla och publicera flera funktioner. Dessa funktioner kombineras ofta till en enda funktionsapp, men de kan också köras i separata funktionsappar. I Premium och dedikerade (App Service) värdplaner kan flera funktionsappar också dela samma resurser genom att köra i samma plan. Hur du grupperar dina funktioner och funktionsappar kan påverka prestanda, skalning, konfiguration, distribution och säkerhet för din övergripande lösning. Det finns inga regler som gäller för varje scenario, så tänk på informationen i det här avsnittet när du planerar och utvecklar dina funktioner.

Organisera funktioner för prestanda och skalning

Varje funktion som du skapar har ett minnesfotavtryck. Även om det här fotavtrycket vanligtvis är litet kan för många funktioner i en funktionsapp leda till långsammare start av appen på nya instanser. Det innebär också att den totala minnesanvändningen för funktionsappen kan vara högre. Det är svårt att säga hur många funktioner som ska finnas i en enda app, vilket beror på din specifika arbetsbelastning. Men om din funktion lagrar mycket data i minnet bör du överväga att ha färre funktioner i en enda app.

Om du kör flera funktionsappar i en enda Premium-plan eller dedikerad (App Service)-plan delar alla dessa appar samma resurser som allokerats till planen. Om du har en funktionsapp som har ett mycket högre minnesbehov än de andra använder den en oproportionerlig mängd minnesresurser på varje instans som appen distribueras till. Eftersom detta kan lämna mindre minne tillgängligt för de andra apparna på varje instans, kanske du vill köra en funktionsapp med hög minnesanvändning som den här i sin egen separata värdplan.

Anmärkning

När du använder förbrukningsplanen rekommenderar vi att du alltid placerar varje app i sin egen plan, eftersom appar skalas oberoende ändå. Mer information finns i Flera appar i samma plan.

Fundera på om du vill gruppera funktioner med olika belastningsprofiler. Om du till exempel har en funktion som bearbetar tusentals kömeddelanden och en annan som bara anropas ibland men har höga minneskrav, kanske du vill distribuera dem i separata funktionsappar så att de får sina egna uppsättningar resurser och de skalas oberoende av varandra.

Organisera funktioner för konfiguration och distribution

Funktionsappar har en host.json fil som används för att konfigurera avancerat beteende för funktionsutlösare och Azure Functions-körning. Ändringar i host.json filen gäller för alla funktioner i appen. Om du har några funktioner som behöver anpassade konfigurationer kan du överväga att flytta dem till en egen funktionsapp.

Alla funktioner i ditt lokala projekt distribueras tillsammans som en uppsättning filer till funktionsappen i Azure. Du kan behöva distribuera enskilda funktioner separat eller använda funktioner som distributionsplatser för vissa funktioner och inte andra. I sådana fall bör du distribuera dessa funktioner (i separata kodprojekt) till olika funktionsappar.

Ordna funktioner efter behörighet

Anslutningssträngar och andra autentiseringsuppgifter som lagras i programinställningarna ger alla funktioner i funktionsappen samma uppsättning behörigheter i den associerade resursen. Överväg att minimera antalet funktioner med åtkomst till specifika autentiseringsuppgifter genom att flytta funktioner som inte använder dessa autentiseringsuppgifter till en separat funktionsapp. Du kan alltid använda tekniker som funktionslänkning för att skicka data mellan funktioner i olika funktionsappar.

Metodtips för skalbarhet

Det finns ett antal faktorer som påverkar hur instanser av din funktionsapp skalas. Informationen finns i dokumentationen för funktionsskalning. Följande är några metodtips för att säkerställa optimal skalbarhet för en funktionsapp.

Dela och hantera anslutningar

Återanvänd anslutningar till externa resurser när det är möjligt. Se hur du hanterar anslutningar i Azure Functions.

Undvik att dela lagringskonton

När du skapar en funktionsapp måste du associera den med ett lagringskonto. Anslutningen till lagringskontot underhålls i programinställningen AzureWebJobsStorage.

Använd ett separat lagringskonto för varje funktionsapp för att maximera prestandan. Den här metoden är särskilt viktig när du har Durable Functions- eller Event Hubs-utlösta funktioner, som båda genererar en stor mängd lagringstransaktioner. När din programlogik interagerar med Azure Storage, antingen direkt (med hjälp av Storage SDK) eller via någon av lagringsbindningarna, bör du använda ett dedikerat lagringskonto. Om du har till exempel en funktion utlöst av en händelsehub som skriver data till bloblagring, använd två lagringskonton: ett för funktionsappen och ett annat för de blobbar som funktionen lagrar.

Blanda inte test- och produktionskod i samma funktionsapp

Funktioner i en funktionsapp delar resurser. Till exempel delas minne. Om du använder en funktionsapp i produktion ska du inte lägga till testrelaterade funktioner och resurser i den. Det kan orsaka oväntad belastning vid körning av produktionskod.

Var försiktig med vad du läser in i dina produktionsfunktionsappar. Minnet beräknas i genomsnitt för varje funktion i appen.

Om du har en delad sammansättning som refereras till i flera .NET-funktioner placerar du den i en gemensam delad mapp. Annars kan du av misstag distribuera flera versioner av samma binärfil som fungerar annorlunda mellan funktioner.

Använd inte utförlig loggning i produktionskod, vilket har en negativ prestandapåverkan.

Använd asynkron kod men undvik att blockera anrop

Asynkron programmering är en rekommenderad metod, särskilt när det gäller blockering av I/O-åtgärder.

I C# ska du alltid undvika att referera till egenskapen Result eller anropa metoden Wait på en Task instans. Den här metoden kan leda till trådöverbelastning.

Tips/Råd

Om du planerar att använda HTTP- eller WebHook-bindningarna planerar du att undvika portöverbelastning som kan orsakas av felaktig instansiering av HttpClient. Mer information finns i Hantera anslutningar i Azure Functions.

Använda flera arbetsprocesser

Som standard använder alla värdinstanser för Functions en enda arbetsprocess. För att förbättra prestanda, särskilt med entrådade runtimer som Python, använd FUNCTIONS_WORKER_PROCESS_COUNT för att öka antalet arbetsprocesser per värd (upp till 10). Azure Functions försöker sedan distribuera samtidiga funktionsanrop jämnt mellan dessa arbetare.

FUNCTIONS_WORKER_PROCESS_COUNT gäller för varje värd som Functions skapar när du skalar ut ditt program för att möta efterfrågan.

Ta emot meddelanden i batch när det är möjligt

Vissa utlösare som Event Hub gör det möjligt att ta emot en batch med meddelanden på ett enda anrop. Batchbearbetning av meddelanden har mycket bättre prestanda. Du kan konfigurera den maximala batchstorleken i filen host.json som beskrivs i referensdokumentationen för host.json

För C#-funktioner kan du ändra typen till en starkt typad matris. I stället för EventData sensorEvent metodsignaturen kan till exempel vara EventData[] sensorEvent. För andra språk måste du uttryckligen ange kardinalitetsegenskapen i din function.json till many för att aktivera batchbearbetning som du ser här.

Konfigurera värdbeteenden för att bättre hantera samtidighet

Filen host.json i funktionsappen tillåter konfiguration av värdkörnings- och utlösarbeteenden. Förutom batchbearbetningsbeteenden kan du hantera samtidighet för ett antal utlösare. Om du ofta justerar värdena i de här alternativen kan varje instans skalas på rätt sätt för de anropade funktionernas krav.

Inställningarna i host.json-filen gäller för alla funktioner i appen, inom en enda instans av funktionen. Om du till exempel hade en funktionsapp med två HTTP-funktioner och maxConcurrentRequests begäranden inställda på 25, skulle en begäran till någon av HTTP-utlösare räknas mot de delade 25 samtidiga begärandena. När funktionsappen skalas till 10 instanser tillåter de tio funktionerna effektivt 250 samtidiga begäranden (10 instanser * 25 samtidiga begäranden per instans).

Andra värdkonfigurationsalternativ finns i artikelnhost.json konfiguration.

Nästa steg

Mer information finns i följande resurser: