JPPF Forums

General Discussions => Forums => Topic started by: brian on May 30, 2016, 06:04:05 PM

Title: Driver embedded in client
Post by: brian on May 30, 2016, 06:04:05 PM
Hi,

I have some basic use cases where simple deployment is primary factor, for those cases I'd like to embed the driver in same JVM as the client. These will be single human user cases with no need for standalone driver. Is this possible? Ideally I could also avoid opening ports for client <-> driver communication in this case.

Thanks.
Title: Re: Driver embedded in client
Post by: lolo on May 31, 2016, 06:11:45 AM
Hello,

Unfortunately, it is not possible to embed the driver without opening TCP connections. The driver was simply not designed this way.
If this is not a blocker, you can still run a driver in the same JVM as your application. For this you need a number of things:

1) add the missing driver dependencies jppf-server.jar and jppf-node.jar to the classpath

2) to start a driver, call org.jppf.server.JPPFDriver.main("noLauncher") (the "noLauncher" parameter is required).

3) by default, there will be some overlap between the client and the driver configuration. In particular, the load-balancing (http://www.jppf.org/doc/5.1/index.php?title=Configuring_a_JPPF_server#Load-balancing) configuration properties are exactly the same for both. This will not prevent either from working, but in some cases it may result in suboptimal perofrmance. If this is really a problem, you can create the JPPFClient with an explicit configuration, using the undocumented constructor JPPFClient(String uuid, TypedProperties config, ConnectionPoolListener... listeners), for instance:

Code: [Select]
public static JPPFClient createClient() {
  TypedProperties clientConfig = new TypedProperties();
  clientConfig.setBoolean("jppf.discovery.enabled", false) // disable server discovery
    .setString("jppf.drivers", "driver1")                  // declare a named driver connection pool
    .setString("driver1.jppf.server.host", "localhost")    // set the driver host or IP
    .setInt("driver1.jppf.server.port", 11111)             // set the driver port
    .setInt("driver1.jppf.pool.size", 1);                  // set the connection pool size
  // let the client generate its own uuid, use the specified configuration, with no connection pool listener
  return new JPPFClient(null, clientConfig, new ConnectionPoolListener[0]);
}

With this, you should be good to go.

Sincerely,
-Laurent
Title: Re: Driver embedded in client
Post by: brian on June 14, 2016, 02:41:28 AM
Thanks.

With discovery disabled, can I tell driver to use port 0 to select its ports, then programmatically find out which ports it chose, and dynamically start client+node with the proper driver ports configured? Again the goal is simplest possible deployment for basic use cases.

One problem I see with calling JPPFDriver.main is that it starts threads which keep the JVM from shutting down. What would be a nice way of shutting it down when my client is closed?
Title: Re: Driver embedded in client
Post by: lolo on June 14, 2016, 08:37:12 AM
Hello,

One thing I'm wondering about is why not simply use the client's local executor in this use case? It can be enabled either via the configuration (http://www.jppf.org/doc/5.1/index.php?title=Client_and_administration_console_configuration#Local_and_remote_execution) or dynamically via the JPPFClient API (http://www.jppf.org/doc/5.1/index.php?title=The_JPPFClient_API#Switching_local_execution_on_or_off). With client-local execution enabled, you don't need a driver + node anymore, unless you intend to run the jobs on multiple nodes. The jobs will be submitted using the exact same client APIs, but they will be executed in a local thread pool instead of on a remote driver. You will also avoid the network and serialization overhead that is incured by using a driver and node.

Quote
can I tell driver to use port 0 to select its ports, then programmatically find out which ports it chose, and dynamically start client+node with the proper driver ports configured?

Yes, it should be doable like this:

Code: [Select]
// set port 0 to have the driver chose an arbitrary port
JPPFConfiguration.getProperties().setInt("jppf.server.port", 0):
JPPFDriver.main("noLauncher");

// retrieve the port number (using undocumented APIs)
JPPFDriver driver = JPPFDriver.getInstance();
int port = -1;
int[] ports = driver.getAcceptorServer().getPorts();
if ((ports != null) && (ports.length > 0)) port = ports[0];
else {
  int[] sslPorts = driver.getAcceptorServer().getSSLPorts();
  if ((sslPorts != null) && (sslPorts.length > 0)) port = sslPorts[0];
}

// setup the client with the port number
TypedProperties clientConfig = new TypedProperties().setBoolean("jppf.discovery.enabled", false)
  .setString("jppf.drivers", "driver1")
  .setString("driver1.jppf.server.host", "localhost")
  .setInt("driver1.jppf.server.port", port);
JPPFClient client = new JPPFClient(null, clientConfig, new ConnectionPoolListener[0]);

Quote
What would be a nice way of shutting it down when my client is closed?
There isn't a nice way to do that. You may want to use the management APIs to shutdown the driver, but ultimately it will result in the JVM being shut down.

Sincerely,
-Laurent
Title: Re: Driver embedded in client
Post by: brian on June 17, 2016, 09:00:55 PM
Quote
One thing I'm wondering about is why not simply use the client's local executor in this use case?

My embedded driver use case still requires remote execution, there will be many workers for the single client/driver. But the deployment overhead of a remote driver is not required because driver/workers will only serve this one client, and they (driver at least, maybe workers too) will be transient (die with client).

Quote
There isn't a nice way to do that.

To confirm, there is no way of embedding a driver with different lifecycle (ie, destroyed before) the host JVM and you don't wish to support that use case.
Title: Re: Driver embedded in client
Post by: lolo on June 27, 2016, 02:29:14 PM
Hello,

I am willing to support this use case and I did, in fact, implement it as enhancement JPPF-458 Ability to shutdown a driver without exiting the JVM (http://www.jppf.org/tracker/tbg/jppf/issues/JPPF-458)

I have released it as patch 01 for JPPF 5.1.4 (http://www.jppf.org/patch_info.php?patch_id=57) and it will aslo be part of the upcoming v5.2.

The enhancement consisted in adding a server configuration property "jppf.server.exitOnShutdown = false" (defaults to true to preserve prior behavior) and modifying the server code to use that property. Now you can shutdown the server (http://www.jppf.org/doc/5.1/index.php?title=Server_management#Stopping_and_restarting_the_server) via the jmx API, and when this property is set to false, the server will shutdown without exiting the JVM.

Example usage:

Code: [Select]
JPPFConfiguration.getProperties().setBoolean("jppf.server.exitOnShutdown", false);

// no-arg contructor ==> no network connection nor remote JMX connector
JMXDriverConnectionWrapper jmx = new JMXDriverConnectionWrapper();
jmx.connect();
jmx.restartShutdown(1L, -1L);
jmx.close();

I have also attached a full client sample code which I used to test this, in the hope you'll find it useful.

Sincerely,
-Laurent
Title: Re: Driver embedded in client
Post by: brian on June 27, 2016, 07:26:07 PM
Lovely, thank you.
Title: Re: Driver embedded in client
Post by: brian on July 20, 2016, 01:06:35 AM
I attempted embedding driver in client JVM running on my desktop and learned something odd about our corporate environment, developer desktops have firewalls which block inbound connections. This meant nodes could not connect to the driver I was running on my desktop.

This is my problem to resolve not yours, but it does make me wonder if JPPF allows having driver initiate connections to nodes instead of nodes initiating connections to driver. If that was possible I could have nodes register themselves in zookeeper and driver discover and connect to them rather than the other way around.
Title: Re: Driver embedded in client
Post by: brian on July 20, 2016, 01:24:43 AM
Another workaround option I just thought of, I could change those remote nodes to be drivers each with a local node and not aware of each other. Then my desktop embedded driver could discover and connect out to each remote driver. It's a bit odd, and would probably look a bit odd in the management UI.

Which option do you like better?
Title: Re: Driver embedded in client
Post by: lolo on July 21, 2016, 07:41:42 AM
Hello,

The two options actually boil down to the same thing. In effect, when a driver connects to another driver, it "masquerades" as a node and uses the exact same communication protocol. The only difference is that it sets a "peer driver" flag during handshake, so the other driver knows what it's dealing with. On the other hand, the driver initiating the connection sees the other driver as a client.

To me, it doesn't make sense to have the driver connect to he the nodes. One of the implications is that the driver would have to discover the nodes, which in my sense is not a realistic way to implement a grid with a fully dynamic topology, not if you want to scale to thousands or even millions of nodes. For instance, I'm thinking of JPPF in a volunteer computing setup, where nodes in offline mode (http://www.jppf.org/doc/5.2/index.php?title=Offline_nodes) can connect at any time from the public network.

By the way, you should have the same issue if you use the admin UI to monitor a remote driver, since the JMX connection has to be initiated by the console, is this correct?

To conclude, the solution has to be to allow inbound connections to the driver's port (and its JMX port as well). This is technically the simplest way, even though I understand it may be a pain from an administrative perspective.

Sincerely,
-Laurent
Title: Re: Driver embedded in client
Post by: brian on November 05, 2016, 07:37:03 PM
Hi,
Just wanted to let you know, this continues to be an issue for us, for users who want a nice quickstart recipe that doesn't require deploying a driver process, we currently provide a non-jppf solution where client discovers and talks to nodes directly. Ideally we'd use jppf only and embed a driver in the client which initiated the connection to nodes, having jppf support both standalone driver usecase and the more simple (and less scalable) "smart client" usecase.
Thanks.