The singleton pattern is a popular software design pattern that defines the use of a single shared instance of a class in an environment. The usual implementation strategy for the singleton design pattern creates one instance for each cluster member. This might have unintended consequences for an application, such as data consistency issues.
Sometimes the application logic requires that only one instance of a particular class runs for the whole cluster. A developer could extract this instance to run as a service deployed into a single non-clustered Red Hat JBoss Enterprise Application Platform (JBoss EAP) instance. Then, the clustered applications can access to this supposed singleton service. But then the service would become a single point of failure.
Many developers incorrectly assume that an EJB annotated with the @Singleton annotation works correctly as a clustered singleton.
An @Singleton annotated EJB, as stated in the EJB specification, produces that each JVM in a distributed application server gets one object instance.
The methods to implement a singleton using only standard JVM or Jakarta EE features also creates one instance per JVM.
This means one instance for each JBoss EAP server in a cluster.
When an application requires a singleton to work as a cluster-wide singleton, and still have high availability, developers and JBoss EAP administrators have to work together to extract the singleton parts from the clustered application, and then adapt it to use one of the following specific JBoss EAP 7 approaches:
Similar to the feature from JBoss EAP 5. The application that you deploy as a singleton deployment runs only in one cluster member. If this cluster member fails, the deployment starts to run in a different member,
Enhanced version of the JBoss EAP 6 feature. The clustered singleton service runs only in one cluster member, called master or primary node. If this primary node fails, then there is an election process to select the new primary node.
Both approaches allow an application to work as an active-passive HA application inside a JBoss EAP cluster. They differ on the configuration details and changes required to the application packaging and the source code.
The singleton subsystem manages the singleton deployments and services.
The singleton subsystem employs an infinispan cache to register all singleton deployments and services, and their location in the cluster.
The JBoss EAP server instance that runs a singleton application is called the master, or primary server for that application.
You can configure the singleton subsystem with different election policies that define the primary server.
The following are the two kinds of election policy provided by JBoss EAP 7:
simple
The first node to join the cluster runs the singleton application.
random
A random node is selected to run the singleton application.
An election policy can optionally specify a preferred server which, when available, becomes the primary for all the singleton applications under that policy.
The policy refers to the node name as specified by the jboss.node.name system property.
The default JBoss EAP configuration files provide a simple election policy called default with no preferred server.
The following listing shows this policy:
...output omitted... <subsystem xmlns="urn:jboss:domain:singleton:1.0"> <singleton-policies default="default"> <singleton-policy name="default" cache-container="server"> <simple-election-policy/> </singleton-policy> </singleton-policies> </subsystem> ...output omitted...
The following commands shows how to create a custom election policy of the random type.
The custom election policy defines the servera1 as the preferred server:
/subsystem=singleton/singleton-policy=custom/election-policy=random:add()
/subsystem=singleton/singleton-policy=custom/election-policy=random:list-add(\ name=name-preferences, value=servera1)
If the primary server fails, the singleton subsystem runs a new election for all singleton applications that were using the failed server.
Then, these applications restart in the new primary server.
Each singleton application must provide their own mechanisms to recover, or recreate in-memory data lost in the failed primary server.
One potential issue with a singleton application are the network partitions, or split brain scenarios: Two sets of servers from the same cluster cannot connect to each other, but servers from one set have no issue connecting to servers from the same set. Each set of servers continue to work as a surviving cluster, but without communicating with the other set.
A split brain scenario has two or more independent clusters where there must be only a single cluster. This scenario can easily lead to data consistency issues. To prevent that, an election policy can specify a quorum. A quorum is the minimum required number of cluster members to elect a new primary node. If there is no a quorum, then the remaining cluster members do not join the cluster.
To configure a quorum of three servers, use the following command:
/subsystem=singleton/singleton-policy=custom:write-attribute(name=quorum, value=3)
The quorum should be at least N/2+1, where N is the anticipated total number of cluster members.
Singleton deployments are similar to the HASingletonDeployer object from JBoss EAP 5 and earlier.
There was no similar feature in JBoss EAP 6.
A singleton deployment is a way to mark a deployment as a cluster-wide singleton, without the need to use specific JBoss EAP 7 APIs.
An application package is considered to be a singleton deployment if it contains the $APP/META-INF/singleton-deployment.xml JBoss EAP deployment descriptor.
This file refers to the election policy for the singleton application.
The following example refers to the custom policy from the previous example:
<singleton-deployment xmlns="urn:jboss:singleton-deployment:1.0" policy="custom"/>
Although this approach does not require an application to use JBoss EAP 7 specific APIs, it still requires the original clustered application to access the extracted singleton application, for example, using remote EJB calls or JMS.
Singleton services are implemented the same way as internal JBoss EAP services. Their source code uses WildFly Core APIs. Although the deployment services are more intrusive than singleton deployments, singleton services provide the following advantages in very specific use cases:
The election policy can be defined by the application, without the need to configure the singleton subsystem.
It allows JBoss EAP modules to start cluster-wide singleton services, which allows a JBoss EAP module to work as an active-passive clustered service.
To learn more about implementation of singleton services and deployments, see the references section.
JSR-345: EJB 3.2 specification
For more information about singleton services, see the HA Singleton Service section in the Development Guide in the Red Hat JBoss EAP documentation at https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.4/html-single/development_guide/index#clustered_ha_singleton_service
For more information about singleton deployments, see the HA Singleton Deployments section in the Development Guide in the Red Hat JBoss EAP documentation at https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.4/html-single/development_guide/index#ha_singleton_deployments