Introduktion till Service Fabric Reliable Actors

Reliable Actors är ett Service Fabric-programramverk baserat på mönstret Virtuell aktör . Reliable Actors-API:et tillhandahåller en enkeltrådad programmeringsmodell som bygger på skalbarhets- och tillförlitlighetsgarantierna som tillhandahålls av Service Fabric.

Vad är Skådespelare?

En aktör är en isolerad, oberoende enhet för beräkning och tillstånd med en trådad körning. Aktörsmönstret är en beräkningsmodell för samtidiga eller distribuerade system där ett stort antal av dessa aktörer kan köras samtidigt och oberoende av varandra. Aktörer kan kommunicera med varandra och de kan skapa fler aktörer.

När du ska använda Reliable Actors

Service Fabric Reliable Actors är en implementering av aktörens designmönster. Precis som med alla mönster för programvarudesign fattas beslutet om ett specifikt mönster ska användas baserat på om ett programvarudesignproblem passar mönstret eller inte.

Även om aktörens designmönster kan passa bra för ett antal problem och scenarier med distribuerade system, måste du noga överväga begränsningarna i mönstret och ramverket som implementerar det. Som allmän vägledning bör du överväga aktörsmönstret för att modellera ditt problem eller scenario om:

  • Ditt problemutrymme omfattar ett stort antal (tusentals eller fler) små, oberoende och isolerade enheter med tillstånd och logik.
  • Du vill arbeta med entrådade objekt som inte kräver betydande interaktion från externa komponenter, inklusive frågetillstånd för en uppsättning aktörer.
  • Dina aktörsinstanser blockerar inte uppringare med oförutsägbara fördröjningar genom att utfärda I/O-åtgärder.

Aktörer i Service Fabric

I Service Fabric implementeras aktörer i ramverket Reliable Actors: Ett aktörsmönsterbaserat programramverk som bygger på Service Fabric Reliable Services. Varje Reliable Actor-tjänst som du skriver är faktiskt en partitionerad, tillståndskänslig tillförlitlig tjänst.

Varje aktör definieras som en instans av en aktörstyp, identisk med hur ett .NET-objekt är en instans av en .NET-typ. Det kan till exempel finnas en aktörstyp som implementerar funktionerna i en kalkylator och det kan finnas många aktörer av den typen som distribueras på olika noder i ett kluster. Varje sådan aktör identifieras unikt av ett aktörs-ID.

Livslängd för skådespelare

Service Fabric-aktörer är virtuella, vilket innebär att deras livslängd inte är kopplad till deras minnesinterna representation. Därför behöver de inte skapas eller förstöras uttryckligen. Reliable Actors-körningen aktiverar automatiskt en aktör första gången den tar emot en begäran om det aktörs-ID:t. Om en aktör inte används under en viss tidsperiod samlar Reliable Actors-skräpkörningen in det minnesinterna objektet. Det kommer också att upprätthålla kunskap om aktörens existens om den behöver återaktiveras senare. Mer information finns i Aktörens livscykel och skräpinsamling.

Den här livslängdsabstraktionen för den virtuella aktören innehåller vissa varningar som ett resultat av modellen för virtuell aktör, och i själva verket avviker Reliable Actors-implementeringen ibland från den här modellen.

  • En aktör aktiveras automatiskt (vilket gör att ett aktörsobjekt skapas) första gången ett meddelande skickas till dess aktörs-ID. Efter en viss tidsperiod samlas aktörsobjektet in. I framtiden kommer ett nytt aktörsobjekt att konstrueras med hjälp av aktörs-ID:t igen. En aktörs tillstånd överlever objektets livslängd när det lagras i tillståndshanteraren.
  • Om du anropar en aktörsmetod för ett aktörs-ID aktiveras den aktören. Av den anledningen har aktörstyper sin konstruktor som implicit anropas av körningen. Klientkoden kan därför inte skicka parametrar till aktörstypens konstruktor, även om parametrar kan skickas till aktörens konstruktor av själva tjänsten. Resultatet är att aktörer kan konstrueras i ett delvis initierat tillstånd när andra metoder anropas på den, om aktören kräver initieringsparametrar från klienten. Det finns ingen enskild startpunkt för aktivering av en aktör från klienten.
  • Även om Reliable Actors implicit skapar aktörsobjekt; du har möjlighet att uttryckligen ta bort en aktör och dess tillstånd.

Distribution och redundans

För att ge skalbarhet och tillförlitlighet distribuerar Service Fabric aktörer i hela klustret och migrerar dem automatiskt från misslyckade noder till felfria efter behov. Det här är en abstraktion över en partitionerad, tillståndskänslig tillförlitlig tjänst. Distribution, skalbarhet, tillförlitlighet och automatisk redundans tillhandahålls alla på grund av att aktörer körs i en tillståndskänslig Reliable Service som kallas aktörstjänsten.

Aktörer distribueras över partitionerna i aktörstjänsten och dessa partitioner distribueras över noderna i ett Service Fabric-kluster. Varje tjänstpartition innehåller en uppsättning aktörer. Service Fabric hanterar distribution och redundans för tjänstpartitionerna.

Till exempel distribueras en aktörstjänst med nio partitioner som distribueras till tre noder med standardplaceringen för aktörspartition:

Reliable Actors-distribution

Actor Framework hanterar partitionsschema och nyckelintervallinställningar åt dig. Detta förenklar vissa val men tar också hänsyn till följande:

  • Med Reliable Services kan du välja ett partitioneringsschema, nyckelintervall (när du använder ett intervallpartitioneringsschema) och partitionsantal. Reliable Actors är begränsat till intervallpartitioneringsschemat (det enhetliga Int64-schemat) och kräver att du använder hela Int64-nyckelintervallet.
  • Som standard placeras aktörer slumpmässigt i partitioner vilket resulterar i en enhetlig fördelning.
  • Eftersom aktörer placeras slumpmässigt bör det förväntas att aktörsåtgärder alltid kräver nätverkskommunikation, inklusive serialisering och deserialisering av metodanropsdata, vilket medför svarstid och omkostnader.
  • I avancerade scenarier är det möjligt att styra aktörens partitionsplacering med hjälp av Int64-aktörs-ID:er som mappar till specifika partitioner. Detta kan dock resultera i en obalanserad fördelning av aktörer mellan partitioner.

Mer information om hur aktörstjänster partitioneras finns i partitioneringsbegrepp för aktörer.

Aktörskommunikation

Aktörsinteraktioner definieras i ett gränssnitt som delas av aktören som implementerar gränssnittet och klienten som hämtar en proxy till en aktör via samma gränssnitt. Eftersom det här gränssnittet används för att anropa aktörsmetoder asynkront måste varje metod i gränssnittet vara Uppgiftsretur.

Metodanrop och deras svar resulterar i slutänden i nätverksbegäranden i klustret, så argumenten och resultattyperna för de uppgifter som de returnerar måste serialiseras av plattformen. I synnerhet måste de vara serialiserbara för datakontrakt.

Aktörsproxyn

Reliable Actors-klient-API:et tillhandahåller kommunikation mellan en aktörsinstans och en aktörsklient. För att kommunicera med en aktör skapar en klient ett aktörsproxyobjekt som implementerar aktörsgränssnittet. Klienten interagerar med aktören genom att anropa metoder på proxyobjektet. Aktörsproxyn kan användas för kommunikation mellan klienter och skådespelare och skådespelare.

// 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();

Observera att de två informationsdelarna som används för att skapa aktörsproxyobjektet är aktörs-ID:t och programnamnet. Aktörs-ID:t identifierar aktören unikt, medan programnamnet identifierar Service Fabric-programmet där aktören distribueras.

ActorProxyKlassen (C#) / ActorProxyBase(Java) på klientsidan utför den lösning som krävs för att hitta aktören efter ID och öppna en kommunikationskanal med den. Den försöker också hitta aktören igen vid kommunikationsfel och redundans. Därför har meddelandeleverans följande egenskaper:

  • Meddelandeleverans är det bästa sättet.
  • Aktörer kan ta emot dubbletter av meddelanden från samma klient.

Samtidighet

Reliable Actors-körningen ger en enkel turbaserad åtkomstmodell för åtkomst till aktörsmetoder. Det innebär att högst en tråd kan vara aktiv i ett aktörsobjekts kod när som helst. Turbaserad åtkomst förenklar avsevärt samtidiga system eftersom det inte finns något behov av synkroniseringsmekanismer för dataåtkomst. Det innebär också att system måste utformas med särskilda överväganden för den enskilda trådade åtkomsten för varje aktörsinstans.

  • En enskild aktörsinstans kan inte bearbeta fler än en begäran i taget. En aktörsinstans kan orsaka en flaskhals i dataflödet om den förväntas hantera samtidiga begäranden.
  • Aktörer kan blockera varandra om det finns en cirkulär begäran mellan två aktörer medan en extern begäran görs till en av aktörerna samtidigt. Aktörskörningen överskrider automatiskt tidsgränsen för aktörsanrop och utlöser ett undantag för anroparen för att avbryta eventuella dödlägen.

Reliable Actors-kommunikation

Turbaserad åtkomst

En tur består av den fullständiga körningen av en aktörsmetod som svar på en begäran från andra aktörer eller klienter, eller den fullständiga körningen av en timer/påminnelseåteranrop . Även om dessa metoder och återanrop är asynkrona, interleaves inte Actors-körningen dem. En sväng måste vara helt klar innan en ny sväng tillåts. Med andra ord måste en aktörsmetod eller timer/påminnelseåteranrop som körs för närvarande vara helt klar innan ett nytt anrop till en metod eller återanrop tillåts. En metod eller motringning anses ha slutförts om körningen har returnerats från metoden eller återanropet och uppgiften som returneras av metoden eller återanropet har slutförts. Det är värt att betona att turbaserad samtidighet respekteras även mellan olika metoder, timers och motringningar.

Actors-körningen framtvingar turbaserad samtidighet genom att skaffa ett lås per aktör i början av en sväng och släppa låset i slutet av svängen. Därför tillämpas turbaserad samtidighet per aktör och inte mellan aktörer. Aktörsmetoder och timer-/påminnelseåteranrop kan köras samtidigt för olika aktörers räkning.

I följande exempel visas ovanstående begrepp. Överväg en aktörstyp som implementerar två asynkrona metoder (till exempel Metod1 och Metod2), en timer och en påminnelse. Diagrammet nedan visar ett exempel på en tidslinje för körning av dessa metoder och återanrop för två aktörer (ActorId1 och ActorId2) som tillhör den här aktörstypen.

Reliable Actors runtime, turbaserad samtidighet och åtkomst

Det här diagrammet följer dessa konventioner:

  • Varje lodrät linje visar det logiska körningsflödet för en metod eller ett återanrop för en viss aktörs räkning.
  • Händelserna som markeras på varje lodrät linje sker i kronologisk ordning, med nyare händelser som inträffar under äldre.
  • Olika färger används för tidslinjer som motsvarar olika aktörer.
  • Markeringen används för att ange hur länge låset per aktör ska hållas för en metod eller motringning.

Några viktiga saker att tänka på:

  • Medan Method1 körs för ActorId2 som svar på klientbegäran xyz789, anländer en annan klientbegäran (abc123) som också kräver att Method1 körs av ActorId2. Den andra körningen av Method1 börjar dock inte förrän den tidigare körningen har slutförts. På samma sätt utlöses en påminnelse som registrerats av ActorId2 medan Method1 körs som svar på klientbegäran xyz789. Återanropet av påminnelsen körs endast när båda körningarna av Method1 har slutförts. Allt detta beror på att turbaserad samtidighet tillämpas för ActorId2.
  • På samma sätt framtvingas även turbaserad samtidighet för ActorId1, vilket framgår av körningen av Metod1, Metod2 och timerns återanrop för ActorId1 som sker på ett seriellt sätt.
  • Körningen av Method1 för ActorId1 överlappar körningen för ActorId2. Detta beror på att turbaserad samtidighet endast framtvingas inom en aktör och inte mellan aktörer.
  • I vissa av metoderna/återanropskörningarna Taskslutförs (C#) / CompletableFuture(Java) som returneras av metoden/återanropet när metoden har returnerats. I vissa andra har den asynkrona åtgärden redan slutförts när metoden/återanropet returneras. I båda fallen släpps låset per aktör först när både metoden/återanropet returnerar och den asynkrona åtgärden har slutförts.

Återinträde

Actors-körningen tillåter återaktivering som standard. Det innebär att om en aktörsmetod för Aktör A anropar en metod på Aktör B, som i sin tur anropar en annan metod på Aktör A, tillåts den metoden att köras. Det beror på att den ingår i samma logiska anropskedja. Alla timer- och påminnelseanrop börjar med den nya logiska samtalskontexten. Mer information finns i Reliable Actors-återaktivering .

Omfång för samtidighetsgarantier

Actors-körningen ger dessa samtidighetsgarantier i situationer där den styr anropet av dessa metoder. Det ger till exempel dessa garantier för de metodanrop som görs som svar på en klientbegäran, samt för timer- och påminnelseåteranrop. Men om aktörskoden direkt anropar dessa metoder utanför de mekanismer som tillhandahålls av Actors-körningen kan körningen inte ge några samtidighetsgarantier. Om metoden till exempel anropas i kontexten för en aktivitet som inte är associerad med uppgiften som returneras av aktörsmetoderna, kan körningen inte ge samtidighetsgarantier. Om metoden anropas från en tråd som aktören skapar på egen hand kan körningen inte heller ge samtidighetsgarantier. För att utföra bakgrundsåtgärder bör aktörer därför använda aktörstimers och aktörspåminnelser som respekterar turbaserad samtidighet.

Nästa steg

Kom igång genom att skapa din första Reliable Actors-tjänst: