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.
Az 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
Az Azure Functions alapértelmezés szerint automatikusan figyeli az alkalmazás terhelését, és szükség szerint több gazdapéldányt hoz létre a Pythonhoz. Az 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ó: Eseményvezérelt skálázás az Azure Functionsben.
Az átviteli sebesség teljesítményének javítása
Az alapértelmezett konfigurációk az Azure Functions-alkalmazások többségéhez 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.
| Számítási feladat 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 |
| CPU-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 függvények számítási feladatai általában az I/O és a CPU-kötések kombinációját képezik, valós éles terhelések mellett kell profilba helyezni 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.
- Aszinkron
- 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
Aszinkron
Mivel a Python egyszálas futtatókörnyezet, a Python gazdagéppéldánya alapértelmezés szerint csak egy függvényhívást tud 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
- adatfolyamok API – Magas szintű aszinkron/várakozásra kész primitívek a hálózati kapcsolat használatához
- Janus Queue – A Python szálbiztos aszinkron üzenetsora
- pyzmq – Python-kötések a ZeroMQ-hoz
Az aszinkron megértése a Python-feldolgozóban
Ha egy függvény aláírása előtt definiálja async a függvényt, a Python koroutinként jelöli meg a függvényt. Amikor meghívja a koroutint, az ütemezhető tevékenységként egy eseményhurokba. 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ó megosztja az eseményhurkot az ügyfél async függvényével, é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 növeli a függvény átviteli sebességét azokkal a kódtárakkal összehasonlítva, amelyek szinkron implementálása esetén történik.
Megjegyzés:
Ha a függvény úgy van deklarálva, hogy async a megvalósításon belül nincs ilyen await , 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 alkalmazásbeállítás használatával FUNCTIONS_WORKER_PROCESS_COUNT növelheti a feldolgozói folyamatok állomásonkénti számát (akár 10-et is). Az 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ány-termékváltozatok.
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 feldolgozószám beállítása hatással lehet az általános teljesítményre a szükséges környezeti kapcsolók megnövekedett száma miatt.
Az FUNCTIONS_WORKER_PROCESS_COUNT Azure Functions által az alkalmazás igény szerinti skálázása során létrehozott összes gazdagépre vonatkozik.
Maximális feldolgozó beállítása egy nyelvi feldolgozói folyamaton belül
Ahogy az aszinkron szakaszban is említettük, a Python nyelvi feldolgozója másképp kezeli a függvényeket és a koroutinokat . 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 max_worker ThreadPoolExecutor objektum argumentumát, amely lehetővé teszi, hogy a Python legfeljebb max_worker szálból álló készletet használjon a hívások aszinkron végrehajtásához. Ez PYTHON_THREADPOOL_THREAD_COUNT vonatkozik a Functions-gazdagép által létrehozott összes feldolgozóra, és a 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) max_worker esetében az érték 1. Python-verzió 3.9 max_worker esetén a beállítás értéke None.
A processzorhoz kötött alkalmazások esetében a beállítást alacsony számon kell tartania, 1-től kezdve, és a számítási feladattal való kísérletezés során növekednie kell. 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. A javaslat az, hogy a Python alapértelmezett értékével (a magok számával) + 4-gyel kezdje, majd a megjelenő átviteli sebesség értékek alapján finomhangolást végezze el.
Vegyes számítási feladatok alkalmazásai esetében az átviteli sebesség maximalizálása érdekében ki kell egyensúlyoznia mind a kettőt, mind FUNCTIONS_WORKER_PROCESS_COUNT PYTHON_THREADPOOL_THREAD_COUNT a 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 további információt a megbízható Azure Functions ajánlott eljárásaiban talál.
Eseményhurok kezelése
Aszinkron kompatibilis külső kódtárakat kell használnia. Ha egyik külső kódtár sem felel meg az igényeinek, az Azure Functionsben is kezelheti az eseményhurkokat. 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-dokumentum foglalkozik a Coroutines és a Tasks és az Event Loop használatával a beépített aszinkron kódtár használatával.
Vegyük példaként a következő kéréstárat. Ez a kódrészlet az asyncio kódtár használatával tördeli a requests.get() metódust egy koroutinba, és egyszerre több webes kérést futtat SAMPLE_URL.
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
Az Azure Functions Python fejlesztésével kapcsolatos további információkért tekintse meg a következő erőforrásokat: