DEV Community

Cover image for Introdução aos Atores Virtuais (Grains) em .NET com Proto.Actor
Rafael Andrade
Rafael Andrade

Posted on

Introdução aos Atores Virtuais (Grains) em .NET com Proto.Actor

No artigo anterior, discuti a configuração de um ator simples. Este artigo foca em Virtual Actor, um conceito que amplia o modelo tradicional de atores com gerenciamento automático de ciclo de vida e comunicação simplificada.

Virtual Actor (Grain)

O modelo de Virtual Actor (ou grain), popularizado pelo framework Orleans da Microsoft, abstrai o gerenciamento manual do ciclo de vida dos atores. Enquanto atores tradicionais exigem criação explícita e referência via PID, os atores virtuais são identificados por uma chave única. O framework os cria, ativa ou reativa automaticamente conforme necessário. Essa abstração simplifica a escalabilidade em sistemas distribuídos, dissociando a identidade do ator de sua localização física ou estado.

Diferenças-chave em relação aos atores clássicos:

  1. Gerenciamento de Ciclo de Vida: O framework (ex: Orleans ou Proto.Actor) cuida da ativação/desativação.
  2. Endereçamento: A comunicação usa identificadores lógicos, não PIDs.
  3. Persistência de Estado: Integra camadas de gerenciamento de estado para tolerância a falhas.

Requisitos

Definindo o Virtual Actor (Grain)

O Proto.Actor usa Protocol Buffers para definir interfaces de atores. Crie um arquivo Greeting.proto:

syntax = "proto3";

option csharp_namespace = "VirtualActor";

import "google/protobuf/empty.proto";

message SayHelloRequest {
  string name = 1;
}

service GreetingGrain {
  rpc SayHello(SayHelloRequest) returns (google.protobuf.Empty);
}
Enter fullscreen mode Exit fullscreen mode

Isso gera:

  • Classes de requisição/resposta (ex: SayHelloRequest).
  • Classe base (GreetingGrainBase) para a lógica do ator.

Atualize o .csproj para habilitar a geração de código:

<ItemGroup>
  <Protobuf Include="Greeting.proto">
    <GrcpServices>None</GrcpServices>
  </Protobuf>
</ItemGroup>

<ItemGroup>
  <ProtoGrain Include="Greeting.proto" />
</ItemGroup>
Enter fullscreen mode Exit fullscreen mode

Implementando o Ator

Crie uma classe GreetingActor herdando de GreetingGrainBase:

public class GreetingActor(
    IContext context,
    ClusterIdentity clusterIdentity,
    ILogger<GreetingActor> logger
) : GreetingGrainBase(context)
{
    private int _invocationCount = 0;

    public override Task SayHello(SayHelloRequest request)
    {
        logger.LogInformation(
            "Hello {Name} (Cluster ID: {ClusterId} | Invocation Count: {Count})",
            request.Name,
            clusterIdentity.Identity,
            _invocationCount++
        );
        return Task.CompletedTask;
    }
}
Enter fullscreen mode Exit fullscreen mode

Detalhes:

  • Gerenciamento de Estado: _invocationCount rastreia chamadas (thread-safe graças ao modelo de atores).
  • Injeção de Dependências: ILogger é injetado via ActivatorUtilities.

Configurando o Sistema de Atores

Configure o cluster com TestProvider (para desenvolvimento) e PartitionIdentityLookup:

var actorSystemConfig = Proto.ActorSystemConfig.Setup();
var remoteConfig = GrpcNetRemoteConfig.BindToLocalhost();

var clusterConfig = ClusterConfig
    .Setup(
        clusterName: "VirtualActor",
        clusterProvider: new TestProvider(new TestProviderOptions(), new InMemAgent()),
        identityLookup: new PartitionIdentityLookup()
    )
    .WithClusterKind(
        kind: GreetingGrainActor.Kind,
        prop: Props.FromProducer(() => 
            new GreetingGrainActor((context, clusterIdentity) => 
                ActivatorUtilities.CreateInstance<GreetingActor>(provider, context, clusterIdentity)))
    );

return new ActorSystem(actorSystemConfig)
    .WithServiceProvider(provider)
    .WithRemote(remoteConfig)
    .WithCluster(clusterConfig);
Enter fullscreen mode Exit fullscreen mode

Integrando ao .NET

Registre o serviço de cluster como um IHostedService:

public class ActorSystemClusterHostedService(ActorSystem actorSystem) : IHostedService
{
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await actorSystem.Cluster().StartMemberAsync();
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await actorSystem.Cluster().ShutdownAsync();
    }
}
Enter fullscreen mode Exit fullscreen mode

Registre em Program.cs:

services.AddHostedService<ActorSystemClusterHostedService>();
Enter fullscreen mode Exit fullscreen mode

Interagindo com Atores Virtuais

Use GetGreetingGrain para referenciar um ator por ID:

var actor = actorSystem.Cluster().GetGreetingGrain(fromName);
await actor.SayHello(new SayHelloRequest { Name = toName }, CancellationToken.None);
Enter fullscreen mode Exit fullscreen mode

Exemplo de fluxo:

while (true)
{
    Console.Write("Seu nome (ou 'q' para sair): ");
    var fromName = Console.ReadLine();
    if (fromName == "q") break;

    Console.Write("Nome do destinatário: ");
    var toName = Console.ReadLine();
    if (toName == "q") break;

    await actor.SayHello(new SayHelloRequest { Name = toName });
}
Enter fullscreen mode Exit fullscreen mode

Benefícios dos Atores Virtuais

  1. Concorrência Simplificada: Processamento sequencial de mensagens evita condições de corrida.
  2. Escalabilidade Elástica: Adicione/remova nós sem reconfigurar atores.
  3. Resiliência: Reativação automática garante comportamento "sempre ativo".

Conclusão

Atores Virtuais (ou Grains) revolucionam o desenvolvimento de sistemas distribuídos ao abstrair complexidade enquanto mantêm os benefícios do modelo de atores. Com o Proto.Actor, desenvolvedores .NET podem:

  • Focar na Lógica de Negócio: O framework gerencia ativação, escalabilidade e recuperação.
  • Construir Sistemas Resilientes: Reativação automática e persistência de estado garantem tolerância a falhas.
  • Escalar sem Esforço: Transparência de localização e clustering elástico distribuem carga entre nós.

Para produção:

  • Substitua TestProvider por provedores como Kubernetes ou Consul.
  • Adicione armazenamento persistente (ex: Redis, PostgreSQL).
  • Implemente monitoramento e health checks.

Referência

Top comments (0)