Chapter 6. Designing VoltDB Client Applications

Documentation

VoltDB Home » Documentation » Using VoltDB

Chapter 6. Designing VoltDB Client Applications

After you design and partition your database schema (Chapter 4, Designing the Database Schema), and after you design the necessary stored procedures (Chapter 5, Designing Stored Procedures to Access the Database), you are ready to write the client application logic. The client code contains all the business-specific logic required for the application, including business rule validation and keeping track of constraints such as proper data ranges for arguments entered in stored procedure calls.

The three steps to using VoltDB from a client application are:

  1. Creating a connection to the database

  2. Calling stored procedures

  3. Closing the client connection

The following sections explain how to perform these functions using the standard VoltDB Java client interface. (See VoltDB Java Client API.) The VoltDB Java Client is a thread-safe class library that provides runtime access to VoltDB databases and functions.

It is possible to call VoltDB stored procedures from programming languages other than Java. However, reading this chapter is still recommended to understand the process for invoking and interpreting the results of a VoltDB stored procedure. See Chapter 8, Using VoltDB with Other Programming Languages for more information about using VoltDB from client applications written in other languages.

6.1. Connecting to the VoltDB Database

The first task for the calling program is to create a connection to the VoltDB database. You do this with the following steps:

org.voltdb.client.Client client = null;
ClientConfig config = null;
try {
       config = new ClientConfig("advent","xyzzy");       1

       client = ClientFactory.createClient(config);       2
 
       client.createConnection("myserver.xyz.net");       3
} catch (java.io.IOException e) {
       e.printStackTrace();
       System.exit(-1);
}

1

Define the configuration for your connections. In its simplest form, the ClientConfig class specifies the username and password to use. It is not absolutely necessary to create a client configuration object. For example, if security is not enabled (and therefore a username and password are not needed) a configuration object is not required. But it is a good practice to define the client configuration to ensure the same credentials are used for all connections against a single client. It is also possible to define additional characteristics of the client connections as part of the configuration, such as the timeout period for procedure invocations or a status listener. (See Section 6.5, “Handling Errors”.)

2

Create an instance of the VoltDB Client class.

3

Call the createConnection() method. After you instantiate your client object, the argument to createConnection() specifies the database node to connect to. You can specify the server node as a hostname (as in the preceding example) or as an IP address. You can also add a second argument if you want to connect to a port other than the default. For example, the following createConnection() call attempts to connect to the admin port, 21211:

client.createConnection("myserver.xyz.net",21211);

If security is enabled and the username and password in the ClientConfig() call do not match a user defined in the deployment file, the call to createConnection() will throw an exception. See Chapter 12, Security for more information about the use of security with VoltDB databases.

When you are done with the connection, you should make sure your application calls the close() method to clean up any memory allocated for the connection. See Section 6.4, “Closing the Connection”.

6.1.1. Connecting to Multiple Servers

You can create the connection to any of the nodes in the database cluster and your stored procedure will be routed appropriately. In fact, you can create connections to multiple nodes on the server and your subsequent requests will be distributed to the various connections. For example, the following Java code creates the client object and then connects to all three nodes of the cluster. In this case, security is not enabled so no client configuration is needed:

try {
       client = ClientFactory.createClient();
       client.createConnection("server1.xyz.net");
       client.createConnection("server2.xyz.net");
       client.createConnection("server3.xyz.net");
} catch (java.io.IOException e) {
       e.printStackTrace();
       System.exit(-1);
}

Creating multiple connections has three major benefits:

  • Multiple connections distribute the stored procedure requests around the cluster, avoiding a bottleneck where all requests are queued through a single host. This is particularly important when using asynchronous procedure calls or multiple clients.

  • For Java applications, the VoltDB Java client library uses client affinity. That is, the client knows which server to send each request to based on the partitioning, thereby eliminating unnecessary network hops.

  • Finally, if a server fails for any reason, when using K-safety the client can continue to submit requests through connections to the remaining nodes. This avoids a single point of failure between client and database cluster. See Chapter 10, Availability for more.

6.1.2. Using an Auto-Reconnecting Client

If the client application loses contact with a server (either because the server goes down or a temporary network glitch), the connection to that server is closed. Assuming the application has connections to multiple servers in the cluster, it can continue to submit stored procedures through the remaining connections. However, the lost connection is not, by default, restored.

The application can use error handling to detect and recover from broken connections, as described in Section 6.5.2, “Handling Timeouts”. Or you can enable auto-reconnecting when you initialize the client object. You set auto-reconnecting in the client configuration before creating the client object, as in the following example:

org.voltdb.client.Client client = null;
ClientConfig config = new ClientConfig("","");
config.setReconnectOnConnectionLoss(true);
 try {
       client = ClientFactory.createClient(config);
       client.createConnection("server1.xyz.net");
       client.createConnection("server2.xyz.net");
       client.createConnection("server3.xyz.net");
            . . .

When setReconnectOnConnectionLoss() is set to true, the client library will attempt to reestablish lost connections, attempts starting every second and backing off to every eight seconds. As soon as the connection is reestablished, the reconnected server will begin to receive its share of the procedure calls.