Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A Azure Functions Python használatával történő fejlesztésekor tisztában kell lenni azzal, hogy a függvények hogyan működnek, és hogy ez a teljesítmény hogyan befolyásolja a függvényalkalmazás méretezését. A nagy teljesítményű alkalmazások tervezésekor fontosabb az igény. A függvényalkalmazások tervezése, írása és konfigurálása során a fő szempontok a horizontális skálázás és az átviteli sebesség teljesítménykonfigurációi.
Horizontális skálázás
Alapértelmezés szerint Azure Functions automatikusan figyeli az alkalmazás terhelését, és szükség szerint több gazdagéppéldányt hoz létre a Python számára. Azure Functions beépített küszöbértékeket használ a különböző triggertípusokhoz, hogy eldöntse, mikor kell példányokat hozzáadni, például az üzenetek életkorát és a QueueTrigger üzenetsorméretét. Ezek a küszöbértékek nem konfigurálhatók felhasználónként. További információ: Event-alapú skálázás Azure Functions.
Az átviteli sebesség teljesítményének javítása
Az alapértelmezett konfigurációk a legtöbb Azure Functions alkalmazáshoz alkalmasak. Az alkalmazások átviteli sebességét azonban javíthatja a számítási feladatprofilon alapuló konfigurációk alkalmazásával. Az első lépés a futó számítási feladatok típusának megismerése.
| Terhelés típusa | A függvényalkalmazás jellemzői | Példák |
|---|---|---|
| I/O-kötött | • Az alkalmazásnak számos egyidejű meghívást kell kezelnie. • Az alkalmazás számos I/O-eseményt dolgoz fel, például hálózati hívásokat és lemez olvasási/írási műveleteket. |
• Webes API-k |
| processzorhoz kötött | • Az alkalmazás hosszú ideig futó számításokat végez, például képek átméretezését. • Az alkalmazás adatátalakítást végez. |
• Adatfeldolgozás • Gépi tanulási következtetés |
Mivel a valós számítási feladatok általában az I/O és a CPU-igényes műveletek kombinációját képezik, valós körülmények közötti terhelések mellett kell profilozni az alkalmazást.
Teljesítményspecifikus konfigurációk
Miután megismerte a függvényalkalmazás számítási feladatprofilját, az alábbi konfigurációkkal javíthatja a függvények átviteli sebességét.
- Async
- Több nyelvi feldolgozó
- A nyelvi feldolgozó folyamaton belüli feldolgozók maximális száma
- Eseményhurok
- Függőleges skálázás
Async
Mivel Python egyszálas futtatókörnyezet, egy Python gazdagép példánya alapértelmezés szerint csak egy függvényhívást képes feldolgozni. Nagy számú I/O-eseményt feldolgozó és/vagy I/O-kötött alkalmazások esetében a függvények aszinkron futtatásával jelentősen javíthatja a teljesítményt.
A függvény aszinkron futtatásához használja az async def utasítást, amely közvetlenül az asyncio használatával futtatja a függvényt:
async def main():
await some_nonblocking_socket_io_op()
Íme egy példa egy HTTP-eseményindítóval rendelkező függvényre, amely aiohttp http-ügyfelet használ:
import aiohttp
import azure.functions as func
async def main(req: func.HttpRequest) -> func.HttpResponse:
async with aiohttp.ClientSession() as client:
async with client.get("PUT_YOUR_URL_HERE") as response:
return func.HttpResponse(await response.text())
return func.HttpResponse(body='NotFound', status_code=404)
A kulcsszó nélküli async függvények automatikusan futnak a ThreadPoolExecutor szálkészletben:
# Runs in a ThreadPoolExecutor threadpool. Number of threads is defined by PYTHON_THREADPOOL_THREAD_COUNT.
# The example is intended to show how default synchronous functions are handled.
def main():
some_blocking_socket_io()
A függvények aszinkron futtatásának teljes körű előnyeinek eléréséhez a kódban használt I/O-műveletnek/kódtárnak aszinkron módon is implementálva kell lennie. Ha szinkron I/O-műveleteket használ az aszinkronként definiált függvényekben, az ronthatja az általános teljesítményt. Ha a használt kódtárak nem implementálják az aszinkron verziót, akkor is kihasználhatja a kód aszinkron futtatását az eseményhurok alkalmazásbeli kezelésével .
Íme néhány példa az aszinkron mintákat implementáló ügyfélkódtárakra:
- aiohttp – Http-ügyfél/kiszolgáló az asyncio-hoz
- Streams API – Magas szintű aszinkron/várakozásra kész primitívek a hálózati kapcsolat használatához
- Janus-üzenetsor – Szálbiztos, aszinkronio-tudatos üzenetsor a Python számára
- pyzmq – a ZeroMQ Python kötései
Az aszinkronok ismertetése Python feldolgozóban
Ha async definiál egy függvény-aláírás előtt, Python a függvényt koroutinként jelöli meg. Amikor meghívja a koroutint, az ütemezhető úgy, mint egy feladat egy eseményhurokban. Amikor meghív await egy aszinkron függvényt, az regisztrálja a folytatást az eseményhurokba, így az eseményhurok feldolgozhatja a következő feladatot a várakozási idő alatt.
A Python Feldolgozóban a feldolgozó az eseményhurkot az ügyfél async függvényével osztja meg, és egyszerre több kérés kezelésére is képes. Határozottan ösztönözzük ügyfeleinket, hogy használjanak asyncio kompatibilis kódtárakat, például az aiohttp-t és a pyzmq-ot. Ezeket a javaslatokat követve a függvény átviteli sebessége növekszik a szinkron implementálású kódtárakhoz képest.
Megjegyzés:
Ha a függvény async deklarálva van anélkül, hogy await lenne a megvalósításon belül, a függvény teljesítménye súlyosan sérül, mivel az eseményhurok le lesz tiltva, ami megakadályozza, hogy a Python feldolgozó egyidejű kéréseket kezeljen.
Több nyelvi feldolgozó folyamat használata
Alapértelmezés szerint minden Functions-gazdagéppéldány egyetlen nyelvi feldolgozó folyamattal rendelkezik. Az FUNCTIONS_WORKER_PROCESS_COUNT alkalmazásbeállítás használatával növelheti a munkafolyamatok hosztonkénti számát (legfeljebb 10). Azure Functions ezután megpróbálja egyenletesen elosztani az egyidejű függvényhívásokat ezeken a feldolgozókon.
A processzorhoz kötött alkalmazások esetében a nyelvmunkások számát a függvényalkalmazásonként elérhető magok számával megegyező vagy annál magasabb értékre kell állítani. További információ: Elérhető példányok SKU-jai.
Az I/O-kötött alkalmazásoknak az is hasznát vehetik, ha a feldolgozói folyamatok száma meghaladja a rendelkezésre álló magok számát. Ne feledje, hogy a túl magas munkavállalók száma beállítása hatással lehet az általános teljesítményre a szükséges környezetváltások megnövekedett száma miatt.
A FUNCTIONS_WORKER_PROCESS_COUNT azokra a hostokra vonatkozik, amelyeket az Azure Functions hoz létre az alkalmazás igény szerinti skálázásakor.
Maximális feldolgozó beállítása egy nyelvi feldolgozói folyamaton belül
Az aszinkron szakaszban a Python nyelvi feldolgozó másképp kezeli a függvényeket és a korrutinokat. A koroutin ugyanabban az eseményhurkban fut, amelyen a nyelvi feldolgozó fut. A függvényhívások viszont egy ThreadPoolExecutoron belül futnak, amelyet a nyelvi feldolgozó szálként tart fenn.
A szinkronizálási függvények futtatásához engedélyezett maximális feldolgozók értékét a PYTHON_THREADPOOL_THREAD_COUNT alkalmazásbeállítással állíthatja be. Ez az érték beállítja a ThreadPoolExecutor objektum max_worker argumentumát, amely lehetővé teszi, hogy Python legfeljebb max_worker szálakból álló készletet használjon a hívások aszinkron végrehajtásához. A PYTHON_THREADPOOL_THREAD_COUNT minden olyan feldolgozóra vonatkozik, amelyet a Functions-gazdagép létrehoz, és Python dönti el, hogy mikor hoz létre új szálat, vagy használja újra a meglévő tétlen szálat. A régebbi Python verziók (azaz 3.8, 3.7 és 3.6) esetében a max_worker érték 1. Python 3.9 verzió esetén a(z) max_worker értéke None.
A processzorhoz kötött alkalmazások esetében a beállítást alacsony értéken kell tartani, kezdve 1-től, majd a terhelés kísérletezésekor fokozatosan növelheti azt. Ez a javaslat csökkenti a környezeti kapcsolókon töltött időt, és lehetővé teszi a processzorhoz kötött tevékenységek befejezését.
Az I/O-hoz kötött alkalmazások esetében jelentős nyereséget tapasztalhat az egyes meghívásokon dolgozó szálak számának növelésével. Az ajánlás az, hogy kezdj a Python alapértelmezett értékével (a magok számával) + 4, és azután a látott átviteli sebességértékek alapján állítsd be.
Vegyes munkaterhelésű alkalmazások esetében az átviteli teljesítmény maximalizálása érdekében egyensúlyba kell hozni a FUNCTIONS_WORKER_PROCESS_COUNT és PYTHON_THREADPOOL_THREAD_COUNT konfigurációkat. Annak megértéséhez, hogy a függvényalkalmazások mire töltik a legtöbb időt, javasoljuk, hogy profilozza őket, és a viselkedésüknek megfelelően állítsa be az értékeket. Az alkalmazásbeállításokról további információt a Több feldolgozói folyamat használata című témakörben talál.
Megjegyzés:
Bár ezek a javaslatok a HTTP és a nem HTTP által aktivált függvényekre is vonatkoznak, előfordulhat, hogy módosítania kell a nem HTTP által aktivált függvények egyéb triggerspecifikus konfigurációit, hogy a függvényalkalmazások elvárt teljesítményt kapják. Erről a Megbízható Azure-függvények legjobb gyakorlatairól című cikkben talál további információt.
Eseményhurok kezelése
Aszinkron kompatibilis külső kódtárakat kell használnia. Ha a külső kódtárak egyike sem felel meg az igényeinek, akkor az eseményhurkokat is kezelheti a Azure Functions. Az eseményhurokok kezelése nagyobb rugalmasságot biztosít a számítási erőforrás-kezelésben, és lehetővé teszi a szinkron I/O-kódtárak koroutinokba való burkolását is.
Számos hasznos Python hivatalos dokumentum foglalkozik a Coroutines és a Tasks és Event Loop a beépített asyncio könyvtár használatával.
Vegyük példaként a következő requests könyvtárat. Ez a kódrészlet az asyncio könyvtár használatával ágyazza be a requests.get() metódust egy koroutinba, és egyszerre több webes kérést futtat a SAMPLE_URL-re.
import asyncio
import json
import logging
import azure.functions as func
from time import time
from requests import get, Response
async def invoke_get_request(eventloop: asyncio.AbstractEventLoop) -> Response:
# Wrap requests.get function into a coroutine
single_result = await eventloop.run_in_executor(
None, # using the default executor
get, # each task call invoke_get_request
'SAMPLE_URL' # the url to be passed into the requests.get function
)
return single_result
async def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
eventloop = asyncio.get_event_loop()
# Create 10 tasks for requests.get synchronous call
tasks = [
asyncio.create_task(
invoke_get_request(eventloop)
) for _ in range(10)
]
done_tasks, _ = await asyncio.wait(tasks)
status_codes = [d.result().status_code for d in done_tasks]
return func.HttpResponse(body=json.dumps(status_codes),
mimetype='application/json')
Vertikális skálázás
Előfordulhat, hogy a magasabb specifikációkkal rendelkező prémium csomagra való frissítéssel több feldolgozási egységhez juthat, különösen a processzorhoz kötött műveletekben. Magasabb feldolgozási egységek esetén a feldolgozói folyamatok számát a rendelkezésre álló magok számának megfelelően módosíthatja, és magasabb fokú párhuzamosságot érhet el.
Következő lépések
A Azure Functions Python fejlesztésével kapcsolatos további információkért tekintse meg a következő erőforrásokat: