Fundamentos de Akka.net para
sistemas concorrentes e distribuídos
usando o modelo de atores.
Elemar Jr
Elemar Júnior
Microsoft Most Valuable Professional (MVP)
Arquiteto de Soluções na Promob há 17 anos
elemarjr.net
github.com/elemarjr
twitter.com/elemarjr
linkedin.com/elemarjr
The Reactive Manifesto
Responsivo
Elástico Resiliente
Orientado a mensagem
Para considerar...
É difícil fazer sistemas verdadeiramente
concorrentes da forma correta
É difícil fazer sistemas que realmente
suportem “Scaling up” e “Scaling out”
É difícil fazer sistemas resilientes, tolerantes
a falhas com “auto recuperação”
Akka.net Docs
O “Actor Model” foi definido em 1973, por Carl
Hewitt
A B
ActorRef
ActorSystem
Message
ActorRef
Message
class Program
{
public static ActorSystem MyActorSystem;
static void Main()
{
// initialize MyActorSystem
MyActorSystem = ActorSystem.Create("MyActorSystem");
var consoleWriterProps = Props.Create(() => new ConsoleWriterActor());
var consoleWriterActor = MyActorSystem.ActorOf(consoleWriterProps);
var consoleReaderProps = Props.Create(() => new ConsoleReaderActor(consoleWriterActor));
var consoleReaderActor =MyActorSystem.ActorOf(consoleReaderProps);
// tell console reader to begin
consoleReaderActor.Tell("start");
// blocks the main thread from exiting until the actor system is shut down
MyActorSystem.AwaitTermination();
class ConsoleReaderActor : UntypedActor
{
public const string ExitCommand = "exit";
private readonly IActorRef _consoleWriterActor;
public ConsoleReaderActor(IActorRef consoleWriterActor)
{
_consoleWriterActor = consoleWriterActor;
}
protected override void OnReceive(object message)
{
var read = Console.ReadLine();
if (!string.IsNullOrEmpty(read) &&
string.Equals(read, ExitCommand, StringComparison.OrdinalIgnoreCase))
{
Context.System.Shutdown();
return;
}
_consoleWriterActor.Tell(read);
Self.Tell("continue");
}
}
class ConsoleWriterActor : UntypedActor
{
protected override void OnReceive(object message)
{
var msg = message as string;
if (string.IsNullOrEmpty(msg))
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("Please provide an input.n");
Console.ResetColor();
return;
}
// if message has even # characters, display in red; else, green
var even = msg.Length % 2 == 0;
var color = even ? ConsoleColor.Red : ConsoleColor.Green;
var alert = even ?
"Your string had an even # of characters.n" :
"Your string had an odd # of characters.n";
Console.ForegroundColor = color;
Console.WriteLine(alert);
Console.ResetColor();
}
}
A B
ActorRef
ActorSystem
Message
ActorRef
Message
Transport
Transport
A B
ActorRef
ActorSystem
Message
ActorRef
Message
Transport
Transport
Mensagens são “imutáveis”
public class InputSuccess
{
public string Reason { get; }
public InputSuccess(string reason)
{
Reason = reason;
}
}
public class ContinueProcessing
{}
public class InputError
{
public string Reason { get; }
public InputError(string reason)
{
Reason = reason;
}
}
internal class NullInputError : InputError
{
public NullInputError(string reason) : base(reason)
{}
}
class ValidationError : InputError {
public ValidationError(string reason) : base(reason)
{}
}
public const string StartCommand = "start";
public const string ExitCommand = "exit";
private readonly IActorRef _consoleWriterActor;
public ConsoleReaderActor(IActorRef consoleWriterActor)
{
_consoleWriterActor = consoleWriterActor;
}
protected override void OnReceive(object message)
{
if (message.Equals(StartCommand))
{
DoPrintInstructions();
}
else if (message is Messages.InputError)
{
_consoleWriterActor.Tell(message as Messages.InputError);
}
GetAndValidateInput();
}
class ConsoleWriterActor : UntypedActor
{
protected override void OnReceive(object message)
{
if (message is Messages.InputError)
{
var msg = message as Messages.InputError;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg.Reason);
}
else if (message is Messages.InputSuccess)
{
var msg = message as Messages.InputSuccess;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(msg.Reason);
}
else
{
Console.WriteLine(message);
}
Console.ResetColor();
}
}
consoleReaderActor.Tell(ConsoleReaderActor.StartCommand);
A B
ActorRef
ActorSystem
Message
ActorRef
Message
Transport
Transport
var consoleWriterProps = Props.Create<ConsoleWriterActor>();
var consoleWriterActor = MyActorSystem.ActorOf(consoleWriterProps, "consoleWriterActor");
var validationActorProps = Props.Create(() => new ValidationActor(consoleWriterActor));
var validationActor = MyActorSystem.ActorOf(validationActorProps, "validationActor");
var consoleReaderProps = Props.Create<ConsoleReaderActor>(validationActor);
var consoleReaderActor = MyActorSystem.ActorOf(consoleReaderProps, "consoleReaderActor");
class ConsoleReaderActor : UntypedActor
{
public const string StartCommand = "start";
public const string ExitCommand = "exit";
private readonly IActorRef _validationActor;
public ConsoleReaderActor(IActorRef validationActor)
{
_validationActor = validationActor;
}
protected override void OnReceive(object message)
{
if (message.Equals(StartCommand))
{
DoPrintInstructions();
}
GetAndValidateInput();
}
private static void DoPrintInstructions() {}
private void GetAndValidateInput()
{
var message = Console.ReadLine();
if (!string.IsNullOrEmpty(message) && string.Equals(message, ExitCommand, StringComparison.OrdinalIgnoreCase))
{
Context.System.Shutdown();
return;
}
_validationActor.Tell(message);
}
}
class ValidationActor : UntypedActor
{
private readonly IActorRef _consoleWriterActor;
public ValidationActor(IActorRef consoleWriterActor)
{ _consoleWriterActor = consoleWriterActor; }
protected override void OnReceive(object message)
{
var msg = message as string;
if (string.IsNullOrEmpty(msg))
{ _consoleWriterActor.Tell(new Messages.NullInputError("No input received.")); }
else
{
if (IsValid(msg))
{_consoleWriterActor.Tell(new Messages.InputSuccess("Thank you! Message was valid."));}
else
{
_consoleWriterActor.Tell(new Messages.ValidationError("Invalid: input had odd number of characters."));
}
}
Sender.Tell(new Messages.ContinueProcessing());
}
private static bool IsValid(string msg)
{
return = msg.Length % 2 == 0;
}
}
A B
ActorRef
ActorSystem
Message
ActorRef
Message
Transport
Transport
Akka.net Docs
protected override void OnReceive(object message)
{
if (message is StartTail)
{
var msg = message as StartTail;
// here we are creating our first parent/child relationship!
// the TailActor instance created here is a child
// of this instance of TailCoordinatorActor
Context.ActorOf(Props.Create(() => new TailActor(msg.ReporterActor, msg.FilePath)));
}
}
protected override SupervisorStrategy SupervisorStrategy()
{
return new OneForOneStrategy(
10, // maxNumberOfRetries
TimeSpan.FromSeconds(30), // duration
x =>
{
//Maybe we consider ArithmeticException to not be application critical
//so we just ignore the error and keep going.
if (x is ArithmeticException) return Directive.Resume;
//Error that we cannot recover from, stop the failing actor
if (x is NotSupportedException) return Directive.Stop;
//In all other cases, just restart the failing actor
return Directive.Restart;
});
}
Akka.net Bootcamp
private void GetAndValidateInput()
{
var message = Console.ReadLine();
if (!string.IsNullOrEmpty(message) && string.Equals(message, ExitCommand,
StringComparison.OrdinalIgnoreCase))
{
Context.System.Shutdown();
return;
}
Context.ActorSelection("akka://MyActorSystem/user/validationActor").Tell(message);
}
A
ActorRef
ActorSystem
Message
ActorRef
Message
Transport
Transport
State A
State B
State C
Props
Props
Akka.net Bootcamp
A
ActorRef
ActorSystem
Message
ActorRef
Message
Transport
Transport
State A
State B
State C
Props
Props
Scheduler
The Reactive Manifesto
Responsivo
Elástico Resiliente
Orientado a mensagem
Obrigado!
tinyurl.com/feedback-ej

Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o modelo de atores

  • 1.
    Fundamentos de Akka.netpara sistemas concorrentes e distribuídos usando o modelo de atores. Elemar Jr
  • 2.
    Elemar Júnior Microsoft MostValuable Professional (MVP) Arquiteto de Soluções na Promob há 17 anos elemarjr.net github.com/elemarjr twitter.com/elemarjr linkedin.com/elemarjr
  • 3.
    The Reactive Manifesto Responsivo ElásticoResiliente Orientado a mensagem
  • 4.
    Para considerar... É difícilfazer sistemas verdadeiramente concorrentes da forma correta É difícil fazer sistemas que realmente suportem “Scaling up” e “Scaling out” É difícil fazer sistemas resilientes, tolerantes a falhas com “auto recuperação”
  • 5.
  • 6.
    O “Actor Model”foi definido em 1973, por Carl Hewitt
  • 9.
  • 10.
    class Program { public staticActorSystem MyActorSystem; static void Main() { // initialize MyActorSystem MyActorSystem = ActorSystem.Create("MyActorSystem");
  • 11.
    var consoleWriterProps =Props.Create(() => new ConsoleWriterActor()); var consoleWriterActor = MyActorSystem.ActorOf(consoleWriterProps); var consoleReaderProps = Props.Create(() => new ConsoleReaderActor(consoleWriterActor)); var consoleReaderActor =MyActorSystem.ActorOf(consoleReaderProps);
  • 12.
    // tell consolereader to begin consoleReaderActor.Tell("start"); // blocks the main thread from exiting until the actor system is shut down MyActorSystem.AwaitTermination();
  • 13.
    class ConsoleReaderActor :UntypedActor { public const string ExitCommand = "exit"; private readonly IActorRef _consoleWriterActor; public ConsoleReaderActor(IActorRef consoleWriterActor) { _consoleWriterActor = consoleWriterActor; } protected override void OnReceive(object message) { var read = Console.ReadLine(); if (!string.IsNullOrEmpty(read) && string.Equals(read, ExitCommand, StringComparison.OrdinalIgnoreCase)) { Context.System.Shutdown(); return; } _consoleWriterActor.Tell(read); Self.Tell("continue"); } }
  • 14.
    class ConsoleWriterActor :UntypedActor { protected override void OnReceive(object message) { var msg = message as string; if (string.IsNullOrEmpty(msg)) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("Please provide an input.n"); Console.ResetColor(); return; } // if message has even # characters, display in red; else, green var even = msg.Length % 2 == 0; var color = even ? ConsoleColor.Red : ConsoleColor.Green; var alert = even ? "Your string had an even # of characters.n" : "Your string had an odd # of characters.n"; Console.ForegroundColor = color; Console.WriteLine(alert); Console.ResetColor(); } }
  • 15.
  • 16.
  • 17.
  • 18.
    public class InputSuccess { publicstring Reason { get; } public InputSuccess(string reason) { Reason = reason; } }
  • 19.
  • 20.
    public class InputError { publicstring Reason { get; } public InputError(string reason) { Reason = reason; } }
  • 21.
    internal class NullInputError: InputError { public NullInputError(string reason) : base(reason) {} }
  • 22.
    class ValidationError :InputError { public ValidationError(string reason) : base(reason) {} }
  • 23.
    public const stringStartCommand = "start"; public const string ExitCommand = "exit"; private readonly IActorRef _consoleWriterActor; public ConsoleReaderActor(IActorRef consoleWriterActor) { _consoleWriterActor = consoleWriterActor; } protected override void OnReceive(object message) { if (message.Equals(StartCommand)) { DoPrintInstructions(); } else if (message is Messages.InputError) { _consoleWriterActor.Tell(message as Messages.InputError); } GetAndValidateInput(); }
  • 24.
    class ConsoleWriterActor :UntypedActor { protected override void OnReceive(object message) { if (message is Messages.InputError) { var msg = message as Messages.InputError; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(msg.Reason); } else if (message is Messages.InputSuccess) { var msg = message as Messages.InputSuccess; Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(msg.Reason); } else { Console.WriteLine(message); } Console.ResetColor(); } }
  • 25.
  • 26.
  • 27.
    var consoleWriterProps =Props.Create<ConsoleWriterActor>(); var consoleWriterActor = MyActorSystem.ActorOf(consoleWriterProps, "consoleWriterActor"); var validationActorProps = Props.Create(() => new ValidationActor(consoleWriterActor)); var validationActor = MyActorSystem.ActorOf(validationActorProps, "validationActor"); var consoleReaderProps = Props.Create<ConsoleReaderActor>(validationActor); var consoleReaderActor = MyActorSystem.ActorOf(consoleReaderProps, "consoleReaderActor");
  • 28.
    class ConsoleReaderActor :UntypedActor { public const string StartCommand = "start"; public const string ExitCommand = "exit"; private readonly IActorRef _validationActor; public ConsoleReaderActor(IActorRef validationActor) { _validationActor = validationActor; } protected override void OnReceive(object message) { if (message.Equals(StartCommand)) { DoPrintInstructions(); } GetAndValidateInput(); } private static void DoPrintInstructions() {} private void GetAndValidateInput() { var message = Console.ReadLine(); if (!string.IsNullOrEmpty(message) && string.Equals(message, ExitCommand, StringComparison.OrdinalIgnoreCase)) { Context.System.Shutdown(); return; } _validationActor.Tell(message); } }
  • 29.
    class ValidationActor :UntypedActor { private readonly IActorRef _consoleWriterActor; public ValidationActor(IActorRef consoleWriterActor) { _consoleWriterActor = consoleWriterActor; } protected override void OnReceive(object message) { var msg = message as string; if (string.IsNullOrEmpty(msg)) { _consoleWriterActor.Tell(new Messages.NullInputError("No input received.")); } else { if (IsValid(msg)) {_consoleWriterActor.Tell(new Messages.InputSuccess("Thank you! Message was valid."));} else { _consoleWriterActor.Tell(new Messages.ValidationError("Invalid: input had odd number of characters.")); } } Sender.Tell(new Messages.ContinueProcessing()); } private static bool IsValid(string msg) { return = msg.Length % 2 == 0; } }
  • 30.
  • 31.
  • 32.
    protected override voidOnReceive(object message) { if (message is StartTail) { var msg = message as StartTail; // here we are creating our first parent/child relationship! // the TailActor instance created here is a child // of this instance of TailCoordinatorActor Context.ActorOf(Props.Create(() => new TailActor(msg.ReporterActor, msg.FilePath))); } } protected override SupervisorStrategy SupervisorStrategy() { return new OneForOneStrategy( 10, // maxNumberOfRetries TimeSpan.FromSeconds(30), // duration x => { //Maybe we consider ArithmeticException to not be application critical //so we just ignore the error and keep going. if (x is ArithmeticException) return Directive.Resume; //Error that we cannot recover from, stop the failing actor if (x is NotSupportedException) return Directive.Stop; //In all other cases, just restart the failing actor return Directive.Restart; }); }
  • 33.
  • 34.
    private void GetAndValidateInput() { varmessage = Console.ReadLine(); if (!string.IsNullOrEmpty(message) && string.Equals(message, ExitCommand, StringComparison.OrdinalIgnoreCase)) { Context.System.Shutdown(); return; } Context.ActorSelection("akka://MyActorSystem/user/validationActor").Tell(message); }
  • 35.
  • 36.
  • 37.
  • 38.
    The Reactive Manifesto Responsivo ElásticoResiliente Orientado a mensagem
  • 39.