It is time to show you how to build a cluster with Domain mode within JBoss EAP 7. Before you read this blog I suggest you to review the following blogs: JBoss terminologies, the Domain architecture understanding, and how to create a Domain. All these bogs will help you to better understand what we will do today 😉

Environment Preparation

The domain will look like the below architecture:
Domain Architecture

On three VMs:

  • vmjboss: master, hosting the Domain Controller
  • vmjboss1: slave1
  • vmjboss2: slave2

I already installed JBoss EAP 7.0.0 on these VMs under $JBOSS_HOME, and created the domain according to the above architecture. If you need any help to create the domain please check this blog.

Start the Domain

I started the domain, I can see that both slaves joined the master:

[Host Controller] 16:53:44,707 INFO  [org.jboss.as.domain.controller] (Host Controller Service Threads - 36) WFLYHC0019: Registered remote slave host "slave1", JBoss JBoss EAP 7.0.0.GA (WildFly 2.1.2.Final-redhat-1)
[Host Controller] 16:54:28,710 INFO  [org.jboss.as.domain.controller] (Host Controller Service Threads - 37) WFLYHC0019: Registered remote slave host "slave2", JBoss JBoss EAP 7.0.0.GA (WildFly 2.1.2.Final-redhat-1)

On slave1 and slave2, you should see the below in the logs:

[Host Controller] 16:54:26,644 INFO  [org.jboss.as.host.controller] (Controller Boot Thread) WFLYHC0148: Connected to master host controller at remote://vmjboss:9999
[Host Controller] 16:54:26,689 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: JBoss EAP 7.0.0.GA (WildFly Core 2.1.2.Final-redhat-1) (Host Controller) started in 13192ms - Started 43 of 44 services (13 services are lazy, passive or on-demand)

Create Server Group

Now, our domain is up and running, we will create the ServerGroup named GroupHA.
You can use the –command argument to provide a single CLI command to execute. The management CLI will terminate once the commands have completed.

[jboss@vmjboss ~]$ $JBOSS_HOME/bin/jboss-cli.sh -c --controller=vmjboss:9990 --command="/server-group=GroupHA:add(profile=ha,socket-binding-group=ha-sockets)"
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}

To build a cluster the profile should be ha or full-ha where needed subsystems are configured by default:

  • Infinispan: An architecture used for caching objects and also replicating objects between caches. The Infinispan subsystem provides caching, state replication, and state distribution support.
  • JGroups: A framework for nodes to communicate with each other using either UDP or TCP.

For more information about profiles read this blog 😉

Create Servers

From the master, create the server1 on slave1:

[jboss@vmjboss ~]$ $JBOSS_HOME/bin/jboss-cli.sh -c --controller=vmjboss:9990 --command="/host=slave1/server-config=server1:add(group=GroupHA,socket-binding-port-offset=100)"
{
    "outcome" => "success",
    "result" => {
        "step-1" => {"outcome" => "success"},
        "step-2" => {"outcome" => "success"},
... 
        "step-255" => {"outcome" => "success"},
        "step-256" => {"outcome" => "success"}
    },
    "server-groups" => undefined
}

The port-offset is set to 100 to avoid port conflict with other instances running on the same VM/IP address.

Create the server2 on slave2:

[jboss@vmjboss ~]$ $JBOSS_HOME/bin/jboss-cli.sh -c --controller=vmjboss:9990 --command="/host=slave2/server-config=server2:add(group=GroupHA,socket-binding-port-offset=200)"
{
    "outcome" => "success",
    "result" => {
        "step-1" => {"outcome" => "success"},
        "step-2" => {"outcome" => "success"},
... 
        "step-255" => {"outcome" => "success"},
        "step-256" => {"outcome" => "success"}
    },
    "server-groups" => undefined
}

Both servers have been assigned to the server group GroupHA created before.

Start both servers:

[jboss@vmjboss ~]$ $JBOSS_HOME/bin/jboss-cli.sh -c --controller=vmjboss:9990 --command=":start-servers(blocking=true)"

{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}

What blocking=true means?
In fact, if blocking=true is set your command will hang or wait until the operation on the server side returns and tells the CLI that the operation is complete.

Cluster Creation

A cluster is a collection of servers that communicate with each other in such a way that they improve the availability of services by providing the following capabilities:

  • High Availability (HA): a service has a very high probability of being available.
  • Scalability: a service can handle a large number of requests by spreading the workload across multiple servers.
  • Failover: if a service fails, the client can continue processing its tasks as another cluster member takes over the client’s requests.
  • Fault Tolerance: a server can guarantee correct behavior even if fail over occurs.

The most common way to achieve scalability and high availability is to use the following together:

  • Load balancer: Often a piece of hardware, or a service like Apache httpd.
  • Data replication services: A service such as memcached or a framework (Infinispan)

Application Preparation

To take advantage of the high availability features of clustered servers, an application first has to be marked as being distributable. To do so, include the tag in the web.xml for the application. The following is extracted from the web.xml of my cluster.war application:

<?xml version="1.0"?>
  <web-app ...>
    <distributable/>
  </web-app>

Application Deployment

Now, I will deploy the cluster.war application on the Server Group GroupHA, so on all servers assigned to this Server Group.

[jboss@vmjboss ~]$ $JBOSS_HOME/bin/jboss-cli.sh -c --controller=vmjboss:9990 --commands="deploy /opt/data/cluster.war --server-groups=GroupHA,deployment-info --name=cluster.war"
NAME        RUNTIME-NAME 
cluster.war cluster.war  

SERVER-GROUP       STATE     
GroupHA            enabled

As you can see the output of deployment-info, the cluster.war application has been deployed and enabled on GroupHA, so on server1 and server2.

Go, and check the slave1 and slave2 logs, you should see:
On slave1:

[Server:server1] 17:45:51,095 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 68) WFLYUT0021: Registered web context: /cluster
[Server:server1] 17:45:52,662 INFO  [org.infinispan.CLUSTER] (remote-thread--p11-t1) ISPN000310: Starting cluster-wide rebalance for cache cluster.war, topology CacheTopology{id=1, rebalanceId=1, currentCH=DefaultConsistentHash{ns=80, owners = (1)[slave1:server1: 80+0]}, pendingCH=DefaultConsistentHash{ns=80, owners = (2)[slave1:server1: 40+40, slave2:server2: 40+40]}, unionCH=null, actualMembers=[slave1:server1, slave2:server2]}
[Server:server1] 17:45:52,681 INFO  [org.infinispan.CLUSTER] (remote-thread--p11-t1) ISPN000310: Starting cluster-wide rebalance for cache routing, topology CacheTopology{id=1, rebalanceId=1, currentCH=DefaultConsistentHash{ns=80, owners = (1)[slave1:server1: 80+0]}, pendingCH=DefaultConsistentHash{ns=80, owners = (2)[slave1:server1: 40+40, slave2:server2: 40+40]}, unionCH=null, actualMembers=[slave1:server1, slave2:server2]}
..
[Server:server1] 17:45:55,104 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 65) WFLYSRV0010: Deployed "cluster.war" (runtime-name : "cluster.war")

On slave2:

[Server:server2] 17:45:52,454 INFO  [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (MSC service thread 1-1) ISPN000094: Received new cluster view for channel hibernate: [slave1:server1|1] (2) [slave1:server1, slave2:server2]
...
[Server:server2] 17:45:53,777 INFO  [javax.enterprise.resource.webcontainer.jsf.config] (ServerService Thread Pool -- 66) Initializing Mojarra 2.2.12-jbossorg-2  for context '/cluster'
[Server:server2] 17:45:55,334 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 66) WFLYUT0021: Registered web context: /cluster
[Server:server2] 17:45:55,451 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 65) WFLYSRV0010: Deployed "cluster.war" (runtime-name : "cluster.war")

Which means that a cluster has been created once your distributable application has been deployed on servers server1 and server2 (members of the server group GroupHA).

The application is available from server2:
Application available on server2

The application is also available from server1:
Application available on server1

Now, you can easily create new server(s) and assign it/them to GroupHA, the application cluster.war will be deployed on it and server3 will join the cluster automatically.

Now, data is replicated between the cluster members, but we will better see clustering benefits with a LB on top. That’s will be the topic of our my next blog, I will show you how to configure JBoss EAP to play as Load Balancer, in the meanwhile don’t hesitate to ask questions 😉

Take care and stay safe 🙂