Wolfgang Liebich
Wolfgang Liebich

Reputation: 408

AKKA.NET question: Is it a good idea to have more than one ActorSystem in an application?

I am writing plugins for a C# Desktop application (not a server but a Desktop GUI application). To make our threading issues simpler I am researching if I can employ AKKA.NET inside of these plugins. The plugins are principally independend from each other. Thus from an architecture POV, it is natural to give each plugin it's own "private" ActorSystem instance. The advantage of this approach is that the plugins are maximally isolated from each other. On the other side, I have read some articles about Akka for the JVM which tell me that having too many ActorSystem instances in an application is an anti pattern because an ActorSystem is quite heavyweight.

A realistic number of concurrent plugins is 10-20, i.e. the appliction could then have at worst 20 ActorSystem instances running inside. Again, this is a GUI desktop application, which is often run in terminal server sessions (i.e. there may be many of these GUI applications running on a terminal server).

So - is this simplicistic approach (one ActorSystem per library) tenable? Or is it better to devise an approach using a global ActorSystem, which uses per-plugin top-level actors to isolate the plugins. This approach is probably better for performance, but I am a bit concerned about it because the plugins are not as isolated from each other.

So - is this "multiple-system" approach a good architectural approach, or is it better to stick with the "one global system" design? What are your experiences here?

Upvotes: 3

Views: 878

Answers (2)

Aaronontheweb
Aaronontheweb

Reputation: 8394

So - is this simplicistic approach (one ActorSystem per library) tenable? Or is it better to devise an approach using a global ActorSystem, which uses per-plugin top-level actors to isolate the plugins. This approach is probably better for performance, but I am a bit concerned about it because the plugins are not as isolated from each other.

This is the approach I'd go with - have each plugin create its own hierarchy of actors using the same ActorSystem. Each plugin can have its own actor and message types with no overlap. If you ended up running multiple ActorSystems you'd still end up having multiple actors all using the same threads, because by default the ActorSystem schedules actors onto the same .NET Thread Pool that the TPL and other parts of your desktop application might use. Having one ActorSystem manage all of that might be easiest since that way you have a single dispatcher marshalling the execution on the same group of threads (less competition.)

Upvotes: 5

Bartosz Sypytkowski
Bartosz Sypytkowski

Reputation: 7542

If isolation is your goal, then multiple actor systems won't solve your issue - ActorSystem is just an ordinary class, you still can share the data using i.e. static fields, and (probably) you can still access other actor systems if you are determined enough. Therefore actor system won't help you if you run untrusted code.

True in-process isolation in .NET could be achieved by using AppDomains in old .NET Framework or AssemblyLoadContext in .NET Core.

Keep in mind, that using actor programming paradigm is serious design decision and component isolation can be achieved in many ways. So if component isolation is the only reason, why you decided on using actors, you may want to look out and reconsider other options.

Akka.NET Extensions

You can use actor per plugin, or even use native Akka.NET extensions - this is mechanism that allows us to build plugins for the akka itself. Almost every higher level feature of Akka is built as an extension: cluster, remoting, cluster sharding, persistence etc.

To build an extension you need two classes:

public class MyExtensionProvider : ExtensionIdProvider<MyExtension>
{
    public override MyExtension CreateExtension(ExtendedActorSystem system) =>
        new MyExtension(system);
}

public class MyExtension : IExtension
{
    public MyExtension(ExtendedActorSystem system) { }
}

You can register and retrieve those extensions from code itself via: actorSystem.WithExtension<MyExtension, MyExtensionProvider>() (checkout overrides of that method too). You can also register them directly in HOCON - this way when provided via HOCON config, they will be started automatically on system start:

akka.extensions = [
    "MyNamespace.MyExtensionProvider1, MyAssembly",    
    "MyNamespace.MyExtensionProvider2, MyAssembly"
]

Upvotes: 3

Related Questions