Azure Service Fabric

AzureServiceFabric
Actors
Agenda
•
•
•
•
WhatareActorsandwhentousethem
Architecture
HelloActors
ServiceFabricActormodel
–
–
–
–
–
Messaging
Turnbasedconcurrency
Lifecycle
Timersandreminders
Events
2
WhatisanActor
• Primitiveunitofcomputation
– Itreceivesamessageanddoessomekindofcomputationbasedonit
• Actorshavemailboxes
– Usedtoreceivemessages
• Actorsprocessonemessageatatime
3
WhatdoActorsdo
• Createmoreactors
• Sendmessagestootheractors
• Designatewhattodowiththenextmessage
– Changestatebasedoncurrentmessage
– Nextmessageisprocessedagainstnewstate
4
Whentouseactors
• Yourproblemspaceinvolvesalargenumber(thousandsor
more)ofsmall,independent,andisolatedunitsofstateand
logic.
• Youwanttoworkwithsingle-threadedobjectsthatdonot
requiresignificantinteractionfromexternalcomponents,
includingqueryingstateacrossasetofactors.
• Youractorinstanceswon'tblockcallerswithunpredictable
delaysbyissuingI/Ooperations.
5
Examples
• Pokergame
–
–
–
–
Dealerasactors
Playersasactors
Playersdigitalwalletasanactor
Deckofcardsasanactor
• Onlineauctions
– Eachauctionasanactor
– Watcherasanactor
– Bidderasanactor
6
ServiceFabricActors
• KnownasVirtualActors
– ReliableActors
• ActorsarehostedbyaReliableService
– ActorService extendsStatefulServiceBase
• ManagesActortypesandinstancesregisteredtothisservice
• Deployedusing
– ApplicationManifest.xml
– ServiceManifest.xml
• VisualStudiotoolingbuildsandmaintainsManifests
– ProjecttypeCloud/Stateful Actor
– SeparatesActorcommunicationcontractfromimplementation
7
ActorService
8
ActorIdentity
• ActorhasanIdscopedbyserviceinstance
– Guid
– Int64
– String
• PartitioningbasedonActorId
– Usesint64basedpartitioning
– Guid andStringallhasheddowntoaint64
9
DefininganActor
• Defineaninterfacethatrepresentsthecommunicationwiththe
Actor
– Typicallymethodpermessagetype
– MethodsmustreturnaTask
• Noreforoutparameters
• CantakeCancellationToken
– CanNOTuseproperties
– AlltypesinvolvedmustbeDataContractSerializable
– Toallowrollingupgradesnormalcontractevolutionrulesapply
• TakecontrolwithDataContract andDataMember
• UseOrder
• Addtotypes
• Usenullable typesifnotrequired
• Implementtheinterface
– ClassthatderivesfromActor
10
ExampleActordefinition
• MustextendIActor
• MustreturnTask
• ShouldtakeCancellationToken
[DataContract(Name="StockQuote",Namespace="urn:rsk/stocks/1")]
public class Stock
{
[DataMember(Name="Symbol",Order=1)]
public string Symbol;
[DataMember(Name = "Price", Order = 2)]
public decimal Price;
}
public interface IStockQuote : IActor
{
Task<Stock> GetPrice(string currrency,CancellationToken ct);
}
11
ImplementandRegister
• Implementactorinterface andextendActor
• RegistertheActortypewhenthehostingservicestartsup
internal class YahooStockQuote: Actor, IStockQuote {
public YahooStockQuote(ActorService actorService, ActorId actorId)
: base(actorService, actorId){ }
public async Task<Stock> GetPrice(string currency,CancellationToken ct) {
. . .
return stock;
}
}
ActorRuntime.RegisterActorAsync<YahooStockQuote>(
(context, actorType) => new ActorService(context,
actorType)).Wait();
12
InvokinganActor
• ActorProxy type
– Createsaninstanceoftheproxy
• Invoke theproxy
const string applicationUrl = "fabric:/StocksRUS”;
IStockQuote actor = ActorProxy.
Create<IStockQuote>(new ActorId(”CSCO"),applicationUrl);
Stock cscoPrice = await actor.GetPrice(“USD”,CancellationToken.None);
13
Turnbasedconcurrency
• Actorsprocessonemessageatatime
• Singlethreadedprogrammingmodel
– Reducedcomplexity
14
Turnbasedconcurrencyinaction
15
Turnbaseconcurrency
• Actorinstancecouldbecomebottleneck
• Possibledeadlocks
– Recoveredthroughtimeoutsandretrys
Call 4
Call 3
Call 2
Call 1
16
Turnbasedconcurrencyexception!
• Actorscanbere-enterable
• CandisableviaActorServiceSettings atregistration
17
VirtualActorLifeCycle
• Activation
– Createdinmemory
– OnActiveAsync called
• Deactivation
– OnDeactive called
– Removedfrommemory
– Butstillexist
• Actorsactivatedwhentheyreceiveamessageandarecurrently
notinmemory
• ActorsareDeactivatedaspartofActorGC
• Actorsliveuntilexplicitlydeleted
18
ActorGC
• AnyActorthathasnotprocessedamessagewithin60minutes
isacandidateforGC
• GCscanisinvokedeveryminute
• Bothidleandscantimesconfigurable
– ActorServiceSettings
19
Maintainingstate
• Objectmembersnotpersistedondeactivation
• StateManager isusedforstatethatneedstobeaccessable
acrossActivations.
• StateManager propertyonActorprovidesaccesstoKey/Value
pairstore
• Choiceofstrategies
– None,inmemory
– Volatile,inmemorybutreplicated
– Persisted,persistedandandreplicated
20
StateManager
• APIsimilartoIReliableDictionary
– GetOrAddStateAsync,AddOrUpdateStateAsync
– SetStateAsync,...
• Commitschangesonsuccesful response
publicclassCountActor :Actor,ICounting {
privateint count=0;
publicCountActor(ActorService actorService,ActorId actorId):base(actorService,actorId){}
protectedoverrideasync TaskOnActivateAsync(){
count=awaitStateManager.GetOrAddStateAsync("count",0,CancellationToken.None);
awaitbase.OnActivateAsync();
}
publicasync Task<int>Increment(){
count++;
awaitStateManager.SetStateAsync("count",count);
return count;
}
}
21
StateManager
• StateManager considersamethodasatransactionscope
– Onlycommitsifmethodcompletessuccessfully
– Countwillnevergetabove4
• Cancommitmidmethod
– SaveStateAsync()
publicasync Task<int>Increment(){
int count =awaitStateManager.GetOrAddStateAsync(“count”,0);
count++;
awaitStateManager.SetStateAsync("count",count);
if (count == 5)
{
thrownewInvalidOperationException();
}
return count;
}
22
StateManagement
• Volatile&Persisted
– MustbeDataContract Serializable
– Considerimpactofupgrade
23
ActorTimers
•
•
•
•
•
Selfgeneratedmessage basedontimeinterval
OnlyfiresifActorisactive
Similarto.NETtimers
Preservesturn-basedconcurrency
RegisterTimer methodavailableontheActorinstance
protectedoverrideasync TaskOnActivateAsync(){
this.RegisterTimer(_=>Increment(),null,TimeSpan.FromSeconds(1),TimeSpan.FromSeconds(1));
}
awaitbase.OnActivateAsync();
publicasync Task<int>Increment(){...}
24
ActorReminders
•
•
•
•
•
•
Selfgeneratedmessagesbasedontimeinterval
ActivatesActorifnecessary
Singleentrypointinclass,IRemindable.ReceiveReminderAsync
Preservesturn-basedconcurrency
Context mustbeconvertedintoabytearray
IActorReminder holdsreferencetoreminder
public class CountActor : Actor,ICounting, IRemindable
public async Task DelayIncrement(int amount)
{
IActorReminder incrementReminder =
await this.RegisterReminderAsync("Increment”,
BitConverter.GetBytes(amount),
TimeSpan.FromSeconds(5),
TimeSpan.FromMilliseconds(-1));
}
}
25
HandlingReminders
ActivatesActorifnecessary
Singleentrypointinclass,IRemindable.ReceiveReminderAsync
Preservesturn-basedconcurrency
Context mustbeconvertedfrombyte[]
•
•
•
•
publicTaskReceiveReminderAsync(stringreminderName,byte[]context,
TimeSpan dueTime,TimeSpan period) {
if(reminderName =="Increment") {
int amount=BitConverter.ToInt32(context,0);
StateManager.AddOrUpdateStateAsync("count",amount,(k,v)=>v+amount,CancellationToken.None);
}
}
returnTask.FromResult(0);
26
UnRegister Reminder
• Cancelreminder,viaIActorReminder
// From inside the Actor
IActorReminder reminder = GetReminder("Increment");
if (reminder != null) {
await this.UnregisterReminderAsync(reminder);
}
27
ActorEvents
• Actorscanraiseevents
– Notintendedforactortoactorbasednotifications
– Usedtonotifyactorclients
• SignalR webapplication,runningasawebgateway
– Eventdeliverynotreliable
• ActorimplementsIActorEventPublisher<T>
– Justasignatureinterface
– MustextendIActorEvents
• Trepresentsaninterfacecontainingmethodstobe
implementedbytheclient(observer)
– Mustallreturnvoid
• Actorcallsthis.GetEvent<T>()asatargettosendobservation
28
ExposingandFiringanActorEvent
• ExposinganActorevent
• FiringanActorevent
public interface ICounterObserver : IActorEvents
void HasReachedMaxValue(int count);
}
{
public interface ICounting: , IActorEventPublisher<ICounterObserver>
{
…
}
public class CountActor : Actor,ICounting, IRemindable
public void OnHasReachedMaxValue(int count){
this.GetEvent<ICounterObserver>().HasReachedMaxValue(count);
}
}
29
ReceivinganActorEvent
• Implementeventinterface
• Subscribetotheeventinterface,viatheactorproxy
public class CounterObserver : ICounterObserver {
public void HasReachedMaxValue(int count) {
Console.WriteLine("Max reached {0}",count);
}
}
. . .
ICounting actor = . . .
actor.SubscribeAsync<ICounterObserver>(new CounterObserver());
30
Summary
• Actorsprovideasimplescalableconcurrentprogrammingmodel
• Suitedforscenarioswheretherearelotsofisolatedunitsof
stateandlogic.
• Reliableservicesprovidesastrongplatformforscalabilityand
faulttolerance.Enablinghighavailabilityandperformance
• Planforupgrade
– VersioninterfacesalongSOAlines
31