org.voltdb.jdbc.JDBC4ClientConnectionPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of voltdbclient Show documentation
Show all versions of voltdbclient Show documentation
VoltDB client interface libraries
/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB. If not, see .
*/
package org.voltdb.jdbc;
import java.util.HashMap;
import org.voltcore.utils.ssl.SSLConfiguration;
/**
* Provides support for database connection pooling, allowing for optimal application performance.
* From benchmarking results, optimal TCP socket usage is attained when 50 threads share the same
* socket, sending execution requests through it. The pool incorporate the logic necessary to issue
* newly created connections or pre-existing connections in use to client threads, as well as proper
* management of those connections (releasing resources, etc.).
*
* @author Seb Coursol (originally in exampleutils)
* @since 2.0
*/
public class JDBC4ClientConnectionPool {
private static final HashMap ClientConnections = new HashMap();
/**
* No instantiation allowed.
*/
private JDBC4ClientConnectionPool() {
}
/**
* Gets a client connection to the given VoltDB server(s).
*
* @param servers
* the list of VoltDB servers to connect to.
* @param port
* the VoltDB native protocol port to connect to (usually 21212).
* @param user
* the user name to use when connecting to the server(s).
* @param password
* the password to use when connecting to the server(s).
* @param isHeavyWeight
* the flag indicating callback processes on this connection will be heavy (long
* running callbacks). By default the connection only allocates one background
* processing thread to process callbacks. If those callbacks run for a long time,
* the network stack can get clogged with pending responses that have yet to be
* processed, at which point the server will disconnect the application, thinking it
* died and is not reading responses as fast as it is pushing requests. When the flag
* is set to 'true', an additional 2 processing thread will deal with processing
* callbacks, thus mitigating the issue.
* @param maxOutstandingTxns
* the number of transactions the client application may push against a specific
* connection before getting blocked on back-pressure. By default the connection
* allows 3,000 open transactions before preventing the client from posting more
* work, thus preventing server fire-hosing. In some cases however, with very fast,
* small transactions, this limit can be raised.
* @param reconnectOnConnectionLoss
* Attempts to reconnect to a node with retry after connection loss
* @return the client connection object the caller should use to post requests.
*/
public static JDBC4ClientConnection get(String[] servers, String user,
String password, boolean isHeavyWeight, int maxOutstandingTxns, boolean reconnectOnConnectionLoss) throws Exception {
return get(servers, user, password, isHeavyWeight, maxOutstandingTxns, reconnectOnConnectionLoss, null);
}
/**
* Gets a client connection to the given VoltDB server(s).
*
* @param servers
* the list of VoltDB servers to connect to.
* @param port
* the VoltDB native protocol port to connect to (usually 21212).
* @param user
* the user name to use when connecting to the server(s).
* @param password
* the password to use when connecting to the server(s).
* @param isHeavyWeight
* the flag indicating callback processes on this connection will be heavy (long
* running callbacks). By default the connection only allocates one background
* processing thread to process callbacks. If those callbacks run for a long time,
* the network stack can get clogged with pending responses that have yet to be
* processed, at which point the server will disconnect the application, thinking it
* died and is not reading responses as fast as it is pushing requests. When the flag
* is set to 'true', an additional 2 processing thread will deal with processing
* callbacks, thus mitigating the issue.
* @param maxOutstandingTxns
* the number of transactions the client application may push against a specific
* connection before getting blocked on back-pressure. By default the connection
* allows 3,000 open transactions before preventing the client from posting more
* work, thus preventing server fire-hosing. In some cases however, with very fast,
* small transactions, this limit can be raised.
* @param reconnectOnConnectionLoss
* Attempts to reconnect to a node with retry after connection loss
* @param sslConfig
* Contains properties - trust store path and password, key store path and password,
* used for connecting with server over SSL. For unencrypted connection, passed in ssl
* config is null
* @return the client connection object the caller should use to post requests.
* @see #get(String servers, int port, String user, String password, boolean isHeavyWeight, int
* maxOutstandingTxns, reconnectOnConnectionLoss)
*/
public static JDBC4ClientConnection get(String[] servers, String user, String password, boolean isHeavyWeight,
int maxOutstandingTxns, boolean reconnectOnConnectionLoss, SSLConfiguration.SslConfig sslConfig) throws Exception {
String clientConnectionKeyBase = getClientConnectionKeyBase(servers, user, password,
isHeavyWeight, maxOutstandingTxns, reconnectOnConnectionLoss);
String clientConnectionKey = clientConnectionKeyBase;
synchronized (ClientConnections) {
if (!ClientConnections.containsKey(clientConnectionKey))
ClientConnections.put(clientConnectionKey, new JDBC4ClientConnection(
clientConnectionKeyBase, clientConnectionKey, servers, user,
password, isHeavyWeight, maxOutstandingTxns, reconnectOnConnectionLoss,
sslConfig));
return ClientConnections.get(clientConnectionKey).use();
}
}
/**
* Releases a connection. This method (or connection.close() must be called by the user thread
* once the connection is no longer needed to release it back into the pool where other threads
* can pick it up. Failure to do so will cause a memory leak as more and more new connections
* will be created, never to be released and reused. The pool itself will run the logic to
* decide whether the actual underlying connection should be kept alive (if other threads are
* using it), or closed for good (if the calling thread was the last user of that connection).
*
* @param connection
* the connection to release back into the pool.
*/
public static void dispose(JDBC4ClientConnection connection) {
synchronized (ClientConnections) {
connection.dispose();
if (connection.users == 0)
ClientConnections.remove(connection.key);
}
}
/**
* Generates a hash/key for a connection based on the given list of connection parameters
*
* @param servers
* the list of VoltDB servers to connect to in comma separated hostname[:port] format.
* @param user
* the user name to use when connecting to the server(s).
* @param password
* the password to use when connecting to the server(s).
* @param isHeavyWeight
* the flag indicating callback processes on this connection will be heavy (long
* running callbacks).
* @param maxOutstandingTxns
* the number of transactions the client application may push against a specific
* connection before getting blocked on back-pressure.
* @param reconnectOnConnectionLoss
* Attempts to reconnect to a node with retry after connection loss
* @return the base hash/key for the given connection parameter
*/
private static String getClientConnectionKeyBase(String[] servers, String user,
String password, boolean isHeavyWeight, int maxOutstandingTxns, boolean reconnectOnConnectionLoss) {
String clientConnectionKeyBase = user + ":" + password + "@";
for (int i = 0; i < servers.length; i++)
clientConnectionKeyBase += servers[i].trim() + ",";
clientConnectionKeyBase += "{"
+ Boolean.toString(isHeavyWeight) + ":" + Integer.toString(maxOutstandingTxns)
+ ":" + Boolean.toString(reconnectOnConnectionLoss) + "}";
return clientConnectionKeyBase;
}
}