Az Orchestrator függvénykódjának korlátozásai
Durable Functions a Azure Functions bővítménye, amellyel állapotalapú alkalmazásokat hozhat létre. A vezénylőfüggvényekkel más tartós függvények végrehajtását is vezényelheti egy függvényalkalmazásban. Az Orchestrator-függvények állapotalapúak, megbízhatóak és hosszú ideig futnak.
Vezénylői kódkorlátozások
Az Orchestrator-függvények eseményforrásokkal biztosítják a megbízható végrehajtást és a helyi változóállapot fenntartását. A vezénylőkód visszajátszási viselkedése kényszereket hoz létre az vezénylőfüggvényekben írható kód típusára. A vezénylő függvényeinek például determinisztikusnak kell lenniük: a vezénylőfüggvények többször lesznek lejátszva, és minden alkalommal ugyanazt az eredményt kell eredményezniük.
Determinisztikus API-k használata
Ez a szakasz néhány egyszerű útmutatót tartalmaz, amelyek segítenek biztosítani, hogy a kód determinisztikus legyen.
Az Orchestrator-függvények bármilyen API-t meghívhatnak a célnyelvükön. Fontos azonban, hogy a vezénylő függvények csak determinisztikus API-kat hívjanak meg. A determinisztikus API olyan API, amely mindig ugyanazt az értéket adja vissza ugyanazzal a bemenettel, függetlenül attól, hogy mikor vagy milyen gyakran hívják meg.
Az alábbi szakaszok útmutatást nyújtanak az OLYAN API-khoz és mintákhoz, amelyeket érdemes elkerülni, mert azok nem determinisztikusak. Ezek a korlátozások csak a vezénylőfüggvényekre vonatkoznak. Más függvénytípusokra nem vonatkoznak ilyen korlátozások.
Megjegyzés
Az alábbiakban számos kódkorlátozástípust ismertetünk. Ez a lista sajnos nem átfogó, és előfordulhat, hogy egyes használati esetekről nem esik szó. A vezénylőkódok írásakor a legfontosabb szempont, hogy a használt API determinisztikus-e. Ha már így gondolkodik, könnyen megértheti, hogy mely API-k használhatók biztonságosan, és melyek nem anélkül, hogy erre a dokumentált listára kellene hivatkoznia.
Dátum és idő
Az aktuális dátumot vagy időpontot visszaadó API-k nem determinisztikusak, és soha nem használhatók vezénylőfüggvényekben. Ennek az az oka, hogy minden vezénylő függvény visszajátszása más értéket eredményez. Ehelyett az Durable Functions egyenértékű API-t kell használnia az aktuális dátum vagy időpont lekéréséhez, amely a visszajátszások között konzisztens marad.
Ne használjon DateTime.Now
, DateTime.UtcNow
vagy azzal egyenértékű API-kat az aktuális időpont lekéréséhez. Az olyan osztályokat is el kell kerülni, mint Stopwatch
amilyeneket el kell kerülni. A folyamaton belüli .NET vezénylőfüggvények esetében használja a IDurableOrchestrationContext.CurrentUtcDateTime
tulajdonságot az aktuális idő lekéréséhez. A .NET izolált vezénylőfüggvényeinél használja a TaskOrchestrationContext.CurrentDateTimeUtc
tulajdonságot az aktuális idő lekéréséhez.
DateTime startTime = context.CurrentUtcDateTime;
// do some work
TimeSpan totalTime = context.CurrentUtcDateTime.Subtract(startTime);
GUID-k és UUID-k
A véletlenszerű GUID-t vagy UUID-t visszaadó API-k nem determinisztikusak, mert a létrehozott érték minden visszajátszásnál eltérő. A használt nyelvtől függően a determinisztikus GUID-k vagy UUID-k létrehozására szolgáló beépített API is elérhető lehet. Ellenkező esetben egy tevékenységfüggvény használatával véletlenszerűen generált GUID-t vagy UUID-t ad vissza.
Ne használjon OLYAN API-kat, mint Guid.NewGuid()
véletlenszerű GUID-k létrehozása. Ehelyett a környezeti objektum API-ját NewGuid()
használva hozzon létre egy véletlenszerű GUID-t, amely biztonságos a vezénylő újrajátszásához.
Guid randomGuid = context.NewGuid();
Megjegyzés
A vezénylési környezet API-jaival létrehozott GUID-k 5-ös típusú UUID-k.
Véletlenszerű számok
Tevékenységfüggvény használatával véletlenszerű számokat ad vissza egy vezénylőfüggvénynek. A tevékenységfüggvények visszatérési értékei mindig biztonságosak a visszajátszáshoz, mert a rendszer menti őket a vezénylési előzményekbe.
Alternatív megoldásként egy fix magértékkel rendelkező véletlenszerű számgenerátor közvetlenül használható egy vezénylőfüggvényben. Ez a módszer mindaddig biztonságos, amíg az egyes vezénylési visszajátszásokhoz ugyanaz a számsor jön létre.
Kötések
A vezénylőfüggvények nem használhatnak kötéseket, beleértve még a vezénylési ügyfél - és entitásügyfél-kötéseket sem. Mindig használjon bemeneti és kimeneti kötéseket egy ügyfélen vagy tevékenységfüggvényen belül. Ez azért fontos, mert a vezénylési függvények többször is lejátszhatók, ami nemdeterminisztikus és duplikált I/O-t okoz külső rendszerekkel.
Statikus változók
Kerülje a statikus változók használatát a vezénylőfüggvényekben, mert értékük idővel változhat, ami nemdeterminisztikus futtatókörnyezeti viselkedést eredményez. Ehelyett használjon állandókat, vagy korlátozza a statikus változók használatát a tevékenységfüggvényekre.
Megjegyzés
A vezénylőfüggvényeken kívül is a statikus változók Azure Functions való használata számos okból problémás lehet, mivel nincs garancia arra, hogy a statikus állapot több függvény végrehajtása során is megmarad. A statikus változókat el kell kerülni, kivéve a nagyon specifikus használati eseteket, például a legjobb memóriabeli gyorsítótárazást a tevékenység- vagy entitásfüggvényekben.
Környezeti változók
A vezénylőfüggvényekben ne használjon környezeti változókat. Az értékek idővel változhatnak, ami nemdeterminisztikus futtatókörnyezeti viselkedést eredményez. Ha egy vezénylőfüggvénynek környezeti változóban meghatározott konfigurációra van szüksége, a konfigurációs értéket bemenetként vagy tevékenységfüggvény visszatérési értékeként kell átadnia a vezénylő függvénynek.
Hálózat és HTTP
A tevékenységfüggvények használatával kimenő hálózati hívásokat kezdeményezhet. Ha HTTP-hívást kell kezdeményeznie a vezénylő függvényből, használhatja a tartós HTTP API-kat is.
Szálblokkoló API-k
Az olyan API-k blokkolása, mint az "alvó állapot" teljesítménybeli és skálázási problémákat okozhat a vezénylői függvények esetében, ezért el kell kerülni. A Azure Functions használatalapú csomagban akár szükségtelen végrehajtási időköltségeket is eredményezhetnek. Alternatív megoldásokkal blokkolhatja az API-kat, ha elérhetők. A Tartós időzítőkkel például olyan késleltetéseket hozhat létre, amelyek biztonságosak a visszajátszáshoz, és nem számítanak bele a vezénylő függvény végrehajtási idejébe.
Aszinkron API-k
Az orchestrator-kódnak soha nem szabad aszinkron műveletet indítania, kivéve azokat, amelyeket a vezénylési eseményindító környezeti objektuma határoz meg. Például soha ne használja a , Task.Delay
a és HttpClient.SendAsync
a parancsot Task.Run
a .NET-ben vagy setTimeout
setInterval
a JavaScriptben. A vezénylőfüggvények csak tartós SDK API-k használatával ütemezhetnek aszinkron munkát, például tevékenységfüggvényeket. Minden más típusú aszinkron hívásnak tevékenységfüggvényeken belül kell lennie.
Aszinkron JavaScript-függvények
A JavaScript-vezénylő függvényeket mindig szinkron generátorfüggvényként deklarálja. Nem deklarálhat JavaScript-vezénylőfüggvényeket, async
mert a Node.js futtatókörnyezet nem garantálja, hogy az aszinkron függvények determinisztikusak.
Python-koroutine-k
A Python vezénylőfüggvényeket nem deklarálhatja coroutine-ként. Más szóval soha ne deklarálja a Python vezénylőfüggvényeket a async
kulcsszóval, mert a coroutine szemantika nem igazodik a Durable Functions visszajátszási modellhez. A Python vezénylőfüggvényeit mindig generátorként kell deklarálnia, ami azt jelenti, hogy az API-t a context
helyett kell használnia yield
await
.
.NET-szálkezelés API-k
A Durable Task Framework egyetlen szálon futtatja a vezénylési kódot, és nem tud más szálakkal kommunikálni. Ha aszinkron folytatásokat futtat egy feldolgozókészlet-szálon, a vezénylés végrehajtása nem meghatározott végrehajtást vagy holtpontot eredményezhet. Ezért a vezénylő függvények szinte soha nem használhatnak szálkezelés API-kat. Például soha ne használja ConfigureAwait(continueOnCapturedContext: false)
vezénylőfüggvényekben. Ez biztosítja, hogy a feladatfolytatások a vezénylő függvény eredetijén SynchronizationContext
fussanak.
Megjegyzés
A Durable Task Framework megpróbálja észlelni a nem vezénylőszálak véletlen használatát a vezénylőfüggvényekben. Ha szabálysértést talál, a keretrendszer egy NonDeterministicOrchestrationException kivételt jelez. Ez az észlelési viselkedés azonban nem fog minden szabálysértést észlelni, és nem szabad attól függenie.
Verziókezelés
A tartós vezénylés napokig, hónapokig, évekig vagy akár örökké is folyamatosan futhat. A befejezetlen vezényléseket befolyásoló Durable Functions alkalmazások kódfrissítései megszakíthatják a vezénylések visszajátszási viselkedését. Ezért fontos körültekintően megtervezni a kódfrissítéseket. A kód verziószámozásának részletesebb leírását a verziószámozásról szóló cikkben találja.
Tartós feladatok
Megjegyzés
Ez a szakasz a Durable Task Framework belső implementációjának részleteit ismerteti. A tartós függvényeket anélkül használhatja, hogy ismerné ezeket az információkat. Ez csak a visszajátszási viselkedés megértését szolgálja.
A vezénylői függvényekben biztonságosan várakozó feladatokat időnként tartós feladatoknak nevezzük. A Durable Task Framework létrehozza és kezeli ezeket a feladatokat. Ilyenek például a , WaitForExternalEvent
és CreateTimer
a .NET-vezénylő függvények által CallActivityAsync
visszaadott feladatok.
Ezeket a tartós feladatokat a .NET objektumlistája TaskCompletionSource
belsőleg kezeli. A visszajátszás során ezek a feladatok a vezénylőkód végrehajtásának részeként jönnek létre. A kézbesítő befejezi a megfelelő előzményesemények számbavételét.
A feladatok szinkron módon, egyetlen szál használatával lesznek végrehajtva, amíg az összes előzményt vissza nem játsszák. Azok a tartós feladatok, amelyek nem fejeződnek be az előzmény-visszajátszás végére, megfelelő műveleteket hajtanak végre. Előfordulhat például, hogy egy üzenet meghív egy tevékenységfüggvényt.
Ez a szakasz a futtatókörnyezet viselkedésének leírásával segít megérteni, hogy egy vezénylőfüggvény miért nem használható await
vagy yield
nem használható feladatban. Ennek két oka lehet: a kézbesítőszál nem tudja megvárni a feladat befejezését, és a feladat visszahívása potenciálisan ronthatja a vezénylő függvény nyomkövetési állapotát. A szabálysértések észleléséhez futásidejű ellenőrzéseket is végeznek.
Ha többet szeretne megtudni arról, hogy a Durable Task Framework hogyan hajtja végre a vezénylői függvényeket, tekintse meg a Tartós feladat forráskódját a GitHubon. Lásd: TaskOrchestrationExecutor.cs és TaskOrchestrationContext.cs.