Comparing Microsoft Orleans and Azure Service Fabric Actors


Never has there been such a good time for C# developers wanting to develop software based on Virtual Actors.

At the moment there are two systems available, Orleans and Service Fabric Reliable Actors.

Other actor frameworks are available of course. On the JVM there is Orbit, a Virtual Actor implementation, and Akka with more traditional actors.

In .NET there is also Akka.NET, a port of the JVM project.

And of course there’s Erlang.

I’m concentrating on comparing the virtual actor feature of Service Fabric and Orleans, because attempting to compare anything else wouldn’t be fair. Akka.NET, for example, is an implementation of the Actor framework, but has a different design to the ‘Virtual Actor’ concept.

Please note that Service Fabric is a more broad offering than Orleans. It offers replicated storage and service hosting (for example), with the actors being just one aspect. I’m limiting my comparison between the actor implementations, and not a full feature comparison.

Please also note that in Orleans, Actors are called ‘grains’.

The Comparison

The two implementations are very similar, and share more in common than there are differences.

This table focuses on where there are variations.

Orleans Service Fabric
Source Code Open Source Open Source
Partition Tolerance (CAP) AP - During a network partition Orleans will maintain availability, this may result in some duplicate grain activations which are removed when the network heals. CP can be achieved on a call-by-call basis by deferring to the storage tier. CP - During a network partition or node failure, if a consensus cannot be reached between nodes, actors may fail to activate and persist state.
Actor Placement Orleans uses a distributed hash table to record actor placement. It provides several placement strategies, including 'prefer local' and 'random'. Service Fabric uses a deterministic hash of the actor identity to place actors in a partition. Partitions are distributed across the nodes in the cluster.
Actor Identity Guid, string or long, as well as compound keys (guid + string, long + string), as well as identifying different concrete class implementations. Guid, string or long.
Message Serialization Custom binary serializer. Data contract serializer.
Persisting State A grain can use a POCO class to serialize state to an underling provider model. Providers include table storage, blob storage and SQL An actor has a state dictionary, keys can be loaded and persisted as required. Values must be annotated with the Data Contract serialization attributes. State is stored in local replicated storage. A provider model allows persistence in alternative stores.
Pub/Sub Messaging Grain observers allow pub sub messaging between actors and actors, and actors and clients. Actor events allow pub sub messaging between actors and clients.
Streaming Streaming between actors or between actors and clients. Different underlying stream providers can provide different semantics. None
Cluster Membership Membership is outsourced using a provider model. Providers include table storage, SQL, Consul and Zoo Keeper. Service Fabric provides its own cluster membership using a replicated log.
Stateless Workers Stateless Worker grains can have multiple activations to handle high workloads. Activations are always local to the calling grain. None
Controlling Actor Lifecycle Grains can request to defer deactivation, or request immediate deactivation. An actor can be deleted by a client.
Reentrancy Full reentrancy is supported. Grains are not reentrant by default. Reentrancy is only enabled within a callchain. This can be disabled.
Hosting Orleans is a library which can be hosted by any .NET 4.5.1 process, including on-premises, Worker Roles in Azure and Service Fabric. It also comes with a host executable to run directly on Windows. Orleans 2.0 can be hosted by a .NET Core proces on Linux or Windows. Service Fabric Actors can run on Windows or Azure. Service Fabric can run on Linux, but the Actors must be witten in Java.

Features such as Timers, Reminders and Interceptors have no significant difference.