Megosztás a következőn keresztül:


Verziószámozás Durable Functions (Azure Functions)

Elkerülhetetlen, hogy a függvények hozzáadva, eltávolítva és módosítva legyenek az alkalmazások élettartama során. Durable Functions lehetővé teszi a láncoló függvények összefűzését olyan módokon, amelyek korábban nem voltak lehetségesek, és ez a láncolás hatással van a verziószámozás kezelésére.

Kompatibilitástörő változások kezelése

Számos példa van a kompatibilitástörő változásokra, amelyeket figyelembe kell venni. Ez a cikk a leggyakoribbakat ismerteti. A fő téma mögöttük az áll, hogy az új és a meglévő függvényvezényléseket is érintik a függvénykód módosításai.

Tevékenység- vagy entitásfüggvény-aláírások módosítása

Az aláírás módosítása egy függvény nevének, bemenetének vagy kimenetének változására utal. Ha ez a fajta módosítás egy tevékenység- vagy entitásfüggvényen történik, az megszakíthatja az attól függő vezénylőfüggvényeket. Ez különösen igaz a típusbiztos nyelvekre. Ha a módosításnak megfelelően frissíti az orchestrator függvényt, megszakíthatja a meglévő tesztpéldányokat.

Tegyük fel például, hogy a következő vezénylőfüggvénnyel rendelkezünk.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Ez a leegyszerűsítő függvény a Foo eredményeit veszi fel, és átadja a Barnak. Tegyük fel, hogy a Foo visszatérési értékét logikai értékről sztringre kell módosítanunk az eredményértékek szélesebb körének támogatásához. Az eredmény a következőhöz hasonló:

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string result = await context.CallActivityAsync<string>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Ez a változás jól működik a vezénylőfüggvény összes új példánya esetében, de megszakíthatja a repülés közbeni példányokat. Vegyük például azt az esetet, amikor egy vezénylési példány meghív egy nevű Foofüggvényt, visszaad egy logikai értéket, majd ellenőrzőpontokat. Ha az aláírás módosítása ezen a ponton van üzembe helyezve, az ellenőrzőponttal megadott példány azonnal meghiúsul, amikor újraindul, és visszajátssza a hívását.Foo Ez a hiba azért fordul elő, mert az előzménytáblában szereplő eredmény logikai érték, de az új kód megpróbálja sztringértékké deszerializálni, ami váratlan viselkedést vagy futásidejű kivételt eredményez a típusbiztos nyelvek esetében.

Ez a példa csak egy a számos különböző módszer közül, amellyel egy függvény aláírásának módosítása megszakíthatja a meglévő példányokat. Általánosságban elmondható, hogy ha egy vezénylőnek módosítania kell a függvények hívási módját, akkor a változás valószínűleg problémás lesz.

A vezénylő logikája módosítása

A verziószámozási problémák másik osztálya a vezénylőfüggvény kódjának olyan módosítása, amely megváltoztatja a tesztkörnyezeti példányok végrehajtási útvonalát.

Vegye figyelembe a következő vezénylőfüggvényt:

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Most tegyük fel, hogy módosítani szeretne egy új függvényhívást a két meglévő függvényhívás között.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    if (result)
    {
        await context.CallActivityAsync("SendNotification");
    }

    await context.CallActivityAsync("Bar", result);
}

Ez a módosítás hozzáad egy új függvényhívást a SendNotification függvényhez Foo és Bar között. Nincsenek aláírásváltozások. A probléma akkor merül fel, ha egy meglévő példány újraindul a Bar hívásából. A visszajátszás során, ha a Foo eredeti hívása vissza lett adva true, akkor a vezénylő visszajátszása meghívja a SendNotification metódust, amely nem szerepel a végrehajtási előzményeiben. A futtatókörnyezet észleli ezt az inkonzisztenciát, és nem determinisztikus vezénylési hibát okoz, mert a SendNotification hívása történt, amikor a sáv hívását várta. Ugyanez a probléma akkor fordulhat elő, ha API-hívásokat ad hozzá más tartós műveletekhez, például tartós időzítőket hoz létre, külső eseményekre vár, alvezényléseket hív meg stb.

Kockázatcsökkentési stratégiák

Íme néhány stratégia a verziószámozási kihívások kezelésére:

  • Ne tegyen semmit (nem ajánlott)
  • Az összes folyamatban lévő példány leállítása
  • Párhuzamos üzembe helyezések

Semmit sem tehet

A verziószámozás naiv megközelítése, hogy semmit sem tesz, és hagyja, hogy a repülés közbeni vezénylési példányok meghiúsuljanak. A változás típusától függően a következő típusú hibák fordulhatnak elő.

  • A vezénylések nem determinisztikus vezénylési hibával meghiúsulhatnak.
  • A vezénylések határozatlan ideig elakadhatnak, és állapotot jelenthetnek Running .
  • Ha egy függvény el lesz távolítva, bármely függvény, amely megpróbálja meghívni, hibával meghiúsulhat.
  • Ha a rendszer eltávolít egy függvényt az ütemezett futtatás után, akkor előfordulhat, hogy az alkalmazás alacsony szintű futásidejű hibákat tapasztal a Durable Task Framework motorban, ami súlyos teljesítménycsökkenést okozhat.

A lehetséges hibák miatt nem ajánlott a "semmit tenni" stratégia.

Az összes folyamatban lévő példány leállítása

Egy másik lehetőség az összes tesztpéldány leállítása. Ha az alapértelmezett Azure Storage-szolgáltatót használja a Durable Functions, az összes példány leállítása a belső vezérlősor és a workitem-queue üzenetsor tartalmának törlésével végezhető el. Másik lehetőségként leállíthatja a függvényalkalmazást, törölheti ezeket az üzenetsorokat, majd újraindíthatja az alkalmazást. Az üzenetsorok automatikusan újra létrejönnek, amint az alkalmazás újraindul. Előfordulhat, hogy a korábbi vezénylési példányok határozatlan ideig "Fut" állapotban maradnak, de nem fogják átnézni a naplókat hibaüzenetekkel, és nem okoznak kárt az alkalmazásban. Ez a megközelítés ideális a prototípus gyors fejlesztéséhez, beleértve a helyi fejlesztést is.

Megjegyzés

Ez a megközelítés közvetlen hozzáférést igényel a mögöttes tárolási erőforrásokhoz, és nem felelek meg az Durable Functions által támogatott összes tárolószolgáltatónak.

Párhuzamos üzembe helyezések

A kompatibilitástörő változások biztonságos üzembe helyezésének legbiztosabb módja az, ha a régebbi verziókkal együtt helyezi üzembe őket. Ez a következő technikák bármelyikével végezhető el:

  • Helyezze üzembe az összes frissítést teljesen új függvényként, így a meglévő függvények is megmaradnak. Ez általában nem ajánlott az új függvényverziók hívóinak rekurzív frissítésének összetettsége miatt.
  • Helyezze üzembe az összes frissítést új függvényalkalmazásként egy másik tárfiókkal.
  • Helyezze üzembe a függvényalkalmazás új példányát ugyanazzal a tárfiókkal, de a feladatközpont frissített nevével. Ez új tárolási összetevők létrehozását eredményezi, amelyeket az alkalmazás új verziója használhat. Az alkalmazás régi verziója továbbra is az előző tárolóösszetevő-készlettel lesz végrehajtva.

A párhuzamos üzembe helyezés az ajánlott módszer a függvényalkalmazások új verzióinak üzembe helyezéséhez.

Megjegyzés

Ez az útmutató a párhuzamos üzembe helyezési stratégiához az Azure Storage-specifikus kifejezéseket használja, de általában az összes támogatott Durable Functions tárolószolgáltatóra vonatkozik.

Üzembe helyezési pontok

Ha párhuzamos üzembe helyezést végez Azure Functions vagy Azure App Service, javasoljuk, hogy helyezze üzembe a függvényalkalmazás új verzióját egy új üzembehelyezési ponton. Az üzembehelyezési pontok lehetővé teszik a függvényalkalmazás több példányának párhuzamos futtatását, amelyek közül csak az egyiket tekinti aktív éles tárolóhelynek . Ha készen áll arra, hogy elérhetővé tegye az új vezénylési logikát a meglévő infrastruktúrának, az egyszerűen felcserélheti az új verziót az éles üzembe helyezési pontra.

Megjegyzés

Ez a stratégia akkor működik a legjobban, ha HTTP- és webhook-eseményindítókat használ a vezénylési függvényekhez. A nem HTTP-eseményindítók, például az üzenetsorok vagy az Event Hubs esetében az eseményindító definíciójának egy olyan alkalmazásbeállításból kell származnia , amely a felcserélési művelet részeként frissül.

Következő lépések