Cluster Singleton in Akka
In a highly-available application, it is occasionally necessary to have some processing performed in isolation within a cluster, whilst still allowing for processing to continue should the designated worker node fail. This is trivial with Akka clustering support for the Cluster Singleton pattern.
For a motivating example, consider a system that processes large files from a clustered file system. It is important that any given file is processed exactly once. Atomic file management is difficult due to the lag time of the file system clustering. Any system that relies solely on file renaming or locking to designate which node is processing the file will most likely run into contention, leading to unreliable results. An alternative approach is to ensure only one node is actively seeking work. In this scenario no contention can possibly occur.
Akka has made things very easy for developers in the Java ecosystem who need this kind of support. Built upon its remote actor support, Akka enables clusters to be created - the formation of disparate actor systems into one logical actor system. Creation of a cluster is straight-forward, requiring only the configuration of a cluster-specific provider and one or more seed nodes. Akka handles the complexity of node membership for us, using a gossip protocol. In a short time it is easy to demonstrate a simple system that is aware of the joining and leaving of nodes and provides horizontal scalability.
Within a cluster there is implicitly always at most one node designated as leader. It is
possible to define an actor that is active only on the leader node. This is the Cluster
Singleton pattern. It is enabled simply by defining actor properties using the akka.contrib.pattern.ClusterSingletonManager
.
val clusterSingletonProperties = ClusterSingletonManager.props(
singletonProps = Props(classOf[YourSingletonActor]),
singletonName = "the-singleton",
terminationMessage = PoisonPill,
role = None)
system.actorOf(clusterSingletonProperties, "clusterSingleton")
The resulting actor will always be created on a node when that node becomes the leader. It will not
exist more than once in a cluster. However it is possible that, through an unfortunate sequence of
seed node termination and restarts that you obtain two clusters! (In which case you will certainly
have two cluster singletons running). The configuration
property akka.cluster.role.$role.min-nr-of-members
can be used to ensure that
the cluster is not effected until a quorum is established.
I have derived a simplified example of cluster singleton usage from the provided typesafe activator examples. Clone it from GitHub and follow the instructions in the readme to observe the cluster singleton in action. https://github.com/Synesso/scratch-akka-cluster-singleton.