The JPPFClient API
From JPPF 6.3 Documentation
(→Default job execution policies) |
Latest revision as of 06:34, 21 August 2019
A JPPF client is an object that will handle the communication between the application and the server. Its role is to:
- manage one or multiple connections with the server
- submit jobs and get their results
- handle notifications of job results
- manage each connection's life cycle events
- provide the low-level machinery on the client side for the distributed class loading mechanism
- provide an access point for the management and monitoring of each server
A JPPF client is represented by the class JPPFClient. We will detail its functionalities in the next sub-sections.
[edit] 1 Creating and closing a JPPFClient
A JPPF client is a Java object, and is created via one of the constructors of the class JPPFClient. Each JPPF client has a unique identifier that is always transported along with any job that is submitted by this client. This identifier is what allows JPPF to know from where the classes used in the tasks should be loaded. In effect, each node in the grid will have a map of each client identifier with a unique class loader, creating the class loader when needed. The implication is that, if a new client identifier is specified, the classes used in any job / task submiotted by this client will be dynamically reloaded. This is what enables the immediate dynamic redeployment of code changes in the application. On the other hand, if a previously existing identifier is reused, then no dynamic redeployment occurs, and code changes will be ignored (i.e. the classes already loaded by the node will be reused), even if the application is restarted between 2 job submissions.
There are two forms of constructors for JPPFClient, each with a specific corresponding semantics:
Generic constructor with automatic identifier generation
public JPPFClient()
When using this constructor, JPPF will automatically create a universal unique identifier (uuid) that is guaranteed to be unique on the grid. The first submission of a job will cause the classes it uses to be dynamically loaded by any node that executes the job.
Constructor specifying a user-defined client identifier
public JPPFClient(String uuid)
In this case, the classes used by a job will be loaded only the first time they are used, including if the application has been restarted in the meantime, or if the JPPF client is created from a separate application. This behavior is more adapted to an application deployed in production, where the client identifier would only change when a new version of the application is deployed on the grid. It is a good practice to include a version number in the identifier.
As a JPPFClient uses a number of system and network resources, it is recommended to use it as a singleton. It is designed for concurrent use by multiple threads, which makes it safe for use with a singleton pattern. It is also recommended to release these resources when they are no longer needed, via a call to the JPPFClient.close() method. The following code sample illustrates what is considered a best practice for using a JPPFClient:
public class MyApplication { // singleton instance of the JPPF client private static JPPFClient jppfClient = new JPPFClient(); // allows access to the client from any other class public static JPPFClient getJPPFClient() { return jppfClient; } public static void main(String...args) { // enclosed in a try / catch to ensure resources are properly released try { '''jppfClient = new JPPFClient();''' // ... application-sepcific code here ... } finally { // close the client to release its resources if (jppfClient != null) '''jppfClient.close()'''; } } }
[edit] 2 Resetting the JPPF client
A JPPFClient can be reset at runtime, to allow the recycling of its server connections, along with dynamic reloading of its configuration. Two methods are provided for this :
public class JPPFClient extends AbstractGenericClient { // close this client, reload the configuration, then open it again public void reset() // close this client, then open it again using the specified confguration public void reset(TypedProperties configuration) }
Note that jobs that were already submitted by the client are not lost: they remain queued in the client and will be resubmitted as soon as one or more server connections become available again.
[edit] 3 Submitting a job
To submit a job, JPPFClient provides two methods:
public class JPPFClient extends AbstractGenericClient { // Submit a job synchronously and wait for the results public List<Tasks<?>> submit(JPPFJob job) // Submit a job asynchronously and return immediately public JPPFJob submitAsync(JPPFJob job) }
These methods have different behaviors:
- the submit() method blocks until the job execution is complete. The return value is a list of tasks with their results, in the same order as the tasks that were added to the job.
- submitAsync() returns immediately, not waiting for the job to execute. It is up to the developer to collect the execution results, generally via the JPPF job API.
[edit] 4 Cancelling a job
The ability to cancel a job is provided by JPPFClient's superclass AbstractGenericClient, which provides a cancelJob() method, defined as follows:
// superclass of JPPFClient public abstract class AbstractGenericClient extends AbstractJPPFClient { // cancel the job with the specified UUID public boolean cancelJob(final String jobUuid) throws Exception; }
This method will work even if the client is connected to multiple drivers. In this case, it will send the cancel request to all the drivers.
[edit] 5 Switching local execution on or off
The JPPFClient API allows users to dynamically turn the local (in the client JVM) execution of jobs on or off, and determine whether it is active or not. This is done via these two methods:
// Determine whether local execution is enabled on this client public boolean isLocalExecutionEnabled() // Specify whether local execution is enabled on this client public void setLocalExecutionEnabled(boolean localExecutionEnabled)
Turning local execution on or off will affect the next job to be executed, but not any that is currently executing.
[edit] 6 Registering additional class loaders to handle requests from the driver
In some unusual use cases, it may be necessary to register addtional class loaders witht he cllient for a given job. This can happen if some of the tasks in the job are loaded with different class loaders, or in some situations when the job is submitted from task executing in a a node. To enable this, the super class of JPPFClient, AbstractGenericClient, provides the following method:
public class AbstractGenericClient extends AbstractJPPFClient { // register a class loader for the specified job uuid public ClassLoader registerClassLoader(ClassLoader cl, String uuid) }
The class loader must be registered before the job is submitted, otherwise it will have no effect. Additionally, the unregistration of the class loader is automatically performed by the JPPF client, once the job has completed.
Example usage:
JPPFClient client = new JPPFClient(); JPPFJob job = newJPPFJob(); // let's assume MyTask is loaded from a separate class loader MyTask myTask = ...; job.add(task); ClassLoader cl = myTask.getClass().getClassLoader(); // register the class loader for the job, before submitting it client.registerClassLoader(cl, job.getUuid()); List<Task<?>> result = client.submit(job);
[edit] 7 Changing and retrieving the load-balancer settings
The load-balancer configuration can be dynamically updated and retrieved, even while the client is executing jobs, using the following methods in JPPFClient:
public class JPPFClient extends AbstractGenericClient { // Get the current load-balancer settings public LoadBalancingInformation getLoadBalancerSettings() // Change the load balancer settings public void setLoadBalancerSettings(String algorithm, Properties parameters) throws Exception }
The parameters of the setLoadBalancerSettings() method are those of the load-balancing algorithm and must not be prefixed. The getLoadBalancerSettings() method provides the current configuration encapsulated in a LoadBalancingInformation object.
Example usage:
JPPFClient jppfCLient = new JPPFClient(); // configure the "proportional" load-balancer algorithm TypedProperties props = new TypedProperties() .setInt("initialSize", 5) .setInt("proportionalityFactor", 1); jppfClient.setLoadBalancerSettings("proportional", props); // retrieve the load-balancer configuration LoadBalancingInformation lbi = jppfClient.getLoadBalancerSettings(); System.out.println("current algorithm is " + lbi.getAlgorithm()); System.out.println("algorithm parameters: " + lbi.getParameters());
[edit] 8 Default job execution policies
A JPPFClient instance can have a default client and/or server side execution policy. The default policies are applied only to submitted jobs that don't have an execution policy (i.e. the execution policy is null). Default execution policies can be set or retrieved with the following methods:
public class JPPFClient extends AbstractGenericClient { // Get the default server-side job execution policy public ExecutionPolicy getDefaultPolicy() // Set the default server-side job execution policy public void setDefaultPolicy(ExecutionPolicy defaultServerPolicy) // Get the default client-side job execution policy public ExecutionPolicy getDefaultClientPolicy() // Set the default client-side job execution policy public void setDefaultClientPolicy(ExecutionPolicy defaultClientPolicy) }
Here is an example usage:
try (JPPFClient client = new JPPFClient()) { // by default, jobs can only execute on nodes with at least 4 CPUs client.setDefaultPolicy(new AtLeast("availableProcessors", 4)); // by default, jobs cannot execute in the client local executor client.setDefaultClientPolicy(new Equal("jppf.channel.local", false)); }
[edit] 9 Inspecting the jobs queue
You can list and count the jobs queued in a JPPFClient instance, using the following methods:
public class JPPFClient extends AbstractGenericClient { // Get the list of currently queued jobs public List<JPPFJob> getQueuedJobs() // Get a list of currently queued jobs, filtered by a JobSelector public List<JPPFJob> getQueuedJobs(JobSelector selector) // Get the current number of queued jobs public int getQueuedJobsCount() // Get the current number of jobs that satisfy a job selector public int getQueuedJobsCount(JobSelector selector) }
Note that you can view or count either all jobs or jobs filtered by a job selector.
Example usage:
JPPFJob job = new JPPFJob(); job.setBlocking(false); job.add(new MyTask()); try (JPPFClient client = new JPPFClient()) [ client.submitJob(job); List<JPPFJob> jobs = client.getQueuedJobs(); // ... do something with the list of queued jobs .. final List<Task<?>> results = job.awaitResults(); // ... process the results ... }
Main Page > Development guide > The JPPFClient API |