Zlepšení výkonu a spolehlivosti Azure Functions

Tento článek obsahuje pokyny ke zlepšení výkonu a spolehlivosti aplikací bezserverových funkcí. Obecnější sadu osvědčených postupů pro Azure Functions najdete v tématu osvědčené postupy pro Azure Functions.

Níže jsou uvedené osvědčené postupy při sestavování a navrhování bezserverových řešení pomocí Azure Functions.

Vyhněte se dlouhotrvajícím funkcím

Velké a dlouhotrvající funkce můžou způsobit neočekávané problémy s vypršením časového limitu. Další informace o vypršení časových limitů pro daný plán hostování najdete v tématu Doba trvání časového limitu aplikace funkcí.

Funkce se může zvětšit kvůli mnoha závislostem Node.js. Import závislostí může také způsobit delší dobu načítání, která vede k neočekávanému vypršení časových limitů. Závislosti se načítají explicitně i implicitně. Jeden modul načtený vaším kódem může načíst vlastní další moduly.

Kdykoli je to možné, refaktorujte velké funkce na menší sady funkcí, které spolupracují a rychle vracejí odpovědi. Například funkce webhooku nebo triggeru HTTP může vyžadovat odpověď na potvrzení v určitém časovém limitu. Je běžné, že webhooky vyžadují okamžitou reakci. Datovou část triggeru HTTP můžete předat do fronty, kterou zpracuje funkce triggeru fronty. Tento přístup umožňuje odložit skutečnou práci a vrátit okamžitou odpověď.

Ujistěte se, že se dokončily úlohy na pozadí.

Když funkce spustí úlohy, zpětná volání, vlákna nebo procesy, musí se dokončit před vrácením kódu funkce. Vzhledem k tomu, že funkce tato vlákna na pozadí nesleduje, může dojít k vypnutí webu bez ohledu na stav vlákna na pozadí, což může způsobit nezamýšlené chování vašich funkcí.

Pokud například funkce spustí úlohu na pozadí a vrátí úspěšnou odpověď před dokončením úlohy, modul runtime služby Functions považuje provedení za úspěšně dokončené bez ohledu na výsledek úlohy na pozadí. Pokud tato úloha na pozadí provádí základní práci, může být ukončena vypnutím webu, takže tato práce zůstane v neznámém stavu.

Komunikace mezi funkcemi

Durable Functions a Azure Logic Apps slouží ke správě přechodů stavu a komunikace mezi několika funkcemi.

Pokud nepoužíváte Durable Functions nebo Logic Apps k integraci s více funkcemi, je nejlepší použít fronty úložiště pro komunikaci mezi funkcemi. Hlavním důvodem je, že fronty úložiště jsou levnější a zřizují se mnohem snadněji než jiné možnosti úložiště.

Velikost jednotlivých zpráv ve frontě úložiště je omezená na 64 kB. Pokud potřebujete mezi funkcemi předávat větší zprávy, můžete Azure Service Bus frontu použít pro podporu zpráv o velikosti až 256 kB na úrovni Standard a až 100 MB na úrovni Premium.

Témata služby Service Bus jsou užitečná, pokud před zpracováním vyžadujete filtrování zpráv.

Centra událostí jsou užitečná pro podporu velkoobsádové komunikace.

Zápis bezstavových funkcí

Pokud je to možné, měly by být funkce bezstavové a idempotentní. Přidružte ke svým datům požadované informace o stavu. Například zpracovávaná objednávka by pravděpodobně měla přidruženého state člena. Funkce může na základě tohoto stavu zpracovat pořadí, zatímco samotná funkce zůstává bezstavová.

Idempotentní funkce se doporučují zejména u triggerů časovače. Pokud máte například něco, co se musí spouštět jednou denně, napište to tak, aby to mohlo běžet kdykoli během dne se stejnými výsledky. Funkce se může ukončit, když pro určitý den není žádná práce. Pokud se předchozí spuštění nepovedlo dokončit, mělo by další spuštění navázat tam, kde skončilo. To je důležité zejména pro vazby založené na zprávách, které se při selhání opakují. Další informace najdete v tématu Návrh Azure Functions pro identický vstup.

Zápis defenzivních funkcí

Předpokládejme, že u vaší funkce může kdykoli dojít k výjimce. Navrhněte funkce tak, aby během dalšího spuštění pokračovaly od předchozího bodu selhání. Zvažte scénář, který vyžaduje následující akce:

  1. Zadejte dotaz na 10 000 řádků v databázi.
  2. Vytvořte zprávu fronty pro každý z těchto řádků, která se bude zpracovávat dále po řádku.

V závislosti na tom, jak je váš systém složitý, jste mohli mít za to, že se podřízené služby chovaly špatně, výpadky sítě, dosažení limitů kvót atd. Všechny tyto možnosti můžou kdykoli ovlivnit vaši funkci. Musíte navrhnout funkce tak, aby na to byly připravené.

Jak váš kód reaguje, když po vložení 5 000 těchto položek do fronty ke zpracování dojde k selhání? Sledujte položky v sadě, kterou jste dokončili. V opačném případě je můžete příště vložit znovu. Toto dvojité vložení může mít vážný dopad na váš pracovní tok, proto nastavte své funkce jako idempotentní.

Pokud již byla položka fronty zpracována, povolte funkci, aby byla no-op.

Využijte obranná opatření, která už jsou k dispozici pro komponenty, které používáte na platformě Azure Functions. Projděte si například téma Zpracování zpráv ve frontě s jedem v dokumentaci k triggerům a vazbám fronty služby Azure Storage.

U funkcí založených na protokolu HTTP zvažte strategie správy verzí rozhraní API pomocí Azure API Management. Pokud například potřebujete aktualizovat aplikaci funkcí založenou na protokolu HTTP, nasaďte novou aktualizaci do samostatné aplikace funkcí a pomocí API Management revizí nebo verzí nasměrujte klienty na novou verzi nebo revizi. Jakmile všichni klienti používají verzi nebo revizi a v předchozí aplikaci funkcí nezůstane žádná další spuštění, můžete zrušit zřízení předchozí aplikace funkcí.

Osvědčené postupy organizace funkcí

Jako součást řešení můžete vyvíjet a publikovat více funkcí. Tyto funkce se často kombinují do jedné aplikace funkcí, ale dají se spustit i v samostatných aplikacích funkcí. V plánech hostování Premium a dedicated (App Service) může několik aplikací funkcí sdílet stejné prostředky spuštěním ve stejném plánu. Způsob seskupení funkcí a aplikací funkcí může ovlivnit výkon, škálování, konfiguraci, nasazení a zabezpečení celkového řešení. Neexistují pravidla, která platí pro každý scénář, proto při plánování a vývoji funkcí zvažte informace v této části.

Uspořádání funkcí pro výkon a škálování

Každá funkce, kterou vytvoříte, má nároky na paměť. I když jsou tyto nároky obvykle malé, příliš mnoho funkcí v rámci aplikace funkcí může vést k pomalejšímu spouštění aplikace na nových instancích. Také to znamená, že celkové využití paměti vaší aplikací funkcí může být vyšší. Je těžké říct, kolik funkcí by mělo být v jedné aplikaci, což závisí na konkrétní úloze. Pokud ale funkce ukládá do paměti velké množství dat, zvažte méně funkcí v jedné aplikaci.

Pokud používáte více aplikací funkcí v jednom plánu Premium nebo vyhrazeném plánu (App Service), všechny tyto aplikace sdílejí stejné prostředky přidělené plánu. Pokud máte jednu aplikaci funkcí, která má mnohem vyšší požadavky na paměť než ostatní, používá nepřiměřeně velké množství paměťových prostředků v každé instanci, do které je aplikace nasazená. Vzhledem k tomu, že by to mohlo ponechat méně paměti dostupné pro ostatní aplikace v každé instanci, můžete chtít spustit aplikaci funkcí s vysokým využitím paměti v jejím vlastním samostatném plánu hostování.

Poznámka

Při použití plánu Consumption doporučujeme vždy umístit každou aplikaci do vlastního plánu, protože aplikace se i tak škálují nezávisle. Další informace najdete v tématu Více aplikací ve stejném plánu.

Zvažte, jestli chcete seskupovat funkce s různými profily zatížení. Pokud máte například funkci, která zpracovává mnoho tisíc zpráv ve frontě, a jinou, která se volá jen občas, ale má vysoké požadavky na paměť, můžete ji nasadit do samostatných aplikací funkcí, aby získaly vlastní sady prostředků a škálovaly se nezávisle na sobě.

Uspořádání funkcí pro konfiguraci a nasazení

Aplikace funkcí mají host.json soubor, který slouží ke konfiguraci pokročilého chování triggerů funkcí a modulu runtime Azure Functions. Změny souboru host.json se vztahují na všechny funkce v aplikaci. Pokud máte některé funkce, které vyžadují vlastní konfiguraci, zvažte jejich přesunutí do jejich vlastní aplikace funkcí.

Všechny funkce v místním projektu se nasadí společně jako sada souborů do vaší aplikace funkcí v Azure. Možná budete muset nasadit jednotlivé funkce samostatně nebo použít funkce, jako jsou sloty nasazení , pro některé funkce a ne pro jiné. V takových případech byste měli tyto funkce nasadit (v samostatných projektech kódu) do různých aplikací funkcí.

Uspořádání funkcí podle oprávnění

Připojovací řetězce a další přihlašovací údaje uložené v nastavení aplikace poskytují všem funkcím v aplikaci funkcí stejnou sadu oprávnění v přidruženém prostředku. Zvažte minimalizaci počtu funkcí s přístupem ke konkrétním přihlašovacím údajům přesunutím funkcí, které tyto přihlašovací údaje nepoužívají, do samostatné aplikace funkcí. K předávání dat mezi funkcemi v různých aplikacích funkcí můžete vždy použít techniky, jako je řetězení funkcí .

Osvědčené postupy pro škálovatelnost

Škálování instancí vaší aplikace funkcí ovlivňuje několik faktorů. Podrobnosti najdete v dokumentaci ke škálování funkcí. Následuje několik osvědčených postupů pro zajištění optimální škálovatelnosti aplikace funkcí.

Sdílení a správa připojení

Kdykoli je to možné, opakovaně používejte připojení k externím prostředkům. Přečtěte si, jak spravovat připojení v Azure Functions.

Vyhněte se sdílení účtů úložiště

Když vytváříte aplikaci funkcí, musíte ji přidružit k účtu úložiště. Připojení k účtu úložiště se udržuje v nastavení aplikace AzureWebJobsStorage.

Pokud chcete maximalizovat výkon, použijte pro každou aplikaci funkcí samostatný účet úložiště. To je obzvláště důležité, pokud máte funkce aktivované Durable Functions nebo centrum událostí, které generují velký objem transakcí úložiště. Když logika aplikace interaguje se službou Azure Storage, a to buď přímo (pomocí sady Storage SDK), nebo prostřednictvím některé z vazeb úložiště, měli byste použít vyhrazený účet úložiště. Pokud například máte funkci aktivovanou centrem událostí, která zapisuje některá data do úložiště objektů blob, použijte dva účty úložiště – jeden pro aplikaci funkcí a druhý pro objekty blob, které funkce ukládá.

Nekombinujte testovací a produkční kód ve stejné aplikaci funkcí.

Funkce v rámci aplikace funkcí sdílejí prostředky. Například se sdílí paměť. Pokud používáte aplikaci funkcí v produkčním prostředí, nepřidávejte do ní funkce a prostředky související s testováním. Může způsobit neočekávanou režii při provádění produkčního kódu.

Buďte opatrní, co načítáte v aplikacích produkčních funkcí. Paměť se průměruje napříč jednotlivými funkcemi v aplikaci.

Pokud máte sdílené sestavení odkazované ve více funkcích .NET, umístěte ho do společné sdílené složky. V opačném případě byste mohli omylem nasadit více verzí stejného binárního souboru, které se mezi funkcemi chovají odlišně.

Nepoužívejte podrobné protokolování v produkčním kódu, které má negativní dopad na výkon.

Použití asynchronního kódu, ale zabránění blokování volání

Osvědčeným postupem je asynchronní programování, zejména pokud se jedná o blokující vstupně-výstupní operace.

V jazyce C# se vždy vyhněte odkazování na Result vlastnost nebo volání Wait metody v Task instanci. Tento přístup může vést k vyčerpání vláken.

Tip

Pokud plánujete používat vazby HTTP nebo WebHook, naplánujte, abyste se vyhnuli vyčerpání portů, které může být způsobeno nesprávným vytvořením instance .HttpClient Další informace najdete v tématu Správa připojení v Azure Functions.

Použití více pracovních procesů

Ve výchozím nastavení každá instance hostitele pro functions používá jeden pracovní proces. Pokud chcete zvýšit výkon, zejména u jednovláknových modulů runtime, jako je Python, použijte FUNCTIONS_WORKER_PROCESS_COUNT ke zvýšení počtu pracovních procesů na hostitele (až 10). Azure Functions se pak pokusí rovnoměrně distribuovat souběžná volání funkcí mezi tyto pracovní procesy.

Nastavení FUNCTIONS_WORKER_PROCESS_COUNT se vztahuje na všechny hostitele, které služba Functions vytvoří při škálování vaší aplikace na více instancí podle poptávky.

Příjem zpráv v dávkách, kdykoli je to možné

Některé triggery, jako je centrum událostí, umožňují příjem dávky zpráv při jednom vyvolání. Dávkování zpráv má mnohem lepší výkon. Maximální velikost dávky v host.json souboru můžete nakonfigurovat, jak je podrobně popsáno v referenční dokumentaci k souboru host.json.

U funkcí jazyka C# můžete typ změnit na pole se silnými typy. Například místo EventData sensorEvent podpisu metody může být EventData[] sensorEvent. V jiných jazycích budete muset explicitně nastavit vlastnost kardinality v function.jsonmany to, aby bylo možné dávkování povolit, jak je znázorněno tady.

Konfigurace chování hostitelů pro lepší zpracování souběžnosti

Soubor host.json v aplikaci funkcí umožňuje konfiguraci modulu runtime hostitele a chování triggerů. Kromě chování dávkování můžete spravovat souběžnost pro řadu triggerů. Úprava hodnot v těchto možnostech může často pomoct každé instanci škálovat odpovídajícím způsobem podle požadavků vyvolaných funkcí.

Nastavení v souboru host.json platí pro všechny funkce v rámci aplikace v rámci jedné instance funkce. Pokud byste například měli aplikaci funkcí se dvěma funkcemi HTTP a maxConcurrentRequests požadavky nastavenými na 25, požadavek na trigger HTTP by se započetl do sdílených 25 souběžných požadavků. Když je tato aplikace funkcí škálovaná na 10 instancí, deset funkcí efektivně umožňuje 250 souběžných požadavků (10 instancí × 25 souběžných požadavků na instanci).

Další možnosti konfigurace hostitele najdete v článku o konfiguraci host.json.

Další kroky

Další informace naleznete v následujících zdrojích: