Akka.Net helps build a solution that can both scale-up as well as scale-out. And the key concept that makes it happens is the messaging infrastructure of Akka.Net.
Akka.Net does not provide guaranteed delivery, just like any other actor implementation. What is supports is the at most once delivery of the message. Which means the message is delivered zero or one time. This is the cheapest form of message delivery as well as the fastest.
But in Akka.Net the message ordering is supported per sender-receiver pair (a feature specific to Akka.Net implementation of Actor framework).
To follow along with this post, I would strongly suggest using reading my previous post: and Akka in .Net Core.
Akka Message Communication
So far in the examples, I have created, I have just focused on the Tell
method for sending messages. There is another method that helps with message communication, and that is Ask
. Unlike Tell
which is a fire and forget, Ask
follows send and receive the pattern. Which technically is like polling and creates performance implications. And hence you will not see it often implemented.
To show how the Ask
method works, I will create a new class AskPatternActor
, which will override the OnReceive
to print the incoming message.
public class AskPatternActor : UntypedActor
{
protected override void OnReceive(object message)
{
Console.WriteLine($"Message regeived {message}");
}
}
Furthermore I will update the Main
method to use Ask
on the actor for sending message. And since Ask
follows send and receive pattern, I will fire the call in a separate thread using a Task
.
class Program
{
static void Main(string[] args)
{
var actrsys = ActorSystem.Create("test-actor-system");
var askRef = actrsys.ActorOf(Props.Create(), "ask-actor");
var askTask = Task.Factory.StartNew(() => askRef.Ask("Ask Actor"));
askTask.Wait();
Console.ReadLine();
}
}
Finally, we will see in the output console printing out the message.
Akka.Net PoisonPill
Akka.Net has a special message type that is represented by the PoisonPill
class. Using the PoisonPill.Instance
we can stop an Actor. This is a very useful message when the supervisor wants to stop a subordinate actor.
The PosionPill
messages are treated like any other message by the Akka.Net messaging infrastructure. This means it will not take any precedence over the other message already in the mailbox queue.
To test this I will use the same AskPatternActor
class, just add an extra Console.WriteLine
inside of OnReceive
event handler. And I will also add the PostStop
handler to print when the actor is stopped.
Finally, I will update the implementation of the Main method.
public class AskPatternActor : UntypedActor
{
protected override void PostStop()
{
Console.WriteLine("AskPatternActor PostStop method");
}
protected override void OnReceive(object message)
{
Console.WriteLine("Inside of AskPatternActor OnReceive method");
Console.WriteLine($"Message regeived {message}");
}
}
class Program
{
static void Main(string[] args)
{
var actrsys = ActorSystem.Create("test-actor-system");
var askRef = actrsys.ActorOf(Props.Create(), "ask-actor");
askRef.Tell(PoisonPill.Instance);
Console.WriteLine("Main function");
Console.Read();
}
}
When we run the code, we will never see the WriteLine statement inside of the OnReceive
of the AskPatternActor
. But we will see the output from the PostStop
event handler.
Akka.Net Kill.Instance
For stopping an actor we can also use the special message type which is represented by the Kill
class. We can send a Kill.Instance
as message to an Actor. And this will stop the actor just like the PoisonPill.Instance
message.
But the difference here is that the actor will through an exception of type ActorKilledException
. And in this case, if there is any supervision strategy at the supervisor will kick in. I am yet to find a very good use case for using this. When I get it, I will update the post.
In terms of code, I will use the same AskPatternActor
class as an actor. But I will just change the Main
method to pass the Kill.Instance
message.
class Program
{
static void Main(string[] args)
{
var actrsys = ActorSystem.Create("test-actor-system");
var askRef = actrsys.ActorOf(Props.Create(), "ask-actor");
askRef.Tell(Kill.Instance);
Console.WriteLine("Main function"); Console.Read();
}
}
In this case, along with stopping the actor, we will also receive the ActorKilledException
.
Conclusion
In this post, I have gone through a few concepts related to Akka.Net messaging. The logical next step would be to start looking into remote actors. So in the next post, I will start working with remote actors.