O modelo de atores é uma alternativa fascinante e relativamente simples para o desenvolvimento de sistemas distribuídos ou concorrentes. Exceto pela liberdade de de adoção tecnológica, entrega quase todos os benefícios geralmente associados a microsserviços com uma parcela reduzida de complexidade (consequentemente, custo).
O modelo de atores não é uma ideia nova. O modelo foi proposto em 1973, por Carl Hewitt, e é aplicada em sistemas básicos de telefonia e em sistemas como Whatsapp e RabbitMQ.
A ideia central para o modelo de atores é “decompor” o sistema em pequenas unidades de processamento (os atores) que se comunicam através da troca de mensagens imutáveis.
class GreeterActor : TypedActor, IHandle<GoodMorning>, IHandle<GoodAfternoon>, IHandle<GoodEvening>, IHandle<GenericGreeting> { public void Handle(GoodMorning m) => WriteLine("Good Morning"); public void Handle(GoodAfternoon m) => WriteLine("Good Afernoon"); public void Handle(GoodEvening m) => WriteLine("Good Evening"); public void Handle(GenericGreeting m) => WriteLine(m.Message); }
O código acima, mostra a implementação de um ator em Akka.net.
Os atores funcionam em um ambiente supervisionado que garante a resiliência do sistema. A supervisão garante que instâncias problemáticas de atores sejam descartadas e substituídas por novas instâncias com o menor prejuízo possível.
A interface de comunicação dos atores é padronizada o que reduz o acoplamento. Dois atores nunca se “comunicam” diretamente, mas sempre através de um “agente” mantido e controlado pelo sistema.
A comunicação entre os atores é garantida pelo sistema. Aliás, para os atores é indiferente se um ator com que precisa interagir está rodando no mesmo processo, no mesmo computador ou, até mesmo, na mesma rede. Essa característica torna o desenvolvimento muito mais simples.
Um ator tem liberdade para criar e supervisionar outras instâncias de atores. Assim, pode distribuir trabalho sem mudar a interação com outros serviços.
static void Main() { var actorSystem = ActorSystem.Create("myactorsystem"); var workerProp = Props.Create(() => new WorkerActor()) .WithRouter(new RoundRobinPool(10)); var worker = actorSystem.ActorOf(workerProp); var boss = actorSystem.ActorOf(Props.Create(() => new BossActor(worker))); boss.Tell(Start.Instance); actorSystem.WhenTerminated.Wait(); }
No exemplo acima, utilizamos um factory de Akka.net para criar um ator que supervisiona a execução de 10 outros atores (que fazem o processamento real) distribuindo a carga em estratégia round robin.
Há frameworks para adoção do modelo de atores em praticamente todos os grandes ecossistemas tecnológicos modernos. Além de ERLANG, há, por exemplo Akka para Java, Akka.net e Orleans para .NET.
Nos próximos posts dessa série mostraremos exemplos concretos de adoção do modelo de atores em diversas tecnologias.
Se você já desenvolve usando modelo de atores, recomendamos ler o livro do Vaugh Vernon sobre padrões.
Só faltou citar Scala, em que o modelo de ator é mais presente. Você acha que linguagens funcionais como o Scala e o F# podem ser mais adequadas para esse modelo?
Sim. Poderia ter mencionado Scala.
Acho que não conheço nenhuma implementação séria usando Akka que não seja em Scala. Penso que há bom fit entre funcionais e o modelo de atores, mas não acho que seja, necessariamente, um pré-requisito.