January 5, 2013

How to Cluster Domain JBoss EAP 6 and AS 7

Introduction

In my previous blog I showed how to cluster with JBoss EAP 6.0.3 in standalone mode, but standalone mode is really used in production, where the domain mode is the preferred way to manage multiple JBoss installations.

In this blog I will also cluster two JBoss nodes, but started in domain mode. To achieve that we need a domain master (domain controller) and slave (host controller), that push and respectively receive configuration. The deployment scenario is the following.

I have in the deployment diagram also added the concerned configuration file for each artifact, which I hope will help you to remember which configuration files goes to which artifact. Lets get started, but first some prerequisites.

Prerequisites:

In this blog I will start everything up on the same machine, which is adequate for testing, but of course not for production, so when you move to production you need to change interfaces IP for each JBoss. But that is about it. Lets get started.

To simulate and keep things separated I have extracted the jboss-eap-6.0.1.zip into three folders:

  • domain
  • host1
  • host2

Domain Controller

The domain controller is configured with three configuration files.

  • domain.xml - main configuration files
  • host-master.xml - boot up configuration files, telling that this is domain controller.
  • host.xml - additional configuration files for server group, such as system-wide properties and JVM configuration.

Lets first define our server group in ./domain/domain/configuration/domain.xml.

    <server-groups>
        <server-group name="cluster-ha" profile="ha">
            <jvm name="default"/>
            <socket-binding-group ref="ha-sockets"/>
        </server-group>
    </server-groups>

Then we will leave the ./domain/domain/configuration/host-master.xml unaltered and use defaults. The part that points out that this is domain controller is the below.

    <domain-controller>
       <local/>
    </domain-controller>

The last thing we need to do is to create a management user in the domain controller.

$ ./domain/bin/add-user.sh 

What type of user do you wish to add? 
 a) Management User (mgmt-users.properties) 
 b) Application User (application-users.properties)
(a): a

Enter the details of the new user to add.
Realm (ManagementRealm) : 
Username : domainadmin
Password : 
Re-enter Password : 
About to add user 'domainadmin' for realm 'ManagementRealm'
Is this correct yes/no? yes
Added user 'domainadmin' to file '/home/magkar/tmp/domain/standalone/configuration/mgmt-users.properties'
Added user 'domainadmin' to file '/home/magkar/tmp/domain/domain/configuration/mgmt-users.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="cGFzc3dvcmQ=" />

Now we are ready to start the domain controller.

$ ./domain/bin/domain.sh --host-config=host-master.xml

If you wanted to bind the domain controller to a specific IP, you would have used the -Djboss.bind.address.management. Which property you see in the interface element in the host-master.xml configuration file.

Now lets move onto the host controller.

Host Controller

A host controller is a slave to the domain controller which listen for configuration and start/stop instruction. The host controller then feeds that information to all server node on a physical machine. The host controller is not really something special to only domain mode, but is also present in a standalone mode, but then not really used.

Lets get started with the configuration for the host controller. Lets open ./host1/domain/configuration/host-slave.xml and define the server nodes that will be managed by this host controller.

<host name="server1" xmlns="urn:jboss:domain:1.3">
    ...
    <servers>
        <server name="server-one" group="cluster-ha" auto-start="false">
            <socket-bindings port-offset="200"/>
        </server>
    </servers>
</host>

Since we are running everything on the same machine, we need to set the port-offset property. If this was running on a dedicated server you leave that out.

We use the server group that was defined in the domain controller.

Next we need to set up security to the domain controller. The host controller needs to know how to establish a connection to the domain controller. Here we use the same base64 password that we recieved when creating the management user for the domain controller.

<host name="server1" xmlns="urn:jboss:domain:1.3">
    ...
            <security-realm name="ManagementRealm">
                <server-identities>
                     <secret value="cGFzc3dvcmQ=" />   
                </server-identities>
                ...
            </security-realm>
    ...
    <domain-controller>
       <remote host="${jboss.domain.master.address}" port="${jboss.domain.master.port:9999}" username="domainadmin" security-realm="ManagementRealm"/>
    </domain-controller>
</host>

The last thing we need to change, and this is because we are running everything on the same machine is the management port.

<host name="server1" xmlns="urn:jboss:domain:1.3">
   ...
            <native-interface security-realm="ManagementRealm">
                <socket interface="management" port="${jboss.management.native.port:19999}"/>
            </native-interface>
   ...
</host>

Now lets multiply the above configuration to host 2 also.

<host name="server2" xmlns="urn:jboss:domain:1.3">
   ...
            <security-realm name="ManagementRealm">
                <server-identities>
                     <secret value="cGFzc3dvcmQ=" />   
                </server-identities>
                ...
            </security-realm>
   ...
   <socket interface="management" port="${jboss.management.native.port:29999}"/>
   ...
    <domain-controller>
       <remote host="${jboss.domain.master.address}" port="${jboss.domain.master.port:9999}" username="domainadmin" security-realm="ManagementRealm"/>
    </domain-controller>
   ...
    <servers>
        <server name="server-two" group="cluster-ha" auto-start="false">
            <socket-bindings port-offset="400"/>
        </server>
    </servers>
</host>

Now we are ready to start the host controllers.

$ ./host1/bin/domain.sh --host-config=host-slave.xml -Djboss.domain.master.address=127.0.0.1
$ ./host2/bin/domain.sh --host-config=host-slave.xml -Djboss.domain.master.address=127.0.0.1

You should now see the following in the domain controller log.

[Host Controller] 02:05:43,589 INFO  [org.jboss.as.domain] (slave-request-threads - 1) JBAS010918: Registered remote slave host "server1", JBoss EAP 6.0.1.GA (AS 7.1.3.Final-redhat-4)
[Host Controller] 02:06:54,395 INFO  [org.jboss.as.domain] (slave-request-threads - 1) JBAS010918: Registered remote slave host "server2", JBoss EAP 6.0.1.GA (AS 7.1.3.Final-redhat-4)

Test Installation

To test is installation, we need a clustered application. I will as in my earlier blog borrow a ready application from https://github.com/akquinet/jbosscc-as7-examples/tree/master/cluster-example.

But now we will use the new JBoss CLI tool to deploy and start and stop our server nodes. See my previous blog on how to deploy with CLI http://magnus-k-karlsson.blogspot.se/2013/01/how-to-deploy-and-undeploy-in-jboss-eap.html.

$ ./domain/bin/jboss-cli.sh 
You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
[disconnected /] connect

[domain@localhost:9999 /] deploy /home/magkar/Downloads/cluster-example-1.0-SNAPSHOT.war --server-groups=cluster-ha

If you now look in each host controller log file, you should see the deployment. If everything is ok. Lets test the application, open http://127.0.0.1/cluster/index.jsf.

Now lets stop the server node, that you were served and test the replication.

[domain@localhost:9999 /] /host=server1/server-config=server-one:stop
{
    "outcome" => "success",
    "result" => "STOPPING"
}

And you should now see in that node server log.

[Server:server-one] 02:15:38,454 INFO  [org.jboss.as] (MSC service thread 1-3) JBAS015950: JBoss EAP 6.0.1.GA (AS 7.1.3.Final-redhat-4) stopped in 1000ms
02:15:38,472 INFO  [org.jboss.as.process.Server:server-one.status] (reaper for Server:server-one) JBAS012010: Process 'Server:server-one' finished with an exit status of 0

Lets now hit the application again.

No comments: