Category Archives: Akka.net

Akka Remoting

In this post I’ll be covering pretty much the same as the Akka.net Remoting page. So I would definitely suggest you read that instead or in conjunction with this post.

As Akka.net has been designed for distributed systems and because (as you’ll have seen from my previous post on Akka.net) you interact with Actor objects via messages. Distributing your Actors should be pretty simple and painless. Let’s see if that holds true.

Initially we’re going to simply create two console applications. Let’s start off by thinking of one as the AkkaServer and the other the AkkaClient (although conceptually, in many ways, the idea of a server and client are meaningless in such an application as they’re really just “peers”).

Let’s write some code

  • Both projects are going to be compiled in .NET 4.6, so go ahead a create two console applications, name the first AkkaServer and the second AkkaClient.
  • Next up, add the Nuget Packages for Akka and Akka.Remote to both projects.
  • We could now create a third solution for our shared types, but let’s just add a new project to the AkkaServer, mine’s named Shared, you’ll need to add the Akka Nuget package to this project also.
  • In the Shared project, add the GreetingActor (as outlined previously and in the Akka.net documentation, here it is for completeness
    public class Greet
    {
       public Greet(string who)
       {
          Who = who;
       }
    
       public string Who { get; private set; }
    }
    
    public class GreetingActor : ReceiveActor
    {
       public GreetingActor()
       {
          Receive<Greet>(greet =>
             Console.WriteLine("{0} Greeting {1}",
             Thread.CurrentThread.ManagedThreadId, 
             greet.Who));
       }
    }
    
  • Once built, add the Shared.dll as a reference to your AkkaClient, so you’ve got access to the same type of GreetingActor etc.
  • In the AkkaServer Main method simply place the following
    var config = ConfigurationFactory.ParseString(@"
    akka {
        actor {
            provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
        }
    
        remote {
            helios.tcp {
                port = 8080
                hostname = localhost
            }
        }
    }");
    
    using (var system = ActorSystem.Create("MyServer", config))
    {
       system.ActorOf<GreetingActor>("greeter");
       Console.ReadKey();
    }
    

    This code is taken from Remoting as is the next piece of code for the client

  • Now in the AkkaClient Main method place the following
    var config = ConfigurationFactory.ParseString(@"
    akka {
        actor {
            provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
        }
        remote {
            helios.tcp {
                port = 8090
                hostname = localhost
            }
        }
    }");
    
    using (var system = ActorSystem.Create("MyClient", config))
    {
       var greeter = system.ActorSelection(
          "akka.tcp://MyServer@localhost:8080/user/greeter");
    
       greeter.Tell(new Greet("Roger"));
    
       Console.ReadLine();
    }
    

Run the server and then the client and you should see (in the server console window) the Greeting Roger text.

What have we just done?

So as you can see, we’re using the ConfigurationFactory.ParseString to simply create our remoting configuration in both the client and server. For this example, both applications are expected to be available on the localhost and therefore require different ports to communicate through.

We then create our ActorSystem in each application, for the sake of this example, one is perceived as the server and one as the client, but the beauty of Akka.net is they can be deployed in a peer-to-peer manner (which we’ll look at also).

Our AkkaServer creates an instance of the GreetingActor and then waits for messages. The AkkaClient uses the ActorSelection method to locate the server Actor (or a known name greeter. Although ofcourse we could just find all Actors if we wished) and then via the Tell method sends a messages to the Actor running on the server.

Let’s move towards a Peer-to-Peer design

Time to create the classic peer-to-peer chat application. This is going to be very basic and built using the previous code. The only changes to the two solutions are in the Main methods. Keep the config code the same as it was, but in the server replace the existing code with

using (var system = ActorSystem.Create("MyServer", config))
{
   system.ActorOf<GreetingActor>("greeter");

   string msg;
   while (!String.IsNullOrEmpty(msg = Console.ReadLine()))
   {
      var greeter = system.ActorSelection(
          "akka.tcp://MyClient@localhost:8090/user/greeter");

      greeter.Tell(new Greet(msg));
   }
}

and in the client, the code is exactly the same except MyServer becomes MyClient and the akka.tcp line changes to akka.tcp://MyServer@localhost:8080/user/greeter. For completeness here’s the code in full anyway

using (var system = ActorSystem.Create("MyClient", config))
{
   system.ActorOf<GreetingActor>("greeter");

   string msg;
   while (!String.IsNullOrEmpty(msg = Console.ReadLine()))
   {
      var greeter = system.ActorSelection(
         "akka.tcp://MyServer@localhost:8080/user/greeter");

      greeter.Tell(new Greet(msg));
   }
}

If you run up both solutions, both will create their own greeter Actor and only upon receiving some input via Console.ReadLine, will try to connect to all greeter Actors on to other’s ActorSystem (i.e. server will try to send to client and vice versa).

All this is happening via TCP and hence we could just as easily move one of the applications onto another machine – as long as both are accessible to one another, they should seamlessly work.

So there you have it, a very basic introduction to peer to peer Akka.net objects.

Getting started with Akka.net

The actor model is a model for implementing highly concurrent and distributed systems. It’s implemented by frameworks/libraries such as the original Akka (for the JVM), Akka.net (the .NET implementation)and Orleans (and probably others).

See Actors for a great explanation of an implementation of an Actor object.

The general idea of the Actor model is that thread locking and other primitives are not required if changes to an object’s state can only happen on a single thread. To facilitate this, an application cannot interact with an Actor object directly, but instead passes messages to it – one might suggests this is analogous to marshaling code onto the UI thread in Windows applications (and others) or similar to using local message queues/bus such as used in Prism etc. if that helps visualize the process.

The Hello World example

As per the Akka.net website, we’ll start off with the Hello World example (from the Akka.net website).

  • Create a Console applications
  • Using Nuget, add the Akka.net 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 : ReceiveActor
    {
       public GreetingActor()
       {
          Receive<Greet>(greet =>
             Console.WriteLine("[Thread {0}] Greeting {1}",
             Thread.CurrentThread.ManagedThreadId, 
             greet.Who));
       }
    }
    
  • Finally we need to use the Akka.net ActorSystem to create proxies for our objects. So in the Main method we should now have
    var system = ActorSystem.Create("MySystem");
    var greeter = system.ActorOf<GreetingActor>("greeter");
    greeter.Tell(new Greet("Hello World"));
    

As already mentioned, the Greet class is used to wrap the data we want to apply/send to our Actor object. It hence should be a simple immutable object which we Tell (in Akka.net parlance) to the Actor.

The Actor, GreetingActor must derive from ReceiveActor and should be set-up to Receive messages of an expected type. We can set-up a Receive for multiple types and use Tell to pass those different types as messages to our Actor.

Obviously we cannot just create the Actor object ourselves, we need for the ActorSystem to know about it and handle our interactions with it. When we create an instance of the proxy to the Actor (via ActorOf) we need to give it a unique name to differentiate the instances of the Actor object (as we don’t get an actual instance but the proxy to it). Alternatively we can pass null (or leave it to it’s default argument) if we don’t supply a name for the Actor.

Finding our Actors

We can query” our ActorSystem for an existing Actor (or multiple Actors) using the ActorSelection method. This allows us to send messages to actors across distributed systems without knowing whether they exist or not.

For example, in the below code, we’ll create three actors without caring what their names are (i.e. they’ll be generated by the ActorSystem). All we care about is that somewhere, something accepts the Greet message.

var system = ActorSystem.Create("MySystem");

system.ActorOf<GreetingActor>();
system.ActorOf<GreetingActor>();
system.ActorOf<GreetingActor>();

system.ActorSelection("/user/*").Tell(new Greet("Hello World"));

This code locates all /MySystem/user/* created Actors, we send a message using Tell to all Actors which support receiving such a message.

Note: The /user part of the path is automatically created for us by the ActorSystem, in this case.

If you’ve taken an instance of an Actor from the ActorOf method, you can use the following, to get the path

var a = system.ActorOf<GreetingActor>("a1");

Console.WriteLine(b.Path.ToString());

this will output akka://MySystem/user/a1 as the path to the Actor.

Stopping an Actor

Obviously, if we can create an Actor, this must (in some way or another) exist in memory or be available within our system. But what if we want to get rid of an Actor and therefore stop it listening for messages. We can use the Stop method on the ActorSystem as follows

var a = system.ActorOf<GreetingActor>();

system.Stop(a);

Stop will immediate stop an Actor, but you can also send a message to the Actor to stop which obviously may not stop the actor immediately, using the PoisonPill, like this

var a = system.ActorSelection("/user/*");
a.Tell(PoisonPill.Instance);

In this example we get all Actors and send them the PosionPill.

We can also use the Kill message, as follows

var a = system.ActorSelection("/user/*");
a.Tell(Kill.Instance);

this will result in log the ActorKilledException to denote the actors that have been killed – the documentation on this seems to suggest this is probably the only reason to use Kill over PoisonPill or Stop.

Finally we can also stop an Actor using GracefulStop

var a = system.ActorOf<GreetingActor>();
var result = a.GracefulStop(TimeSpan.FromSeconds(5));

the main use of this form of stop is that we can get a result back (eventually) via a Task. The result is a Task hence we can tell when the Actor has been shutdown. In the above the TimeSpan is a timeout.

See How to Stop an Actor… the Right Way for a fuller explanation of stopping Actors.