What is Cluster Singleton in Akka?

A Cluster Singleton in Akka is a feature that ensures a single instance of an actor is running across the entire cluster at any given time. This is useful for scenarios where you need centralized processing or coordination within a distributed system, but still want fault tolerance and failover support.

Key Features of Cluster Singleton :
  1. Single Instance Across the Cluster:

    • Only one instance of the singleton actor exists in the entire cluster, regardless of the number of nodes.
  2. Automatic Failover:

    • If the node hosting the singleton actor fails or leaves the cluster, the actor is automatically recreated on another node.
  3. Cluster Membership Awareness:

    • The singleton is tied to the cluster's lifecycle and automatically adapts to changes in the cluster (e.g., nodes joining or leaving).
  4. Location Transparency:

    • Other actors or components can send messages to the singleton without needing to know where it is currently running.
How Cluster Singleton Works :
  1. Singleton Manager:

    • The SingletonManager is responsible for managing the singleton actor across the cluster.
    • It ensures that only one instance of the singleton actor exists at any time.
  2. Singleton Proxy:

    • The SingletonProxy allows other actors in the cluster to communicate with the singleton actor without worrying about its physical location.
  3. Leader Node:

    • The cluster leader is typically responsible for hosting the singleton actor. If the leader changes, the singleton will move to the new leader node.
Configuration for Cluster Singleton :

You need to define a SingletonManager and (optionally) a SingletonProxy in your code.

Example : Cluster Singleton Implementation
import akka.actor.{Actor, ActorSystem, Props}
import akka.cluster.singleton._
import com.typesafe.config.ConfigFactory

object ClusterSingletonExample extends App {
  // Actor to be used as a singleton
  class SingletonActor extends Actor {
    override def receive: Receive = {
      case message => println(s"Singleton Actor received: $message")
    }
  }

  // Create ActorSystem with cluster configuration
  val config = ConfigFactory.load("application.conf")
  val system = ActorSystem("ClusterSystem", config)

  // SingletonManager definition
  val singletonManager = system.actorOf(
    ClusterSingletonManager.props(
      singletonProps = Props[SingletonActor], // Props for the singleton actor
      terminationMessage = PoisonPill,       // Message to terminate the singleton
      settings = ClusterSingletonManagerSettings(system)
    ),
    name = "singletonManager"
  )

  // SingletonProxy definition
  val singletonProxy = system.actorOf(
    ClusterSingletonProxy.props(
      singletonManagerPath = "/user/singletonManager", // Path to SingletonManager
      settings = ClusterSingletonProxySettings(system)
    ),
    name = "singletonProxy"
  )

  // Send a message to the singleton actor via the proxy
  singletonProxy ! "Hello, Singleton!"
}