Actor model concept fascinated me since I’ve heard about it for the first time. It’s been on my todo list ever since and Get Noticed 2017 is great opportunity to give it a try. That’s why there is an actor responsible for almost anything in Me2.0. But, what is an actor, actor model and are benefits of using it in our projects? You’ll find out in a minute.
What is Actor Model?
Actor model is one of many programming models and it’s basic principle is that basically everything is an actor (or message but we’ll get there soon). It is not necessary to use actore model i every single one module in your application. In example – your controllers and surrounding layer probably will be just endpoints for your real actor model beneath.
What is an Actor?
So what is an actor? It’s just an object with very specific behavior. In akka.NET it is a class that derives from ActorBase class. But it’s not something that makes actor special and we’ll get there in post about creating actors. There are some basic principles and concepts that makes simple C# object an actor.
First of all there is matter of state and modifying it. Actor have state but can change it only from within itself. All properties, fields and most of methods in actor are private. And any interaction with an actor are done through messages.
Actors and messages
Every actor have it’s own personal mailbox. It’s used to store incoming messages. When actor receive a message it runs some operations that we define ourselves in simple lambdas. Actor does so one message at a time.
While it’s possible to have hundreds, thousands and even millions of concurrent actors in our application and every one of them can process independent operations in the same time as it’s colleagues and then send even more messages. Every one of those messages are being processed by receiving actors one at a time. It makes concurrent operations VERY simple, but we’ll talk about this in some other post.
Actors are lazy beings. Until they receive any message they’re just sitting in memory and doing nothing. But as soon when they receive something, they’re starting to process. They can change state, read message contents, use them to do some operations, send some messages to other actors or even create some child actors. That’s pretty much wraps everything that actor should be able do.
What is an message?
We know what is an actor, what it should do and how actors like to chatter and sending messages to each other. But what exactly is a message?
Its simple C# class that contains some data. Message contents should be impossible to change from the outside that’s why I’m using public geters/private seters in them. There are no formal requirements for an object to be a message but it is a good practide to use some kind of naming convention for them. My messages just ending with word Message ie. SubscribeTagMessage.
Every message have one job – transfer some data between actors. Inside of an actor you can handle them as you see fit so in case when actor receives mentioned SubsribeTagMessage you could for example grab tag name from it and add it to list of subscribed tags, after that you can use some other data from message to compose some other message and send it to some other actor to perform another task, related or not.
Why not simple objects and methods?
Why create some overisolated actors with no easily accesible properties or methods? Why send message and not simply invoke public method?
First of all, actor is object that resides in memory and just waitining for something to happen. You don’t need to create new actor instance every time that you want it to do something, it also stores state. That means actors are rather fast, at least when being reused.
Second thing is much more fun. As I mentioned you could have many of active actors simmultaneously in your system. And by many I mean hundreds of thousands, even millions. Every one of them will work in parallel, one message at a time. It’s much simpler concurrency that managing threads by hand. Even unit testing of actors is much simpler that testing multiple threads.
Third reason is even better one. You can create remote actors on other machines in other server farms, basically whenever you want. You can configure your actor model applications to reuse some elements. And it’s not just data, it can be existing, working actors. Customer related actors are rather lightweight? Just put them in some separate low tier cloud application. But if your order services are using most of your power and do almost all heavylifting, you could just move all of them to some other server. You can even run some part of application on cloud app service and some on some sort of virtual machine or even on-premises server. It’s simple and I hope we’ll cover that in one of future articles about akka.NET. Even more beautiful in that is fact that aside from configuring remote settings it is possible that nothing will change in your code, maybe you’ll need to extract something to separate service but that’s all.
Last reason is surprising. Because while actor model concept could be hard to grasp at the beggining, using it is very simple and intuitive. It takes a while to get used to work with actor and messages, but it’s worth it.
Did you just said “in memory”?
In prevous section of this article you could read something that could disturb you a bit. That was the part about actors sitting in memory and waiting for messages.
Yes, actors are not disposed and they’re staying alive and active in memory just waiting for any message. Isn’t this a waste? No, if actor is being reused. Memory overhead is as small as around 400 bytes per actor and we’re saving on actor initializing.
But what about application crashes and restarts? What’ll happen with actor state then? By default, it’s gone. But we can easilly persist actor state by persisting incoming messages and/or snapshots, just like in Event Sourcing. I’ll make post just about that soon enough.
Other fun stuff.
Actor model offers many benefits for your application. I haven’t mentioned anything about self healing (actor model is really stable ecosystem), switchable actor behaviors, extensibility and other cool stuff that you could do with akka.NET. I’ll cover some of those fun features in following weeks.
In next post we’ll create our simple actor system, actor or two and we’ll send some basic messages between them. That will cover some of technical basics. We’ll follow with dependency injection in actors, persisting messages, logging, testing actors and some other related topics.