joaofbantunes joaofbantunes - 10 months ago 108
C# Question

Implement one actor per user (Child-Per-Entity pattern) in a cluster using Akka.NET

I'm doing a little sample to learn a bit about Akka.NET. I'm trying to implement a Child-Per-Entity pattern (as seen in Akka.NET Design Patterns), where I have one actor per user (across a cluster).

To do this I was trying to use a ClusterRouterPool with ConsistentHashingPool, that distributed the messages to some parent actors that kept an IDictionary(int,IActorRef) with the child actors indexed by their id (used as the key for the consistent hash).

This approach however doesn't seem to be working as I initially expected because:

  1. Having different clients creating routers will result in them creating multiple parent actors, which in turn will create repeated child actors.

  2. Even if I had a single router, if a new node joins the cluster what happens? Wouldn't the router re-balance itself causing again the routing being made to new parent actors that would create repeated child actors?

There's a somewhat similar question here on StackOverflow that points to using Akka.Cluster.Sharding, but on Akka.NET Design Patterns Aaron has a comment stating he used the consistent hash router approach, hence why I started it in the first place.


Answer Source

I think, that key concept is to understand a difference between Akka.Cluster.Sharding and consistent hash router:

  • In Akka.Cluster.Sharding message-actor routing is based on (ShardId, EntityId) identifier. This is 1-to-1 relationship, which means that messages with different identifiers will always be routed their dedicated actors. Moreover cluster sharding will assure, that messages are send correctly to their actors even when number of nodes in the cluster will change.
  • In consistent hash router approach important thing to understand is a concept of the key space - it's a space of all possible message identifiers to be received. This space is then divided by the number of actors behind the router - this means that each actor is not associated with a single identifier, but a range of it. This is 1-to-many relationship, so that it's possible that two messages with different ids will be routed to the same actor. Moreover as number of nodes in the cluster will change, number of actors behind that router will also change - as result, key range is not fixed for an actor and it may change over time. This means that message with the same identifier may be routed to a different actor when the cluster size will change.

Therefore I think, that cluster sharding is what you're looking for. Inside examples section of Akka.NET core repository you may find a sample which addresses your case directly.