Category Archives: Proto.Actor

Proto.Actor Remoting

I’m now going to take a look at what’s required to implement a remote Proto.Actor and a “client” to interact with it. I’m going to stick to the standard Greet class, as shown in my previous post, but we’re going to generate the Greet class from a .proto (protocol buffers) definition file.

So before we get into the client/server code, let’s create the Greet.proto file, here’s it is

syntax = "proto3";

package messages;
option csharp_namespace = "Messages";

message Greet {
   string Who = 1;
}

The Greet message will generate a Greet type with a property name Who. So once you’ve created this file, you’ll need to use protoc.exe with the following command line

protoc.exe –csharp_out=. Greet.proto

This will generate the Greet.cs file, which I will not bother to show here.

Next up, we’ll reuse our GreetActor class from the previous post, recreated below

public class GreetingActor : IActor
{
   public Task ReceiveAsync(IContext context)
   {
      var greet = context.Message as Greet;
      if (greet != null)
      {
         Console.WriteLine("[Thread {0}] Greeting {1}",
            Thread.CurrentThread.ManagedThreadId,
            greet.Who);
      }
      return Actor.Done;
   }
}

As we know, strictly speaking Akka.net and also Proto.Actor do not adhere to a client/server architecture but remote objects are created in a peer to peer architecture. For the sake of this post we will create two separate projects, one named Server the other Client, just for simplicity.

Creating our server

  • Create a Console application, named something like ProtoActorServer
  • Using Nuget add the Proto.Actor and Proto.Remote packages
  • Add or link to the Greet.cs file generated by protoc
  • Add or link to the GreetActor.cs file from above
  • In Program.cs add the following using clauses
    using Messages;
    using Proto;
    using Proto.Remote;
    
  • In the Main method add the following code
    Serialization.RegisterFileDescriptor(GreetReflection.Descriptor);
    RemotingSystem.Start("127.0.0.1", 12000);
    
    var props = Actor.FromProducer(() => new GreetingActor());
    Actor.SpawnNamed(props, "remote");
    
    // just to keep the app. open
    Console.ReadLine();
    

Creating our client

As we know, this is going to basically be very similar to the server is set-up, but there are differences in the code, but I’ll still list all the steps for completeness

  • Create a Console application, named something like ProtoActorClient
  • Using Nuget add the Proto.Actor and Proto.Remote packages
  • Add or link to the Greet.cs file generated by protoc
  • Add or link to the GreetActor.cs file from above
  • In Program.cs add the following using clauses
    using Messages;
    using Proto;
    using Proto.Remote;
    
  • In the Main method add the following code
    Serialization.RegisterFileDescriptor(GreetReflection.Descriptor);
    RemotingSystem.Start("127.0.0.1", 12001);
    
    var remote = new PID("127.0.0.1:12000", "remote");
    remote.Tell(new Greet { Who = "Hello World" });;
    
    // just to keep the app. open
    Console.ReadLine();
    

If you now run the ProtoActorServer and then the ProtoActorClient you should see the Greeting Hello World message displayed on the server console via it’s GreetingActor.

Disclaimer

At the time of writing this I’ve not yet seen documentation to suggest I’m doing everything 100% by the Proto.Actor book, so to speak, I’ve based this code on previous use of protobuf and Akka.net as well as a couple of examples from the Proto.Actor git repos. If I find I’m doing anything incorrectly, I will update this page.

Proto.Actor first look

No sooner had I started looking to use Akka.net, than I find out about Proto.Actor (via .NET Rocks). From my understanding this comes from some of the same guys involved in Akka.net and currently supports .NET and the language Go.

One of my previous posts covered Getting started with Akka.net. Let’s take that post and rewrite the code using the Proto.Actor library, just to see what the differences are.

  • Create a Console application
  • Using Nuget, add the Proto.Actor package
  • Create a class named Greet, this will be used as the payload for wrapping our data that we shall pass to our Actor object. Here’s the code
    public class Greet
    {
       public Greet(string who)
       {
          Who = who;
       }
     
       public string Who { get; private set; }
    }
    
  • Create a new class named GreetingActor. This is our Actor object that does something and will accept objects of type Greet, the code should look like this
    public class GreetingActor : IActor
    {
       public Task ReceiveAsync(IContext context)
       {
          var greet = context.Message as Greet;
          if (greet != null)
          {
             Console.WriteLine("[Thread {0}] Greeting {1}",
                    Thread.CurrentThread.ManagedThreadId,
                    greet.Who);
          }
          return Actor.Done;
       }
    }
    

    So here’s the first difference, code-wise. We are implementing the IActor interface and our code goes in the ReceiveAsync method as opposed the Akka.net code which went in the constructor. Also we have to check the type in the context Message as opposed to using the Akka.net Receive<> generic to differentiate our types. Obviously with the latest C# 7 features we can use type matching, but I’m running this on C# 6 so the standard as operator is used.

  • Finally we want to create an instance of an actor and send a message to it via the Tell method, so our Main method should look like this
    var props = Actor.FromProducer(() => new GreetingActor());
    var greeter = Actor.Spawn(props);
    greeter.Tell(new Greet("Hello World"));
    
    // to stop the console closing 
    // before the message is received
    Console.ReadLine();
    

    This differs from Akka.net in the way we create the greeter but it’s the same number of lines of code and equally simple.

So in the code above we create the Greet class for our message type (in essence) and obviously the GreetingActor listens for Greet messages. In the Main method we create a Props instance from the Actor system using FromProducer (which acts as a factory type pattern) then using the Actor.Spawn we actually create an instance of each actor we want in our system.

The Tell line in the Main method is the same as Akka.net, in that we send a message to the greeter Actor via the Tell method and at some point the GreatingActor will receive this message and write it’s text to the Console and that’s it.