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   Forums 

Server management

From JPPF 6.0 Documentation

Jump to: navigation, search

Contents

Main Page > Management and monitoring > Server management


Out of the box in JPPF, each server provides 2 MBeans that can be accessed remotely using a JMXMP remote connector with the JMX URL “service:jmx:rmi://host:port”, where host is the host name or IP address of the machine where the server is running (value of “jppf.management.host” in the server configuration file), and port is the value of the property “jppf.management.port” specified in the server's configuration file.

1 Server-level management and monitoring

MBean name: “org.jppf:name=admin,type=driver

This is also the value of the constant JPPFDriverAdminMBean.MBEAN_NAME.

This MBean's role is to perform management and monitoring at the server level. It exposes the JPPFDriverAdminMBean interface, which provides the functionalities described hereafter.

1.1 Server statistics

You can get a snapshot of the server's state by invoking the following method, which provides statistics on execution performance, network overhead, server queue behavior, number of connected nodes and clients:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Get the latest statistics snapshot from the JPPF driver
  public JPPFStats statistics() throws Exception;
}

This method returns an object of type JPPFStatistics. We invite you to read the dedicated section in The JPPF statistics API for the full details of its usage.

Additionally, you can reset the server statistics using the following method:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Reset the JPPF driver statistics
  public void resetStatistics() throws Exception;
}

1.2 Stopping and restarting the server

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Perform a shutdown or restart of the server. The server stops after
  // the specified shutdown delay, and restarts after the specified restart delay
  public String restartShutdown(Long shutdownDelay, Long restartDelay)
    throws Exception;
}

This method allows you to remotely shut down the server, and eventually to restart it after a specified delay. This can be useful when an upgrade or maintenance of the server must take place within a limited time window. The server will only restart after the restart delay if it is at least equal to zero, otherwise it simply shuts down and cannot be restarted remotely anymore.

1.3 Managing the nodes attached to the server

The driver MBean allows monitoring and managing the nodes attached to the driver with the following methods:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Request the JMX connection information for all nodes attached to the server
  public Collection<JPPFManagementInfo> nodesInformation() throws Exception;
  // Request the JMX connection information for all nodes which satisfy the node selector
  public Collection<JPPFManagementInfo> nodesInformation(NodeSelector selector)
    throws Exception;

  // Get the number of nodes currently attached to the server
  public Integer nbNodes() throws Exception;
  // Get the number of nodes attached to the driver that satisfy the specified selector
  public Integer nbNodes(NodeSelector selector) throws Exception;
}

Note that the methods using a node selector as input parameter provide a lot of flexibility in chosing which nodes to get information about.

The JPPFManagementInfo objects returned in the resulting collection encapsulate enough information to connect to the corresponding node's MBean server:

public class JPPFManagementInfo
  implements Serializable, Comparable<JPPFManagementInfo> {
  // the host on which the node is running
  public String getHost()
  // the port on which the node's JMX server is listening
  public int getPort()
  // Get the driver or node's unique id
  public String getUuid()
  // Determine whether this is a driver connected as a node to another driver
  public boolean isPeer()
  // Determine whether this information represents a real node
  public boolean isNode()
  // Determine whether this is a driver
  public boolean isDriver()
  // Determine whether communication is be secured via SSL/TLS
  public boolean isSecure()
  // Determine whether this information represents a local node on client or driver
  public boolean isLocal()
  // Determine whether this information represents a master node for provisioning
  public boolean isMasterNode() {
  // Determine whether this information represents a slave node for provisioning
  public boolean isSlaveNode() {
  // Determine whether this information represents a node than can execute .Net tasks
  public boolean isDotnetCapable()
}

For example, based on what we saw in the section about nodes management, we could write code that gathers connection information for each node attached to a server, and then performs some management request on them:

// Obtain connection information for all attached nodes
Collection<JPPFManagementInfo> nodesInfo = myDriverMBeanProxy.nodesInformation();
// for each node
for (JPPFManagementInfo info: nodesInfo) {
  // create a JMX connection wrapper based on the node information
  JMXNodeConnectionWrapper wrapper =
    new JMXNodeConnectionWrapper(info.getHost(), info.getPort());
  // connect to the node's MBean server
  wrapper.connectAndWait(5000);
  // restart the node
  wrapper.restart();
}

Additionally, if all you need is the number of nodes attached to the server, then simply calling the nbNodes() method will be much more efficient in terms of CPU usage and network traffic.

1.4 Monitoring idle nodes

The JPPF driver MBean provides the following methods to gather information on idle nodes:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Request information on the idle nodes attached to the server
  public Collection<JPPFManagementInfo> idleNodesInformation() throws Exception;
  // Request information on all idle nodes which satisfy the node selector
  public Collection<JPPFManagementInfo> idleNodesInformation(NodeSelector selector)
    throws Exception;

  // Get the number of currently idle nodes attached to the server
  public Integer nbIdleNodes() throws Exception;
  // Get the number of idle nodes that satisfy the specified selector
  public Integer nbIdleNodes(NodeSelector selector) throws Exception;
}

idlesNodesInformation() is similar to nodesInformation() except that it provides information only for the nodes that are currently idle. If all you need is the number of idle nodes, then it is much less costly to call nbIdleNodes() instead.

1.5 Nodes active state

From the server's perspective, the nodes can be considered either active or inactive. When a node is “active” the server will take it into account when scheduling the execution of the jobs. Inversely, when it is “inactive”, no job can be scheduled to execute on this node. In this case, the node behaves as if it were not part of the JPPF grid for job scheduling purposes, while still being alive and manageable.

This provides a way to disable nodes without the cost of terminating the corresponding remote process. For example, this provides a lot of flexibility in how the workload can be balanced among the nodes: sometimes you may need to have more nodes with less processing threads each, while at other times you could dynamically setup less nodes with more processing threads.

This can be done with the following methods:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Toggle the activate state of the specified nodes
  public void toggleActiveState(NodeSelector selector) throws Exception;
  // Get the active states of the nodes specified vith a NodeSelector
  Map<String, Boolean> getActiveState(NodeSelector selector) throws Exception;
  // Set the active state of the specified nodes
  void setActiveState(NodeSelector selector, boolean active) throws Exception;
}

The toggleActiveState() method acts as an on/off switch: nodes in the 'active' state will be deactivated, whereas nodes in the 'inactive' state will be activated. Also note that this method uses a node selector to specifiy which nodes it applies to.

1.6 Load-balancing settings

The driver management MBean provides two methods to dynamically obtain and change the server's load balancing settings:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Obtain the current load-balancing settings
  public LoadBalancingInformation loadBalancerInformation() throws Exception;
}

This method returns an object of type LoadBalancingInformation, defined as follows:

public class LoadBalancingInformation implements Serializable {
  // the name of the algorithm currently used by the server
  public String algorithm = null;
  // the algorithm's parameters
  public TypedProperties parameters = null;
  // the names of all algorithms available to the server
  public List<String> algorithmNames = null;
}

Notes:

  • the value of algorithm is included in the list of algorithm names
  • parameters contains a mapping of the algorithm parameters names to their current value. Unlike what we have seen in the configuration guide chapter, the parameter names are expressed without suffix. This means that instead of strategy.<profile_name>.<parameter_name>, they will just be named as <parameter_name>.

It is also possible to dynamically change the load-balancing algorithm used by the server, and / or its parameters:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Change the load-balancing settings
  public String changeLoadBalancerSettings(String algorithm, Map parameters)
    throws Exception;
}

Where:

  • algorithm is the name of the algorithm to use. If it is not known to the server, no change occurs.
  • parameters is a map of algorithm parameter names to their value. Similarly to what we saw above, the parameter names must be expressed without suffix. Internally, the JPPF server will use a the profile name “jppf”.

1.7 Driver UDP broadcasting state

The driver management MBean has a read-write attribute which allows monitoring and setting its ability to boradcast its connection information to clients, nodes or other servers, via UDP. This atribute isdefined via the following accessors:

public interface JPPFDriverAdminMBean extends JPPFAdminMBean {
  // Determine whether the driver is broadcasting
  Boolean isBroadcasting() throws Exception;

  // Activate or deactivate the broadcasting of the driver's connection information
  void setBroadcasting(Boolean broadcasting) throws Exception;
}

2 Job-level management and monitoring

MBean name: “org.jppf:name=jobManagement,type=driver

This is also the value of the constant DriverJobManagementMBean.MBEAN_NAME.

The role of this MBean is to control and monitor the life cycle of all jobs submitted to the server. It exposes the DriverJobManagementMBean interface, defined as follows:

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Cancel the job with the specified id
  public void cancelJob(String jobUuid) throws Exception;
  // Cancel the selected jobs
  public void cancelJobs(JobSelector selector) throws Exception;
  // Suspend the job with the specified id
  public void suspendJob(String jobUuid, Boolean requeue) throws Exception;
  // Suspend the selected jobs
  public void suspendJobs(JobSelector selector, Boolean requeue) throws Exception;
  // Resume the job with the specified id
  public void resumeJob(String jobUuid) throws Exception;
  // Resume the selected jobs
  public void resumeJobs(JobSelector selector) throws Exception;
  // Update the maximum number of nodes a job can run on
  public void updateMaxNodes(String jobUuid, Integer maxNodes) throws Exception;
  // Update the maximum number of nodes for the selected jobs
  public void updateMaxNodes(JobSelector selector, Integer maxNodes) throws Exception;
  // Update the priority of a job
  void updatePriority(String jobUuid, Integer newPriority);
  // Update the priority the selected jobs
  void updatePriority(JobSelector selector, Integer newPriority);
  // Get the set of uuids of all the jobs currently queued or executing
  public String[] getAllJobUuids() throws Exception;
  // Get an object describing the job with the specified uuid
  public JobInformation getJobInformation(String jobUuid) throws Exception;
  // Get information on the selected jobs
  public JobInformation[] getJobInformation(JobSelector selector) throws Exception;
  // Get a list of objects describing the nodes to which the whole
  // or part of a job was dispatched
  public NodeJobInformation[] getNodeInformation(String jobUuid) throws Exception;
  // Get the list of dispatches for each of the selected nodes
  public Map<String, NodeJobInformation[]> getNodeInformation(JobSelector selector)
    throws Exception;
}

Reminder:

A job can be made of multiple tasks. These tasks may not be all executed on the same node. Instead, the set of tasks may be split in several subsets, and these subsets can in turn be disptached to different nodes to allow their execution in parallel. In the remainder of this section we will call each subset a “sub-job”, to distinguish them from actual jobs at the server level. Thus a job is associated with a server, whereas a sub-job is associated with a node.

2.1 Job selectors

Many of the methods in DriverJobManagementMBean use a JobSelector, which allows filtering the jobs in the driver's queue according to user-defined criteria. This interface is defined as folows:

public interface JobSelector extends Serializable {
  // Whether the specified job is accepted by this selector
  boolean accepts(JPPFDistributedJob job);
}

As we can see, it acts as a yes/no filter for instances of JPPFDistributedJob, which represent remote jobs present in a JPPF driver. Job selectors are similar in functionality to the node selectors seen later in this documentation.

The JPPF API provides three predefined implementations of JobSelector:

2.1.1 AllJobsSelector

An instance of AllJobsSelector will select all the jobs present in the driver at the time a management request is made. To use it, you can either construct a new instance or use the predefined constant JobSelector.ALL_JOBS.

Example usage:

DriverJobManagementMBean jobManager = ...;
// get information on all the jobs
JobInformation[] jobInfos = jobManager.jobInformation(new AllJobsSelector());
// alternatively, use the ALL_JOBS constant
jobInfos = jobManager.jobInformation(JobSelector.ALL_JOBS);

2.1.2 JobUuidSelector

An instance of JobUuidSelector filters jobs based on a set of job uuids provided in one of its constructors. It is defined as:

public class JobUuidSelector implements JobSelector {
  // Initiialize this selector with the specified collection of accepted job uuids
  public JobUuidSelector(final Collection<String> uuids)

  // Initiialize this selector with the specified array of accepted job uuids
  public JobUuidSelector(final String...uuids)

  // Get the set of job uuids accepted by this selector
  public Set<String> getUuids()

  @Override
  public boolean accepts(final JPPFDistributedJob job)
}

It can be used as in this example:

DriverJobManagementMBean jobManager = ...;
// create a selector with known uuids
JobSelector selector = new JobUuidSelector("job_uuid_1", "job_uuid_2");
// alternatively, build a collection of uuids from a set of jobs
List<JPPFJob> jobs = ...;
List<String> uuidList = new ArrayList<>();
for (JPPFjob job: jobs) uuidList.add(job.getUuid());
selector = new JobUuidSelector(uuidList);
// get information on the selected jobs
JobInformation[] jobInfos = jobManager.jobInformation(selector);

2.1.3 Scripted job selector

A ScriptedJobSelector uses a script expression that evaluates to a boolean to determine which jobs are accepted. The script language must be accepted by the JVM and must conform to the JSR-223 / javax.script API specifications.

A scripted job selector is particularly useful when you need to implement a complex filtering logic but do not want to deploy the associated code in the driver's classpath.

ScriptedJobSelector extends BaseScriptEvaluator and is defined as follows:

public class ScriptedJobSelector extends BaseScriptEvaluator implements JobSelector {
  // Initialize this selector with the specfied language and script
  public ScriptedJobSelector(String language, String script)

  // Initialize this selector with the specfied language and script reader
  public ScriptedJobSelector(String language, Reader scriptReader) throws IOException

  // Initialize this selector with the specfied language and script file
  public ScriptedJobSelector(String language, File scriptFile) throws IOException

  // Get the language of the script to evaluate
  public String getLanguage()

  // Get the script to evaluate
  public String getScript()

  @Override
  public boolean accepts(final JPPFDistributedJob job)
}

The script will be evaluated for each JPPFDistributedJob passed as input to the accepts() method of the selector. The job can be accessed from the script using a predefined variable name "jppfJob", as in this example:

DriverJobManagementMBean jobManager = ...;
// create a selector with a Javascript script
JobSelector selector =
  new ScriptedJobSelector("javascript", "jppfJob.getName().startsWith('MyJob-')");
// or an equivalent Groovy script
selector =
  new ScriptedJobSelector("groovy", "return jppfJob.getName().startsWith('MyJob-')");
// get information on the selected jobs
JobInformation[] jobInfos = jobManager.jobInformation(selector);

2.1.4 Custom job selector

When a job selector requires a complex logic and its performance is critical, you can always write your own implementation of JobSelector, as in this example:

public class CustomJobSelector implements JobSelector {
  @Override
  public boolean accepts(JPPFDistributedJob job) {
    // retrieve a parameter from the job metadata
    int param = job.getMetadata().getParameter("my.param", -1);
    // use the param in the filtering expression
    return !job.getSLA().isSuspended() && (param >= 0);
  }
}

Since the job selector is evaluated by the driver, the code of its implementation, along with all the classes it depends on, must be deployed in the driver's classpath. This is usually done by dropping the class folder or jar file that contains the code in the driver's /lib folder.

2.2 Controlling a job's life cycle

It is possible to terminate, suspend and resume a job using the following methods:

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Cancel the job with the specified uuid
  public void cancelJob(String jobUuid) throws Exception;

  // Cancel the selected jobs
  public void cancelJobs(JobSelector selector) throws Exception;
}

This will terminate the specified jobs. Any sub-job running in a node will be terminated as well. If a sub-job was partially executed (i.e. at least one task execution was completed), the results are discarded. If the job was still waiting in the server queue, it is simply removed from the queue, and the enclosed tasks are returned in their original state to the client.

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Suspend the job with the specified uuid
  public void suspendJob(String jobUuid, Boolean requeue) throws Exception;

  // Suspend the selected jobs
  public void suspendJobs(JobSelector selector, Boolean requeue) throws Exception;
}

These methods will suspend the specified jobs. The requeue parameter specifies how the currently running sub-jobs will be processed:

  • if true, then the sub-job is canceled and inserted back into the server queue, for execution at a later time
  • if false, JPPF will let the sub-job finish executing in the node, then suspend the rest of the job still in the server queue

If the job is already suspended, then calling this method has no effect.

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Resume the job with the specified uuid
  public void resumeJob(String jobUuid) throws Exception;

  // Resume the selected jobs
  public void resumeJobs(JobSelector selector) throws Exception;
}

These methods resume the execution of the specified jobs. If a job was not suspended, then the method has no effect.

2.3 Number of nodes assigned to a job

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Update the maximum number of nodes a job can run on.
  public void updateMaxNodes(String jobUuid, Integer maxNodes) throws Exception;

  // Update the maximum number of nodes for the selected jobs
  public void updateMaxNodes(JobSelector selector, Integer maxNodes) throws Exception;
}


These methods specify the maximum number of nodes the selected jobs can run on in parallel. It does not guarantee that this number of nodes will be used: the nodes may already be assigned to other jobs, or the job may not be splitted into that many sub-jobs (depending on the load-balancing algorithm). However, it does guarantee that no more than maxNodes nodes will be used to execute the jobs.

2.4 Updating the priority of a job

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Update the priority of a job
  void updatePriority(String jobUuid, Integer newPriority);

  // Update the priority the selected jobs
  void updatePriority(JobSelector selector, Integer newPriority);
}

These methods dynamically update the priority of the specified jobs. The update takes effect immediately.

2.5 Updating the job SLA and metadata

The SLA and metadata of one or more jobs can be updated dynamically, together, atomically and as a whole. This is done with the following method:

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Update the SLA and/or metadata of the specified jobs
  void updateJobs(JobSelector selector, JobSLA sla, JobMetadata metadata);
}

Note that, if any or both of the sla and metadata parameters are null, they will be ignored. To perform the update on a single job, use a JobUuidSelector as follows:

JPPFJob job = ...;
JobSelector selector = new JobUuidSelector(job.getUuid());

Below is an example using this feature:

// get a proxy to the job management MBean
JMXDriverConnectionWrapper jmx = ...;
DriverJobManagementMBean jobManager = jmx.getJobManager();

// create a non-blocking job
JPPFJob job = new JPPFJob();
job.setBlocking(false);
for (int i=0; i<3; i++) job.add(new MyTask());
JobSLA sla = job.getSLA();
// disable execution on master nodes
sla.setExecutionPolicy(new Equal("jppf.node.provisioning.master", false));

// submit the job and do something else
client.submitJob(job);
...

// remove the execution policy to allow execution on all nodes
sla.setExecutionPolicy(null);
// now update the SLA for our job
jobManager.updateJobs(new JobUuidSelector(job.getUuid()), sla, null);
...

2.6 Job introspection

The management features allow users to query and inspect the jobs currently queued or executing in the server. This can be done using the related methods of the jobs management MBean:

public interface DriverJobManagementMBean extends NotificationEmitter {
  // Get the set of uuids for all the jobs currently queued or executing
  public String[] getAllJobUuids() throws Exception;

  // Get an object describing the job with the specified uuid
  public JobInformation getJobInformation(String jobUuid) throws Exception;
  // Get information on the selected jobs
  public JobInformation[] getJobInformation(JobSelector selector) throws Exception;

  // Get a list of objects describing the nodes to which the whole
  // or part of a job was dispatched
  public NodeJobInformation[] getNodeInformation(String jobUuid) throws Exception;
  // Get the list of dispatches for each of the selected nodes
  public Map<String, NodeJobInformation[]> getNodeInformation(JobSelector selector)
    throws Exception;
}

The getAllJobUuids() method returns the UUIDs of all the jobs currently handled by the server. These UUIDs can be directly used with the other methods of the job management MBean.

The getJobInformation(...) methods retrieve information about the state of the specified job(s) in the server. These methods return one or more objects of type JobInformation, defined as follows:

public class JobInformation implements Serializable {
  // the job's name
  public String getJobName()
  // the current number of tasks in the job or sub-job
  public int getTaskCount()
  // the priority of this task bundle
  public int getPriority()
  // the initial task count of the job (at submission time)
  public int getInitialTaskCount()
  // determine whether the job is in suspended state
  public boolean isSuspended()
  // set the maximum number of nodes this job can run on
  public int getMaxNodes()
  // the pending state of the job
  // a job is pending if its scheduled execution date/time has not yet been reached
  public boolean isPending()
}

The getNodeInformation(...) methods also allow to obtain information about all the sub-jobs of a job that are disptached to remote nodes. The return value is an array of objects of type NodeJobInformation, or a map of job uuid to such an array if using a selector, defined as follows:

public class NodeJobInformation implements Serializable {
  // Get the JMX connection information for the node
  public JPPFManagementInfo getNodeInfo()

  // Get the information about the sub-job
  public JobInformation getJobInformation()
}

This class is simply a grouping of two objects of type JobInformation and JPPFManagementInfo, which we have already seen previously. The nodeInfo attribute will allow us to connect to the corresponding node's MBean server and obtain additional job monitoring data.

Please also note that the method getNodeInformation(JobSelector) returns a mapping of job uuids to their corresponding node dispatches.

2.7 Job notifications

Whenever a job-related event occurs, the job management MBean will emit a notification of type JobNotification, defined as follows:

public class JobNotification extends Notification {
  // the information about the job or sub-job
  public JobInformation getJobInformation()

  // the information about the node (for sub-jobs only)
  // null for a job on the server side
  public JPPFManagementInfo getNodeInfo()

  // the creation timestamp for this event
  public long getTimestamp()

  // the type of this job event
  public JobEventType getEventType()

  // Get the uuid of the driver which emitted the notification
  public String getDriverUuid()
}

The value of the job event type (see JobEventType type safe enumeration) is one of the following:

  • JOB_QUEUED: a new job was submitted to the JPPF driver queue
  • JOB_ENDED: a job was completed and sent back to the client
  • JOB_DISPATCHED: a sub-job was dispatched to a node
  • JOB_RETURNED: a sub job returned from a node
  • JOB_UPDATED: one of the job attributes has changed

3 Accessing and using the server MBeans

As for the nodes, JPPF provides an API that simplifies access to the JMX-based management features of a server, by abstracting most of the complexity of JMX programming. This API is implemented by the class JMXDriverConnectionWrapper, which provides a simplified way of connecting to the server's MBean server, along with a set of convenience methods to easily access the MBeans' exposed methods and attributes. Please note that this class implements the JPPFDriverAdminMBean interface.

3.1 Connecting to an MBean server

Connection to to a server MBean server is done in two steps:

a. Create an instance of JMXDriverConnectionWrapper

To connect to a local (same JVM) MBean server, use the no-arg constructor:

JMXDriverConnectionWrapper wrapper = new JMXDriverConnectionWrapper();

To connect to a remote MBean server, use the constructor specifiying the management host, port and secure flag:

JMXDriverConnectionWrapper wrapper = new JMXDriverConnectionWrapper(host, port, secure);

Here host and port represent the server's configuration properties “jppf.management.host” and “jppf.management.port”, and secure is a boolean flag indicating whether the network transport is secured via SSL/TLS.


b. Initiate the connection to the MBean server and wait until it is established

There are two ways to do this:

Synchronously:

// connect and wait for the connection to be established
// choose a reasonable value for the timeout, or 0 for no timeout
wrapper.connectAndWait(timeout);

Asynchronously:

// initiate the connection; this method returns immediately
wrapper.connect()
// ... do something else ...
// check if we are connected
if (wrapper.isConnected()) ...;
else ...;

3.2 Direct use of the JMX wrapper

JMXDriverConnectionWrapper implements directly the JPPFDriverAdminMBean interface. This means that all the JPPF server's management and monitoring methods can be used directly from the JMX wrapper. For example:

JMXDriverConnectionWrapper wrapper = new JMXDriverConnectionWrapper(host, port);
wrapper.connectAndWait(timeout);
// get the ids of all jobs in the server queue
String jobUuids = wrapper.getAllJobIds();
// stop the server in 2 seconds (no restart)
wrapper.restartShutdown(2000L, -1L);

3.3 Use of the JMX wrapper's invoke() method

JMXConnectionWrapper.invoke() is a generic method that allows invoking any exposed method of an MBean.

Here is an example:

JMXDriverConnectionWrapper wrapper = new JMXDriverConnectionWrapper(host, port, secure);
wrapper.connectAndWait(timeout);
// equivalent to JPPFStats stats = wrapper.statistics();
JPPFStats stats = (JPPFStats) wrapper.invoke(
  JPPFDriverAdminMBean.MBEAN_NAME, "statistics", (Object[]) null, (String[]) null);
int nbNodes = stats.getNodes().getLatest();

3.4 Use of an MBean proxy

A proxy is a dynamically created object that implements an interface specified at runtime.

The standard JMX API provides a way to create a proxy to a remote or local MBean. This is done as follows:

JMXDriverConnectionWrapper wrapper = new JMXDriverConnectionWrapper(host, port, secure);
wrapper.connectAndWait(timeout);
// create the proxy instance
DriverJobManagementMBean proxy = '''wrapper.getProxy(
  DriverJobManagementMBean.MBEAN_NAME,  DriverJobManagementMBean.class);
// get the ids of all jobs in the server queue
String jobIds = proxy.getAllJobIds();

JMXDriverConnectionWrapper also has a more convenient method getJobManager() to obtain a proxy to the job management MBean:

JMXDriverConnectionWrapper wrapper = ...;
// create the proxy instance
DriverJobManagementMBean proxy = wrapper.getJobManager();
// get the ids of all jobs in the server queue
String[] jobUuids = proxy.getAllJobUuids();

3.5 Subscribing to MBean notifications

We have seen that the task monitoring MBean represented by the JPPFNodeTaskMonitorMBean interface is able to emit notifications of type TaskExecutionNotification. There are 2 ways to subscribe to these notifications:


a. Using a proxy to the MBean

JMXDriverConnectionWrapper wrapper = new JMXNodeConnectionWrapper(host, port, secure);
wrapper.connectAndWait(timeout);
DriverJobManagementMBean proxy = wrapper.getJobManager();
// subscribe to all notifications from the MBean
proxy.addNotificationListener(myJobNotificationListener, null, null);


b. Using the MBeanServerConnection API

JMXDriverConnectionWrapper wrapper = new JMXDriverConnectionWrapper(host, port, secure);
wrapper.connectAndWait(timeout);
MBeanServerConnection mbsc = wrapper.getMbeanConnection();
ObjectName objectName = new ObjectName(DriverJobManagementMBean.MBEAN_NAME);
// subscribe to all notifications from the MBean
mbscaddNotificationListener(objectName, myNotificationListener, null, null);

Here is an example notification listener implementing the NotificationListener interface:

// this class prints a message each time a job is added to the server's queue
public class MyJobNotificationListener implements NotificationListener {
  // Handle an MBean notification
  public void handleNotification(Notification notification, Object handback) {
    JobNotification jobNotif = (JobNotification) notification;
    JobEventType eventType = jobNotif.getEventType();
    // print a message for new jobs only
    if (eventType == JobEventType.JOB_QUEUED) {
      String uuid = jobNotif.getJobInformation().getJobUuid();
      System.out.println("job " + uuid + " was queued at " + jobNotif.getTimeStamp());
    }
  }
};
NotificationListener myJobNotificationListener = new MyJobNotificationListener();

4 Remote logging

It is possible to receive logging messages from a driver as JMX notifications. Specific implementations are available for Log4j and JDK logging. To configure Log4j to send JMX notifications, edit the log4j configuration files of the driver and add the following:

### direct messages to the JMX Logger ###
log4j.appender.JMX = org.jppf.logging.log4j.JmxAppender
log4j.appender.JMX.layout = org.apache.log4j.PatternLayout
log4j.appender.JMX.layout.ConversionPattern = %d [%-5p][%c.%M(%L)]: %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger = INFO, JPPF, JMX

To configure the JDK logging to send JMX notifications, edit the JDK logging configuration file of the driver as follows:

# list of handlers
handlers = java.util.logging.FileHandler, org.jppf.logging.jdk.JmxHandler
# Write log messages as JMX notifications
org.jppf.logging.jdk.JmxHandler.level = FINEST
org.jppf.logging.jdk.JmxHandler.formatter = org.jppf.logging.jdk.JPPFLogFormatter

To receive the logging notifications from a remote application, you can use the following code:

// get a JMX connection to the node MBean server
JMXDriverConnectionWrapper jmxDriver = new JMXDriverConnectionWrapper(host, port, secure);
jmxDriver.connectAndWait(5000L);
// get a proxy to the MBean
JmxLogger driverProxy =
  jmxDriver.getProxy(JmxLogger.DEFAULT_MBEAN_NAME, JmxLogger.class);
// use a handback object so we know where the log messages come from
String source = "driver " + jmxDriver.getHost() + ":" + jmxDriver.getPort();
// subscribe to all notifications from the MBean
NotificationListener listener = new MyLoggingHandler();
driverProxy.addNotificationListener(listener, null, source);

// Logging notification listener that prints remote log messages to the console
public class MyLoggingHandler implements NotificationListener {
  // handle the logging notifications
  public void handleNotification(Notification notification, final Object handback) {
    String message = notification.getMessage();
    System.out.println(handback.toString() + ": " + message);
  }
}
Main Page > Management and monitoring > Server management



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