Defining the node connection strategy
From JPPF 6.2 Documentation
|
Main Page > Customizing JPPF > Node connection strategy |
By default, JPPF nodes rely on their configuration to find out the information required to connect to a server: either via UDP multicast discovery when discovery is enabled, or via manually set configuration properties for the server host, port, whether SSL is enabled, etc... This makes it potentially complex to define what the behavior should be when the node fails to connect to a server. For example this does not allow to define which server(s) a node should fail over to in case a server dies or is no longer reacheable via the network.
The connection strategy add-on provides a simple way to specify which server a node shoud connect to and how to react when it fails to do so.
1 The DriverConnectionStrategy interface
The node's strategy to connect to a driver is defined as an implementation of the interface DriverConnectionStrategy, which is defined as follows:
// Defines which parameters should be used to connect to the driver public interface DriverConnectionStrategy { // Get a new connection information, eventually based on the current one DriverConnectionInfo nextConnectionInfo( DriverConnectionInfo currentInfo, ConnectionContext context); }
This interface defines a single method which takes two parameters as input, and returns a DriverConnectionInfo object, which encapsulates the information required to connect to a JPPF driver.
The first parameter represents the current connection information, that is, the information that was used for the last connection attempt. When the node connects for the first time, this parameter will be null. This parameter is an instance of the interface DriverConnectionInfo, defined as follows:
public interface DriverConnectionInfo { // determine whether secure SSL/TLS connections should be established boolean isSecure(); // get the driver host name or IP address String getHost(); // get the driver port to connect to int getPort(); // whether the heartbeat (recovery) mechanism is enabled boolean isRecoveryEnabled(); }
JPPF provides a ready-to-use implementation of this interface with the class JPPFDriverConnectionInfo.
The second parameter represents the context of the connection or reconnection request, basically explaining why the request is made. It could be due to a management request or to an error occurring within the node, or simply the first connection attempt at node startup time. It is designed to help make a decision about which driver to connect to. It is an instance of the class ConnectionContext, defined as:
public class ConnectionContext { // get an explanation text for the reconnection public String getMessage() // get an eventual Throwable that triggered the reconnection public Throwable getThrowable() // get the reason for the connection or reconnection public ConnectionReason getReason() }
The getReason() method returns a reason code among those defined in the ConnectionReason enum:
public enum ConnectionReason { // indicates the first connection attempt when the node starts up INITIAL_CONNECTION_REQUEST, // a reconnection was requested via the management APIs or admin console MANAGEMENT_REQUEST, // An error occurred while initializing the class loader connection CLASSLOADER_INIT_ERROR, // an error occurred while processing a class loader request CLASSLOADER_PROCESSING_ERROR, // an error occurred during the job channel initialization JOB_CHANNEL_INIT_ERROR, // an error occurred on the job channel while processing a job JOB_CHANNEL_PROCESSING_ERROR, // the heartbeat mechanism failed to receive a message from the server HEARTBEAT_FAILURE }
The following example implementation uses a set of driver connection information objects stored in a queue and performs a round-robin selection at each connection request:
public class MyConnectionStrategy implements DriverConnectionStrategy { // the queue in which DriverConnectionInfo objects are stored private final Queue<DriverConnectionInfo> queue = new LinkedBlockingQueue<>(); // initialize the set of drivers to connect to public MyConnectionStrategy() { queue.offer(new JPPFDriverConnectionInfo(false, "192.168.1.11", 11111, false)); queue.offer(new JPPFDriverConnectionInfo(false, "192.168.1.12", 11111, false)); queue.offer(new JPPFDriverConnectionInfo(true, "192.168.1.13", 11443, false)); } @Override public DriverConnectionInfo nextConnectionInfo( DriverConnectionInfo currentInfo, ConnectionContext context) { DriverConnectionInfo info; // if the reconnection is requested via management, keep the current driver info if ((currentInfo != null) && (context.getReason() == ConnectionReason.MANAGEMENT_REQUEST)) { info = currentInfo; } else { // extract the next info from the queue info = queue.poll(); // put it back at the end of the queue queue.offer(info); } return info; } }
public class MyConnectionStrategy implements DriverConnectionStrategy { // the node configuration passed to the constructor private final TypedProperties configuration; public MyConnectionStrategy(TypedProperties configuration) { this. configuration = configuration; } @Override public DriverConnectionInfo nextConnectionInfo( DriverConnectionInfo currentInfo, ConnectionContext context) { ... } }
2 Pluging the strategy into the node
Specifying which connection strategy a node should use is done in the node's configuration as follows:
# fully qualified name of a class implementing DriverConnectionStrategy jppf.server.connection.strategy = test.MyConnectionStrategy
As stated in the comment, the value of the “jppf.server.connection.strategy” property is the fully qualified name of a class implementing DriverConnectionStrategy, which must also have a no-args constructor. If this property is left unspecified, or if the specified class cannot be instantiated, the node will default to an instance of JPPFDefaultConnectionStrategy, which uses the configuration to find out the connection information, either via server discovery or from the manually specified server-related properties.
3 Built-in strategies
3.1 File-based CSV server definitions
In addition to the default JPPFDefaultConnectionStrategy, JPPF provides a connection strategy which reads a list of driver connection information from a CSV file. As in the example above, it will perform a round-robin selection of the drivers to connect to. Additionally, if the specified CSV file is invalid or cannot be read, or none of its entries is valid, it will default to JPPFDefaultConnectionStrategy.
This implementation is named JPPFCsvFileConnectionStrategy and is configured as follows:
# read the driver connection info from a CSV file jppf.server.connection.strategy = org.jppf.node.connection.JPPFCsvFileConnectionStrategy # location of the CSV file jppf.server.connection.strategy.file = /home/me/data/drivers.csv
The file is first looked up in the file system at the specified location, then in the classpath if not found in the file system.
The syntax and format for the entries in the CSV files are as in the following example:
# CSV columns: ssl_enabled, server_host, server_port, recovery_enabled # server 1 false, 192.168.1.15, 11111, false # server 2, with recovery enabled false, 192.168.1.16, 11111, true # server 3, with SSL enabled true, 192.168.1.17, 11443, false
Please note that any line starting with a '#' (after trimming) is considered a comment.
3.2 Configuration-based CSV server definitions
JPPFCsvPropertyConnectionStrategy is very similar to JPPFCsvFileConnectionStrategy, with the difference that it takes the values from a single configuration property instead of from a file, with the following format:
jppf.server.connection.strategy.definitions = \ secure1, host1, port1, recovery_enabled1 | \ ... | \ secureN, hostN, portN, recovery_enabledN
where:
- each connection definition is represented as a group of comma-separated values
- csv groups are separated with the '|' (pipe) character
- in each csv group:
- securei is a boolean value (either 'true' or 'false', case-insensitive) indicating whether SSL/TLS connectivity is enabled. Any value that is not 'true' is interpreted as 'false'.
- hosti is the host name or ip address of the driver to connect to
- porti is the port to connect to on the driver host
- recovery_enabledi determines whether the recovery (heartbeat) mechanism should be enabled for the node
- if the first character is a '#' then the group is considered a comment and ignored.
Here is an example configuration:
# read the driver connection info from a configuration property jppf.server.connection.strategy = \ org.jppf.node.connection.JPPFCsvPropertyConnectionStrategy # definitions of the server connections jppf.server.connection.strategy.definitions = \ # definition for server 1 |\ false, my.host1.org, 11111, false |\ # definition for server 2 |\ true, my.host2.org, 11443, true
Note the multiline syntax that makes the configuration easier to read.
Main Page > Customizing JPPF > Node connection strategy |