A Service Fabric Reliable Actors bemutatása

A Reliable Actors egy Service Fabric-alkalmazás-keretrendszer, amely a virtuális aktor mintáján alapul. A Reliable Actors API egy egyszálú programozási modellt biztosít, amely a Service Fabric skálázhatósági és megbízhatósági garanciáira épül.

Mik azok az Actorsek?

Az aktor egy elkülönített, független számítási és állapotegység, amely egyszálas végrehajtással rendelkezik. Az aktorminta olyan párhuzamos vagy elosztott rendszerek számítási modellje, amelyekben ezen szereplők nagy száma egyidejűleg és egymástól függetlenül is végrehajtható. A színészek kommunikálhatnak egymással, és további színészeket hozhatnak létre.

Mikor érdemes a Reliable Actorst használni?

A Service Fabric Reliable Actors a szereplők tervezési mintájának implementációja. Mint minden szoftvertervezési minta esetében, az adott minta használatának eldöntése attól függ, hogy egy szoftvertervezési probléma megfelel-e a mintának.

Bár az aktor tervezési mintája jó választás lehet számos elosztott rendszerproblémához és forgatókönyvhöz, alaposan figyelembe kell venni a minta korlátait és az azt megvalósító keretrendszert. Általános útmutatásként tekintse át az aktormintát a probléma vagy forgatókönyv modellezéséhez, ha:

  • A problématér nagy számú (több ezer vagy több) kis, független és elkülönített állapot- és logikai egységből áll.
  • Olyan egyszálú objektumokkal szeretne dolgozni, amelyek nem igényelnek jelentős interakciót a külső összetevőktől, beleértve a lekérdezési állapotot a szereplők egy csoportjában.
  • Az aktorpéldányok nem blokkolják a kiszámíthatatlan késésű hívókat az I/O-műveletek kiadásával.

Aktorok a Service Fabricben

A Service Fabricben az aktorok a Reliable Actors keretrendszerben vannak implementálva: a Service Fabric Reliable Servicesre épülő aktorminta-alapú alkalmazás-keretrendszerben. Minden megírt Reliable Aktor-szolgáltatás valójában egy particionált, állapotalapú Reliable Service.

Minden aktor egy aktortípus példányaként van definiálva, amely megegyezik a .NET-objektumok .NET-típusú példányával. Lehet például egy aktortípus, amely megvalósítja a számológép funkcióit, és számos ilyen típusú szereplő lehet, amelyek egy fürt különböző csomópontjai között vannak elosztva. Minden ilyen szereplőt egyedileg azonosít egy aktorazonosító.

Színész élettartama

A Service Fabric-szereplők virtuálisak, ami azt jelenti, hogy élettartamuk nincs a memóriában való ábrázolásukhoz kötve. Ennek eredményeképpen nem kell explicit módon létrehozni vagy megsemmisíteni őket. A Reliable Actors futtatókörnyezet automatikusan aktivál egy aktort, amikor először kap kérést az adott aktorazonosítóra vonatkozóan. Ha egy aktort egy ideig nem használ, a Reliable Actors futtatókörnyezete szemétgyűjtéssel gyűjti össze a memóriában lévő objektumot. Emellett a színész létezéséről is tud, ha később újra kell aktiválni. További részletekért lásd: Aktoréletciklus és szemétgyűjtés.

Ez a virtuális aktor élettartam-absztrakciója a virtuális aktormodell eredményeképpen bizonyos kikötéseket hordoz, és valójában a Reliable Actors implementációja időnként eltér ettől a modelltől.

  • Az aktor automatikusan aktiválódik (ami egy aktorobjektum létrehozását okozza) az üzenet első elküldésekor az aktorazonosítónak. Bizonyos idő elteltével az aktorobjektum szemétgyűjtésre kerül. A jövőben az aktorazonosító újbóli használatával létrejön egy új aktorobjektum. A színész állapota túllépi az objektum élettartamát, amikor az állapotkezelőben tárolja.
  • Az aktorazonosító bármely aktormetódusának meghívása aktiválja az adott aktort. Ezért az aktortípusok konstruktorát implicit módon hívja meg a futtatókörnyezet. Ezért az ügyfélkód nem tud paramétereket átadni az aktortípus konstruktorának, bár a paramétereket maga a szolgáltatás is átadhatja az aktor konstruktorának. Ennek az az eredménye, hogy az aktorok részben inicializált állapotban hozhatók létre, mire más metódusok meghívása történik, ha az aktor inicializálási paramétereket igényel az ügyféltől. Nincs egyetlen belépési pont az ügyfélből származó aktor aktiválásához.
  • Bár a Reliable Actors implicit módon hoz létre aktorobjektumokat; lehetősége van arra, hogy explicit módon törölje az aktort és annak állapotát.

Elosztás és feladatátvétel

A méretezhetőség és a megbízhatóság biztosítása érdekében a Service Fabric elosztja az aktorokat a fürtben, és szükség szerint automatikusan áttelepíti őket a hibás csomópontokról az kifogástalan állapotúra. Ez egy particionált, állapotalapú Reliable Service-szolgáltatás absztrakciója. Az elosztást, a méretezhetőséget, a megbízhatóságot és az automatikus feladatátvételt az határozza meg, hogy az aktorok az Aktor szolgáltatás nevű állapotalapú Reliable szolgáltatásban futnak.

Az Aktorok az Aktor szolgáltatás partíciói között vannak elosztva, és ezek a partíciók egy Service Fabric-fürt csomópontjai között vannak elosztva. Minden szolgáltatáspartíció egy-egy szereplőkészletet tartalmaz. A Service Fabric kezeli a szolgáltatáspartíciók elosztását és feladatátvételét.

Egy olyan aktorszolgáltatás például, amelynek kilenc partíciója három csomópontra van üzembe helyezve az alapértelmezett aktorpartíció elhelyezésével, így oszlik el:

Reliable Actors-disztribúció

Az Aktor-keretrendszer kezeli a partíciósémát és a kulcstartomány beállításait. Ez leegyszerűsít néhány választási lehetőséget, de figyelembe is veszi a következőket:

  • A Reliable Services lehetővé teszi a particionálási séma, a kulcstartomány (tartományparticionálási séma használata esetén) és a partíciók számának kiválasztását. A Reliable Actors a tartományparticionálási sémára (az egységes Int64-sémára) korlátozódik, és a teljes Int64-kulcstartományt kell használnia.
  • Alapértelmezés szerint az aktorok véletlenszerűen vannak elhelyezve a partíciókban, ami egységes eloszlást eredményez.
  • Mivel az aktorok véletlenszerűen vannak elhelyezve, elvárás, hogy az aktorműveletek mindig hálózati kommunikációt igényeljenek, beleértve a metódushívási adatok szerializálását és deszerializálását, a késést és a többletterhelést.
  • Speciális forgatókönyvekben az aktorpartíciók elhelyezését az adott partíciókra leképezett Int64 aktorazonosítók használatával szabályozhatja. Ez azonban a szereplők partíciók közötti kiegyensúlyozatlan elosztását eredményezheti.

Az aktorszolgáltatások particionálásával kapcsolatos további információkért tekintse meg az aktorok particionálási fogalmait.

Aktorok kommunikációja

Az aktor-interakciók olyan felületen vannak meghatározva, amelyet az interfészt megvalósító aktor oszt meg, és az ügyfél, amely ugyanazon a felületen keresztül proxyt kap egy aktorhoz. Mivel ez a felület aszinkron aktormetódusok meghívására szolgál, az illesztő minden metódusának Feladatvisszaadónak kell lennie.

A metódushívások és azok válaszai végső soron hálózati kéréseket eredményeznek a fürtön, így az általuk visszaadott tevékenységek argumentumainak és eredménytípusainak szerializálhatónak kell lenniük a platformon. Különösen az adatszerződés szerializálhatónak kell lennie.

Az aktorproxy

A Reliable Actors ügyfél API kommunikációt biztosít egy aktorpéldány és egy aktorügyfél között. Az aktorral való kommunikációhoz az ügyfél létrehoz egy aktorproxy-objektumot, amely megvalósítja az aktor felületét. Az ügyfél a proxyobjektum metódusainak meghívásával kommunikál az aktorral. Az aktorproxy ügyfél-aktor és aktor-aktor közötti kommunikációhoz használható.

// Create a randomly distributed actor ID
ActorId actorId = ActorId.CreateRandom();

// This only creates a proxy object, it does not activate an actor or invoke any methods yet.
IMyActor myActor = ActorProxy.Create<IMyActor>(actorId, new Uri("fabric:/MyApp/MyActorService"));

// This will invoke a method on the actor. If an actor with the given ID does not exist, it will be activated by this method call.
await myActor.DoWorkAsync();
// Create actor ID with some name
ActorId actorId = new ActorId("Actor1");

// This only creates a proxy object, it does not activate an actor or invoke any methods yet.
MyActor myActor = ActorProxyBase.create(actorId, new URI("fabric:/MyApp/MyActorService"), MyActor.class);

// This will invoke a method on the actor. If an actor with the given ID does not exist, it will be activated by this method call.
myActor.DoWorkAsync().get();

Vegye figyelembe, hogy az aktorproxy-objektum létrehozásához használt két információ az aktor azonosítója és az alkalmazás neve. Az aktor azonosítója egyedileg azonosítja az aktort, az alkalmazás neve pedig azt a Service Fabric-alkalmazást , amelyben az aktor üzembe van helyezve.

Az ActorProxyügyféloldali (C#) / ActorProxyBase(Java) osztály végrehajtja a szükséges megoldást az aktor azonosító alapján történő megkereséséhez és egy kommunikációs csatorna megnyitásához. A rendszer a kommunikációs hibák és feladatátvételek esetén is újrapróbálkozhat a szereplő megkeresésével. Ennek eredményeképpen az üzenetkézbesítés a következő jellemzőkkel rendelkezik:

  • Az üzenetek kézbesítése a legjobb erőfeszítés.
  • Az aktorok duplikált üzeneteket kaphatnak ugyanabból az ügyfélből.

Egyidejűség

A Reliable Actors futtatókörnyezet egyszerű, turn-alapú hozzáférési modellt biztosít az aktor metódusainak eléréséhez. Ez azt jelenti, hogy az aktorobjektum kódjában egynél több szál nem lehet aktív. A turn-based hozzáférés jelentősen leegyszerűsíti az egyidejű rendszereket, mivel nincs szükség szinkronizálási mechanizmusokra az adathozzáféréshez. Ez azt is jelenti, hogy a rendszereket speciális szempontok alapján kell megtervezni az egyes aktorpéldányok egyszálas hozzáférési jellegére vonatkozóan.

  • Egyetlen aktorpéldány egyszerre nem tud több kérést feldolgozni. Az aktorpéldányok átviteli sebességbeli szűk keresztmetszetet okozhatnak, ha várhatóan egyidejű kéréseket fognak kezelni.
  • A színészek holtpontot hozhatnak egymással, ha két szereplő között körkörös kérés van, miközben egy külső kérést küld az egyik szereplőnek egyidejűleg. Az aktor futtatókörnyezete automatikusan időtúllépést jelez az aktorhívásokon, és kivételt küld a hívónak a lehetséges holtponthelyzetek megszakítása érdekében.

Reliable Actors-kommunikáció

Turn-based access

A sor egy aktormetódus teljes végrehajtásából áll, amely más szereplők vagy ügyfelek kérésére adott válaszként, vagy egy időzítő/emlékeztető visszahívás teljes végrehajtásából áll. Bár ezek a metódusok és visszahívások aszinkronok, az Actors-futtatókörnyezet nem fonódik össze. Az új sor engedélyezése előtt egy sornak teljesen be kell fejeződnie. Más szóval a jelenleg futó aktormetódust vagy időzítőt/emlékeztető visszahívást teljesen be kell fejezni, mielőtt engedélyezve lenne egy metódus vagy visszahívás új hívása. Egy metódus vagy visszahívás akkor tekinthető befejezettnek, ha a végrehajtás a metódusból vagy visszahívásból lett visszaadva, és a metódus vagy visszahívás által visszaadott feladat befejeződött. Érdemes kiemelni, hogy a turn-alapú egyidejűség a különböző módszerek, időzítők és visszahívások esetében is tiszteletben van tartva.

Az Actors-futtatókörnyezet a turn-alapú egyidejűséget úgy kényszeríti ki, hogy a fordulás elején egy aktoronkénti zárolást szerez be, és a sor végén feloldja a zárolást. Így a fordulásalapú egyidejűség aktoronként van kikényszerítve, nem pedig az aktorok között. Az aktor metódusai és az időzítő/emlékeztető visszahívások egyszerre hajthatók végre a különböző szereplők nevében.

Az alábbi példa a fenti fogalmakat szemlélteti. Vegyünk egy aktortípust, amely két aszinkron metódust implementál (például Method1 és Method2), egy időzítőt és egy emlékeztetőt. Az alábbi ábrán egy példa látható ezen metódusok és visszahívások végrehajtásának ütemtervére két szereplő (ActorId1 és ActorId2) nevében, amelyek ehhez az aktortípushoz tartoznak.

Reliable Actors runtime turn-based concurrency and access

Ez az ábra a következő konvenciók szerint jelenik meg:

  • Minden függőleges vonal egy metódus vagy egy adott szereplő nevében történő visszahívás végrehajtásának logikai folyamatát mutatja.
  • Az egyes függőleges vonalakon megjelölt események időrendi sorrendben következnek be, és az újabb események a régebbiek alatt következnek be.
  • A különböző szereplőknek megfelelő idősorok különböző színeket használnak.
  • A kiemelés azt az időtartamot jelzi, amelyre vonatkozóan a színészenkénti zárolás egy metódus vagy visszahívás nevében van tárolva.

Néhány fontos szempont:

  • Míg az 1. metódus az ActorId2 nevében fut az xyz789 ügyfélkérésre válaszul, egy másik ügyfélkérés (abc123) érkezik, amely az 1. metódust is az ActorId2 által hajtja végre. Az 1. módszer második végrehajtása azonban csak akkor kezdődik meg, ha az előző végrehajtás befejeződött. Hasonlóképpen, az ActorId2 által regisztrált emlékeztető aktiválódik, miközben az 1. metódus végrehajtása az xyz789 ügyfélkérésre válaszul történik. Az emlékeztető visszahívás csak akkor lesz végrehajtva, ha az 1. módszer mindkét végrehajtása befejeződött. Mindez annak köszönhető, hogy az AktorId2 esetében a fordulóalapú egyidejűség van kényszerítve.
  • Hasonlóképpen, a turn-alapú egyidejűség is kikényszeríthető az ActorId1 esetében, amint azt az 1. módszer, a 2. módszer és az Időzítő visszahívása az ActorId1 nevében, soros módon történik.
  • Az 1. metódus az ActorId1 nevében történő végrehajtása átfedésben van az ActorId2 nevében történő végrehajtásával. Ennek az az oka, hogy a fordulóalapú egyidejűség csak egy szereplőn belül van kényszerítve, nem pedig a szereplők között.
  • Egyes metódus-/visszahívási végrehajtásokban a Taskmetódus/visszahívás által visszaadott (C#) / CompletableFuture(Java) befejeződik a metódus visszatérése után. Néhány más esetben az aszinkron művelet már befejeződött, mire a metódus/visszahívás visszatér. Az aktoronkénti zárolás mindkét esetben csak a metódus/visszahívás visszatérése és az aszinkron művelet befejeződése után szabadul fel.

Újbóli belépés

Az Actors-futtatókörnyezet alapértelmezés szerint engedélyezi az újrabetöltést. Ez azt jelenti, hogy ha az A aktor egy aktor metódusa meghív egy metódust a B aktoron, amely viszont egy másik metódust hív meg az A színészen, akkor ez a metódus futtatható. Ennek az az oka, hogy ugyanahhoz a logikai híváslánc-környezethez tartozik. Minden időzítő- és emlékeztetőhívás az új logikai hívási környezettel kezdődik. További részletekért tekintse meg a Reliable Actors újbóli belépését ismertető cikket.

Az egyidejűségi garanciák hatóköre

Az Actors-futtatókörnyezet biztosítja ezeket az egyidejűségi garanciákat olyan helyzetekben, amikor a metódusok meghívását szabályozza. Ezek a garanciák biztosítják például az ügyfélkérésekre adott válaszként végrehajtott metódushívásokat, valamint az időzítő és az emlékeztető visszahívások esetében. Ha azonban az aktorkód közvetlenül meghívja ezeket a metódusokat az Actors-futtatókörnyezet által biztosított mechanizmusokon kívül, akkor a futtatókörnyezet nem tud egyidejűségi garanciákat biztosítani. Ha például a metódust egy olyan tevékenység kontextusában hívja meg a rendszer, amely nincs társítva az aktor metódusok által visszaadott feladattal, akkor a futtatókörnyezet nem tud egyidejűségi garanciákat nyújtani. Ha a metódust egy olyan szálból hívja meg a rendszer, amelyet a szereplő önállóan hoz létre, akkor a futtatókörnyezet sem tud egyidejűségi garanciákat nyújtani. Ezért a háttérműveletek végrehajtásához a szereplőknek olyan aktor-időzítőket és aktoremlékeket kell használniuk, amelyek tiszteletben tartják a fordulóalapú egyidejűséget.

Következő lépések

Első lépések az első Reliable Actors szolgáltatás kiépítésével: