JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF

The open source
grid computing
solution

 Home   About   Features   Download   Documentation   On Github   Forums 

Grid topology monitoring

From JPPF 6.2 Documentation

Jump to: navigation, search

Contents

Main Page > Development guide > Grid topology monitoring


As of JPPF v5.0, the package org.jppf.client.monitoring.topology provides an API to explore and monitor the topology of a JPPF grid, such as discovered from a JPPF client's perspective. This API is used by the administration and monitoring console, and allows to explore the topology as well as subscribe to notifications of the changes that occur, such as new server being brought online, nodes started or terminated, etc.

1 Building and exploring the topology

The entry point for this API is the TopologyManager class. A TopologyManager uses a JPPFClient to discover its connections to one or more drivers, and queries these drivers via the management API to obtain information about their attached JPPF nodes and other peer drivers they are connected to. All this information is used to build a model of the JPPF grid topology as a tree. For example, with a grid that has two drivers connected to each other, we would have a representation like this:

TopologyTree.gif

The dotted lines emphasize the fact that a peer is actually a "virtual" component which references a real driver. Peer objects are here to allow representing the topology as a tree rather than as a graph, which makes their usage a lot easier.

You may notice that this is very similar to the "toplogy tree" view of the administration console:

TopologyTreeView.png

This is not a coincidence: the adminstration console indeed uses its own instance of TopologyManager and the tree view is a direct mapping of the topology to a tree-like swing component.

The model representing the components of the JPPF toplogy is a class hierarchy whose base super class is the abtract class AbstractTopologyComponent, which provides an API to navigate within the tree strutcture, along with ways to identify each component and methods to retrieve information that are common to drivers and nodes.

The object model is as follows:

TopologyObjectModel.gif

AbstractComponent provides the API to navigate a tree of elements uniquely identified with a uuid:

public abstract class AbstractComponent<E extends AbstractComponent> {
  // Get the parent of this compponent
  public synchronized E getParent() {
  // Get the number of children of this component
  public synchronized int getChildCount()
  // Get the children of this component
  public synchronized List<E> getChildren()
  // Get the child with the specified uuid
  public synchronized E getChild(final String uuid)
  // Get the uuid of this ocmponent
  public synchronized String getUuid()
  // Get a user-friendly representation of this topology component
  public String getDisplayName()
}

AbstractTopologyComponent is defined as follows:

public abstract class AbstractTopologyComponent
  extends AbstractComponent<AbstractTopologyComponent> {
   // Whether this object represents a driver
  public boolean isDriver()
  // Whether this object represents a node
  public boolean isNode()
  // Whether this object represents a peer driver
  public boolean isPeer()

  // Get the object describing the health of a node or driver
  public HealthSnapshot getHealthSnapshot()
  // Get the management information for this component
  public JPPFManagementInfo getManagementInfo()
  // Get a user-friendly representation of this component
  public String getDisplayName()
}

TopologyDriver provides the following additional methods:

public class TopologyDriver extends AbstractTopologyComponent {
  // Get the JMX connection wrapper
  public JMXDriverConnectionWrapper getJmx()
  // Get the driver connection
  public JPPFClientConnection getConnection()
  // Get a proxy to the MBean that forwards node management requests
  public JPPFNodeForwardingMBean getForwarder()
  // Get a proxy to the jobs monitoring MBean
  public DriverJobManagementMBean getJobManager()
  // Get a proxy the diagnostics MBean for this driver
  public DiagnosticsMBean getDiagnostics()
}

TopologyNode provides two specialized methods to query the node's state:

public class TopologyNode extends AbstractTopologyComponent {
  // Get the object describing the current state of a node
  public JPPFNodeState getNodeState()
  // Get the number of slaves for a master node (node provisioning)
  public int getNbSlaveNodes()
}

Whereas TopologyPeer does not provide any additional method, since its uuid is all that is needed:

public class TopologyPeer extends TopologyNode {
}

The root of the tree is our TopologyManager, defined as follows:

public class TopologyManager implements ClientListener {
  // Create a topology manager with a new JPPFClient
  public TopologyManager()
  // Create a toplogy manager with the specified JPPFClient
  public TopologyManager(JPPFClient client)
  // Get the JPPF client
  public JPPFClient getJPPFClient()
  // Get all drivers
  public List<TopologyDriver> getDrivers()
  // Get all nodes
  public List<TopologyNode> getNodes()
  // Get all peers
  public List<TopologyPeer> getPeers()
  // Get a driver from its uuid
  public TopologyDriver getDriver(String uuid)
  // Get a node from its uuid
  public TopologyNode getNode(String uuid)
  // Get a peer from its uuid
  public TopologyPeer getPeer(String uuid)
  // Get a node or peer from its uuid
  public TopologyNode getNodeOrPeer(String uuid)
  // Get the number of drivers
  public int getDriverCount()
  // Get the number of nodes
  public int getNodeCount()
  // Get the number of peers
  public int getPeerCount()
  // Get and set the node filter
  public NodeSelector getNodeFilter()
  public void setNodeFilter(NodeSelector selector)
  // Get the nodes that are slaves of the specified master node, if any
  public List<TopologyNode> getSlaveNodes(String masterNodeUuid)
}

According to this, the following code example can be used to visit the entire tree:

// this creates a new JPPFClient accessible with manager.getJPPFClient()
TopologyManager manager = new TopologyManager();
// iterate over the discovered drivers
for (TopologyDriver driver: manager.getDrivers()) {
  // ... do something with the driver ...
  // iterate of the nodes and peers for this driver
  for (AbstractTopologyComponent comp: driver.getChildren()) {
    if (comp.isNode()) {
      TopologyNode node = (TopologyNode) comp;
      // ... do something with the node ...
    } else { // if (comp.isPeer())
      TopologyPeer peer = (TopologyPeer) comp;
      // retrieve the actual driver the peer refers to
      TopologyDriver actualDriver = manager.getDriver(peer.getUuid());
      // ... do something with the peer ...
    }
  }
}

A TopologyManager instance also automatically refreshes the states of the nodes, along with the JVM health snapshots of the drivers and nodes. The interval between refreshes is determined via the value of the following configuration properties:

# refresh interval in millis for the grid topology.
# this is the interval between 2 successive runs of the task that refreshes the
# topology via JMX requests; defaults to 1000
jppf.admin.refresh.interval.topology = 1000

# refresh interval for the JVM health snapshots; defaults to 1000
# this is the interval between 2 successive runs of the task that refreshes
# the JVM health snapshots via JMX requests
jppf.admin.refresh.interval.health = 1000

These values can be set both in a configuration file and programmatically, for instance:

TypedProperties config = JPPFConfiguration.getProperties();
// refresh the nodes states every 3 seconds
config.setLong("jppf.admin.refresh.interval.topology", 3000L);
// refresh the JMV health snapshots every 5 seconds
config.setLong("jppf.admin.refresh.interval.health", 5000L);
TopologyManager manager = new TopologyManager();

2 Receiving notifications of changes in the topology

It is possible to subscribe to topology change events emitted by a TopologyManager, using an implementation of the TopologyListener interface as parameter of the related constructors and methods in TopologyManager:

public class TopologyManager implements ClientListener {
  // Create a topology manager with a new JPPFClient
  // and add the specified listeners immediately
  public TopologyManager(TopologyListener...listeners)
  // Create a topology manager with the specified JPPFClient
  // and add the specified listeners immediately
  public TopologyManager(JPPFClient client, TopologyListener...listeners)

  // Add a topology change listener
  public void addTopologyListener(TopologyListener listener)
  // Remove a topology change listener
  public void removeTopologyListener(TopologyListener listener)
}

TopologyListener is defined as follows:

public interface TopologyListener extends EventListener {
  // Called when a driver is discovered
  void driverAdded(TopologyEvent event);
  // Called when a driver is terminated
  void driverRemoved(TopologyEvent event);
  // Called when the state of a driver has changed
  void driverUpdated(TopologyEvent event);

  // Called when a node is added to a driver
  void nodeAdded(TopologyEvent event);
  // Called when a node is removed from a driver
  void nodeRemoved(TopologyEvent event);
  // Called when the state of a node has changed
  void nodeUpdated(TopologyEvent event);
}

As we can see, each notification is encapsulated in a TopologyEvent object:

public class TopologyEvent extends EventObject {
  // Get the driver data
  public TopologyDriver getDriver()
  // Get the related node or peer
  public TopologyNode getNodeOrPeer()
  // Get the topology manager which emitted this event
  public TopologyManager getTopologyManager()
}

Please note that, for the driverAdded(...), driverRemoved(...) and driverUpdated(...) notifications, the corresponding event's getNodeOrPeer() method will always return null.

Additionally, if you do not wish to override all the methods of the TopologyListener interface, you can instead extend the class TopologyListenerAdapter, which provides an empty implementation of each method.

Here is a listener implementation that prints topology changes to the console:

public class MyListener extends TopologyListenerAdapter {
  @Override
  public void driverAdded(TopologyEvent e) {
    System.out.printf("added driver %s%n", e.getDriver().getDisplayName());
  }

  @Override
  public void driverRemoved(TopologyEvent e) {
    System.out.printf("removed driver %s%n", e.getDriver().getDisplayName());
  }

  @Override
  public void nodeAdded(TopologyEvent e) {
    TopologyNode node = e.getNodeOrPeer();
    System.out.printf("added %s %s to driver %s%n", (node.isNode() ? "node" :  "peer"),
      node.getDisplayName(), e.getDriver().getDisplayName());
  }

  @Override
  public void nodeRemoved(TopologyEvent e) {
    TopologyNode node = e.getNodeOrPeer();
    System.out.printf("removed %s %s from driver %s%n", (node.isNode() ?"node" :"peer"), 
      node.getDisplayName(), e.getDriver().getDisplayName());
  }
}

To subscribe this listener to topology changes:

TopologyManager manager = new TopologyManager();
MyListener myListener = new MyListener();
manager.addTopologyListener(myListener);

or, in a single statement:

TopologyManager manager = new TopologyManager(new MyListener());

3 Node filtering

TopologyManager provides an API to filter the nodes in the grid topology, based on node selectors:

public class TopologyManager implements ClientListener {
  // Get the node filter
  public NodeSelector getNodeFilter()
  // Set the node filter
  public void setNodeFilter(NodeSelector selector)
}

To activate the node filtering, you only need to call setNodeFilter() with a non-null NodeSelector. Inversely, calling setNodeFilter() with a null selector will deactivate the node filtering. Here is an example which filters out all slave nodes in the topology:

TopologyManager manager = ...;
// a policy that filters out slave nodes
ExecutionPolicy noSlavePolicy = new Equal("jppf.node.provisioning.slave", false);
NodeSelector selector = new ExecutionPolicySelector(noSlavePolicy);
// activate node filtering with our policy
manager.setNodeFilter(selector);

When node filtering is active:

  • only the nodes that match the selector will be available via the TopologyManager API
  • events will be emitted only for the nodes that match the selector


The administration console also provides a UI to enter an execution policy in XML format to use as a filter:

NodeFiltering-Active.gif

Main Page > Development guide > Grid topology monitoring



JPPF Copyright © 2005-2020 JPPF.org Powered by MediaWiki