How to discover JBoss Cluster members

In this tutorial we will learn some techniques to discover your JBoss / WildFly cluster members using a set of available tools. We will use both tools included in WildFly distribution and standard tools like JMX.

Discover cluster nodes using the CLI

The simplest way to list the cluster nodes is to use the Command Line Interace (CLI) and query the view attribute. Here is the CLI command to retrieve the view attribute from the “ee” channel:

 /subsystem=jgroups/channel=ee:read-attribute(name=view,include-defaults=true)
{
    "outcome" => "success",
    "result" => "[fedora|0] (1) [fedora]"
}

In the above example, only one cluster node (fedora) was active.

Please note that, for the above command to work, you need to make sure the channel was activated by a clustered application. You can check that from the server logs:

17:58:58,152 INFO  [org.infinispan.CLUSTER] (ServerService Thread Pool -- 79) ISPN000094: Received new cluster view for channel ejb: [fedora|0] (1) [fedora]

Check cluster nodes from JConsole

You can also check the view attribute from JMX. For example, connect to WildFly using JConsole. Then, head to the org.wildfly.clustering.infinispan MBeans and search for the cluster channel:

discover cluster members jboss

The above information is also available in the jgroups MBeans.

Finally, to fetch the cluster members programmatically using JMX, you can use the following code snippet:

Object obj = ManagementFactory.getPlatformMBeanServer().getAttribute(ObjectName.getInstance("jgroups:type=channel,cluster=\"web\""), "View");

System.out.println(obj);

Using Mod Cluster Manager UI

If you have installed Mod Cluster on top of Apache Server, then you can use the Mod Cluster Manager Web interface as source of information about your cluster.

You should have the following configuration in Apache:

<Location /mod_cluster-manager>
    SetHandler mod_cluster-manager

    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
 </Location>

Then you can have a quick look at cluster members by requesting the mod_cluster-manager Web context:

mod cluster jboss as 7 discover cluster members

On the other hand, if you are using WildFly or JBoss EAP 7 as Load Balancer then you don’t have an equivalent management interface.

You will however find in your server logs any change in the Cluster topology:

INFO  [org.infinispan.CLUSTER] (thread-6,ejb,master:server-one) ISPN000094: Received new cluster view for channel ejb: [master:server-one|1] (2) [master:server-one, master:server-two]

Using org.wildfly.clustering.group.Group API

If you are running a WIldFly cluster, then you can use also a programmatic approach to monitor your cluster. To do that, you will access the org.wildfly.clustering.group.Group API. This is discussed more in detail in the following article: Monitoring a cluster using WildFly API

Using JGroups API

Another needful source of information is the underlying JGroups transport protocol. Since all members which join the cluster need to use a Channel object, then a simple and elegant solution to provide cluster members is reading the Channel’s view which contains a getMembers method. Here’s a sample code snippet:

Channel channel = (Channel) CurrentServiceContainer.getServiceContainer().getService(ServiceName.JBOSS.append("jgroups", "channel", "web")).getValue();

List<org.jgroups.Address> members = channel.getView().getMembers();
List< IpAddress> addresses = new ArrayList< IpAddress>();


for (org.jgroups.Address member: members) {
            PhysicalAddress physicalAddr = (PhysicalAddress)channel.down(new Event(Event.GET_PHYSICAL_ADDRESS, member));
            IpAddress ipAddr = ( IpAddress)physicalAddr;
            System.out.println("Found IP: "+ipAddr.getIpAddress().getHostAddress());
            addresses.add(ipAddr);
}

Using Infinispan API

Infinispan is the default Cache Manager for WildFly. There’s a simple shortcut into the EmbeddedCacheManager object which allows reading the cluster members:

@Resource(lookup="java:jboss/infinispan/container/cluster")
private CacheContainer container;

. . . . . . 
List<org.infinispan.remoting.transport.Address> members = container.getCache().getCacheManager().getMembers();


for (org.infinispan.remoting.transport.Address member: members) {
     System.out.println("Found Member:" +member.toString());
}

Be Careful! Both Infinispan API and JGroups API use the Address class. We have fully specified the Class name in order to avoid conflicts between the imports!


Using Probe shell script (JBoss 5)

Another discovery tool which shipped with JBoss AS 4-5-6 is the probe.sh shell which invokes a test class contained in JGroups API named org.jgroups.tests.Probe.

This class sends a multicasts a packet to 224.0.75.75:7500 (default multicast address and port) and waits for responses until the timeout has elapsed. Here’s how you can adapt it to JBoss AS 7 (warning not tested!)

set CLASSPATH=%JBOSS_HOME%\modules\org\jgroups\main\jgroups-3.0.6.Final.jar

set CP=%CLASSPATH%

java -cp %CP% org.jgroups.tests.Probe %*

Here’s the expected output:

-- send probe on /224.0.75.75:7500

#1 (263 bytes): 192.168.0.1:2222 (ClusterGroup)
local_addr=192.168.0.1:2222
group_name=ClusterGroup
Version=2.2.9 beta, cvs="$Id: Version.java,v 1.23 2006/04/04 17:21:24 
p $"
view: [192.168.0.1:2222|1] [192.168.0.2:2222:2226|1]
group_addr=226.6.6.6:12345
. . . . . . .

Using an Helper Servlet

Finally, if you want a Quick Servlet for dumping the various programming options displayed in this tutorial:

package com.sample;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.infinispan.manager.CacheContainer;
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
import org.jboss.as.server.CurrentServiceContainer;
import org.jboss.msc.service.ServiceName;

import org.jgroups.Channel;
import org.jgroups.Event;
import org.jgroups.PhysicalAddress;
import org.jgroups.stack.IpAddress;

import java.util.Hashtable;
import javax.management.*;
import javax.management.remote.*;


/**
 * Servlet implementation class TestCluster
 */
@WebServlet("/TestCluster")
public class TestCluster extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Resource(lookup="java:jboss/infinispan/container/cluster")
    private CacheContainer container;


    public TestCluster() {
        super();
        // TODO Auto-generated constructor stub
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //getClusterMembersInfinispan();
        try {
            getClusterMembersJGroups(response);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public Collection<IpAddress> getClusterMembersJGroups(HttpServletResponse response) {
        PrintWriter out = response.getWriter();
        Channel channel = (Channel) CurrentServiceContainer.getServiceContainer().getService(ServiceName.JBOSS.append("jgroups", "channel", "web")).getValue();

        List<org.jgroups.Address> members = channel.getView().getMembers();
        List< IpAddress> addresses = new ArrayList< IpAddress>();
        for (org.jgroups.Address member: members) {
            PhysicalAddress physicalAddr = (PhysicalAddress)channel.down(new Event(Event.GET_PHYSICAL_ADDRESS, member));
            IpAddress ipAddr = ( IpAddress)physicalAddr;
            out.println("Found IP: "+ipAddr.getIpAddress().getHostAddress());
            addresses.add(ipAddr);
        }
        out.close();
        return addresses;
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }
    public Collection<org.infinispan.remoting.transport.Address> getClusterMembersInfinispan(HttpServletResponse response) {
        PrintWriter out = response.getWriter();
        List<org.infinispan.remoting.transport.Address> members = container.getCache().getCacheManager().getMembers();
        for (org.infinispan.remoting.transport.Address member: members) {
            out.println("Found Member:" +member.toString());
        }
        out.close();
        return members;
    }

    public void getClusterMembersJMX(HttpServletResponse response) throws Exception {
        PrintWriter out = response.getWriter();
        Object obj = ManagementFactory.getPlatformMBeanServer().getAttribute(ObjectName.getInstance("jgroups:type=channel,cluster=\"web\""), "View");
        out.println(obj);
        out.close();
    }
}

Just keep in mind that when deploying your Servlet, you need to trigger some dependencies like the JBoss AS core modules, the Infinispan API and JGroups API.

Dependencies: org.jboss.as.server,org.jgroups,org.infinispan export
Found the article helpful? if so please follow us on Socials