I wanted to integrate tomcat jdbc connection pool with HA-JDBC. From the ha-jdbc documentation I read, I understand that datasource properties could be set by calling DataSourceDatabase.setProperty(key, value) method. Since tomcat jdbc pool configuration involves an object inside an object, I am looking for some help on how do I configure tomcat-jdbc-pool with ha-jdbc.
Here is a sample configuration code for tomcat jdbc pool
PoolConfiguration poolConfig = new PoolProperties();
poolConfig.setName(name);
poolConfig.setDataSource(getOracleDataSource(config));
poolConfig.setUsername(config.getUser());
poolConfig.setPassword(config.getPassword());
poolConfig.setMaxActive(config.getMaxPoolSize());
poolConfig.setMinIdle(config.getMinPoolSize());
poolConfig.setInitialSize(config.getMinPoolSize());
poolConfig.setMinEvictableIdleTimeMillis(config.getMaxIdleTime() * 1000);
poolConfig.setTestWhileIdle(false);
poolConfig.setTestOnBorrow(true);
poolConfig.setValidationQuery("select 1 from dual");
poolConfig.setInitSQL(config.getInitSql());
poolConfig.setJdbcInterceptors("ConnectionState;StatementFinalizer");
org.apache.tomcat.jdbc.pool.DataSource tomcatDataSource =
new org.apache.tomcat.jdbc.pool.DataSource();
tomcatDataSource.setPoolProperties(poolConfig);
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
try {
tomcatDataSource.createPool();
mBeanServer.registerMBean(tomcatDataSource.getPool().getJmxPool(), getObjectName(name));
} catch (Exception e) {
throw new RuntimeException("Error registering the connection pool data source", e);
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You have two options. Either you can configure tomcat's connection pool to access HA-JDBC's datasource (i.e. a pool of HA-JDBC connections), or you can configure HA-JDBC to access individual connection pools, one per database, where each database is a org.apache.tomcat.jdbc.pool.DataSource.
Given your code fragments, you appear to be configuring both your connection pool and HA-JDBC programmatically, so I'll use similar conventions.
The former method is fairly straightforward. I'm assuming that you're configuring everything programatically. This makes things easy. Your pool config would reference the HA-JDBC datasource.
e.g.
net.sf.hajdbc.sql.DataSource ds = new net.sf.hajdbc.sql.DataSource();
ds.setConfigurationFactory(...);
ds.setCluster("cluster");
PoolConfiguration config = new PoolProperties();
config.setDataSource(ds);
The rest of the configuration looks the same as above.
To configure HA-JDBC using the latter method, you would create 2 tomcat datasources, each with a pool config that references the Oracle datasource.
e.g.
I seem to remember that with hajdbc on top of some connection pools there
was an issue with hajdbc getting into a deadlock is that still the case.
You have two options. Either you can configure tomcat's connection pool to
access HA-JDBC's datasource (i.e. a pool of HA-JDBC connections), or you
can configure HA-JDBC to access individual connection pools, one per
database, where each database is a org.apache.tomcat.jdbc.pool.DataSource.
Given your code fragments, you appear to be configuring both your
connection pool and HA-JDBC programmatically, so I'll use similar
conventions.
The former method is fairly straightforward. I'm assuming that you're
configuring everything programatically. This makes things easy. Your pool
config would reference the HA-JDBC datasource.
e.g.
net.sf.hajdbc.sql.DataSource ds = new
net.sf.hajdbc.sql.DataSource();ds.setConfigurationFactory(...);ds.setCluster("cluster");PoolConfiguration
config = new PoolProperties();config.setDataSource(ds);
The rest of the configuration looks the same as above.
To configure HA-JDBC using the latter method, you would create 2 tomcat
datasources, each with a pool config that references the Oracle datasource.
e.g.
Bind each of these to JNDI, then reference them in your HA-JDBC
DataSourceDatabase by jndi name.
e.g.
DataSourceDatabase db1 = new DataSourceDatabase();
db1.setLocation("java:comp/env/ds/tomcatDS1");
DataSourceDatabase db2 = new DataSourceDatabase();
db2.setLocation("java:comp/env/ds/tomcatDS2");
If I recall correctly, the deadlocking was because the JDK DriverManager.getConnection(...) method was synchronized. As of Java 1.6, this is no longer the case.
I general, I recommend configuring HA-JDBC on top of your connection pool (i.e. as a cluster of connection pools, instead of a single connection pool of HA-JDBC connections). In this configuration, it is important to enable testOnBorrow to prevent a stale connection in the pool from triggering an unnecessary database deactivation.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
No the problem was that with a round robin setup you could empty both
connection pools and then threads were deadlocked waiting for a connection
to become available.
If I recall correctly, the deadlocking was because the JDK
DriverManager.getConnection(...) method was synchronized. As of Java 1.6,
this is no longer the case.
I general, I recommend configuring HA-JDBC on top of your connection pool
(i.e. as a cluster of connection pools, instead of a single connection pool
of HA-JDBC connections). In this configuration, it is important to enable
testOnBorrow to prevent a stale connection in the pool from triggering an
unnecessary database deactivation.
I didn't understand the reason why you mention that using HA-JDBC on top of tomcat connection pool (which means the second option from your original mail). The point about testOnBorrow would apply to the first option if I understand it correctly.
One issue I see with the second option is that I need to set up datasources using JNDI which could be an issue since we create datasource at runtime in our application (connecting to multiple db servers).
I tried implementing the first option of using the tomcat over the ha-jdbc cluster. But it fails with invalid username/password error since ha-jdbc tries to connect using the cluster data source. The code snippet is as below.
The authentication information defined by your DataSourceDatabase instances is not used when your application attempts to obtain a connection from the connection pool. The reason for this has to do with the different authorization requirements. The user defined by the DataSourceDatabase should have administrative/superuser privileges on the database (e.g. be able to create/drop schemas/tables, constraints, indexes, etc.) whereas the database user used by your application will typically have a subset of these privileges (e.g. insert/update/delete/select). Consequently, you will need to configure your connection pool with the appropriate username/password.
e.g.
When tomcat's connection pool attempts to create a connection to your actual databases, it will use the username/password defined above. Anytime HA-JDBC needs to access your database on its own (e.g. for database synchronization, when determining the initial cluster state, etc.) it will use the username/password defined in your DatabaseClusterConfiguration.
N.B. While the admin username/password can be different on each database, the username/password used by your application must be the same on each database.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ok. It works with your suggestion of setting the username/password in the tomcat connection pool configuration.
Do you see any other config options which should be taken care off when I configure with the first option i.e. tomcat connection pool over ha-jdbc cluster. I have made a note of testOnBorrow setting to avoid stale connections.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
One downside I realized with the first option is that the tomcat pool could at a time contain connections to different servers. DML operations could be directed to any of the db-servers at runtime. Any replication mechanism used external to ha-jdbc to synchronize the databases in the cluster would have to account for this i.e. multi-directional replication.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Actually, with the 1st option (a pool of HA-JDBC connections), your pool will always contain connections to each database. During runtime, HA-JDBC will always direct DML operations to all databases (hence the need to have connections to each database).
As I explained in another thread, HA-JDBC was not designed to be used in conjunction with an external replication mechanism. If you're looking for a simple connection failover mechanism, I listed a few in the other thread.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The scenario was very heavy load which was using all of the db connections.
Two threads would take the last connection from two pools and then block
waiting to get a connection from the other pool which never got freed up.
Hence the deadlock.
I seem to recall the solution was to make the choosing of the first pool
predictable.
I wanted to integrate tomcat jdbc connection pool with HA-JDBC. From the ha-jdbc documentation I read, I understand that datasource properties could be set by calling DataSourceDatabase.setProperty(key, value) method. Since tomcat jdbc pool configuration involves an object inside an object, I am looking for some help on how do I configure tomcat-jdbc-pool with ha-jdbc.
Here is a sample configuration code for tomcat jdbc pool
Thanks.
You have two options. Either you can configure tomcat's connection pool to access HA-JDBC's datasource (i.e. a pool of HA-JDBC connections), or you can configure HA-JDBC to access individual connection pools, one per database, where each database is a org.apache.tomcat.jdbc.pool.DataSource.
Given your code fragments, you appear to be configuring both your connection pool and HA-JDBC programmatically, so I'll use similar conventions.
The former method is fairly straightforward. I'm assuming that you're configuring everything programatically. This makes things easy. Your pool config would reference the HA-JDBC datasource.
e.g.
The rest of the configuration looks the same as above.
To configure HA-JDBC using the latter method, you would create 2 tomcat datasources, each with a pool config that references the Oracle datasource.
e.g.
Bind each of these to JNDI, then reference them in your HA-JDBC DataSourceDatabase by jndi name.
e.g.
Last edit: Paul Ferraro 2013-03-15
I seem to remember that with hajdbc on top of some connection pools there
was an issue with hajdbc getting into a deadlock is that still the case.
You have two options. Either you can configure tomcat's connection pool to
access HA-JDBC's datasource (i.e. a pool of HA-JDBC connections), or you
can configure HA-JDBC to access individual connection pools, one per
database, where each database is a org.apache.tomcat.jdbc.pool.DataSource.
Given your code fragments, you appear to be configuring both your
connection pool and HA-JDBC programmatically, so I'll use similar
conventions.
The former method is fairly straightforward. I'm assuming that you're
configuring everything programatically. This makes things easy. Your pool
config would reference the HA-JDBC datasource.
e.g.
net.sf.hajdbc.sql.DataSource ds = new
net.sf.hajdbc.sql.DataSource();ds.setConfigurationFactory(...);ds.setCluster("cluster");PoolConfiguration
config = new PoolProperties();config.setDataSource(ds);
The rest of the configuration looks the same as above.
To configure HA-JDBC using the latter method, you would create 2 tomcat
datasources, each with a pool config that references the Oracle datasource.
e.g.
org.apache.tomcat.jdbc.pool.DataSource tomcatDS1 =
...;org.apache.tomcat.jdbc.pool.DataSource tomcatDS2 = ...;
Bind each of these to JNDI, then reference them in your HA-JDBC
DataSourceDatabase by jndi name.
e.g.
DataSourceDatabase db1 = new DataSourceDatabase();
db1.setLocation("java:comp/env/ds/tomcatDS1");
DataSourceDatabase db2 = new DataSourceDatabase();
db2.setLocation("java:comp/env/ds/tomcatDS2");
Using in a connection pool with
ha-jdbchttps://sourceforge.net/p/ha-jdbc/discussion/383397/thread/aa333c4f/?limit=25#b3e0
Sent from sourceforge.net because you indicated interest in
https://sourceforge.net/p/ha-jdbc/discussion/383397/
To unsubscribe from further messages, please visit
https://sourceforge.net/auth/prefs/
If I recall correctly, the deadlocking was because the JDK DriverManager.getConnection(...) method was synchronized. As of Java 1.6, this is no longer the case.
I general, I recommend configuring HA-JDBC on top of your connection pool (i.e. as a cluster of connection pools, instead of a single connection pool of HA-JDBC connections). In this configuration, it is important to enable testOnBorrow to prevent a stale connection in the pool from triggering an unnecessary database deactivation.
No the problem was that with a round robin setup you could empty both
connection pools and then threads were deadlocked waiting for a connection
to become available.
On 16 Mar 2013 16:48, "Paul Ferraro" ferraro@users.sf.net wrote:
I didn't understand the reason why you mention that using HA-JDBC on top of tomcat connection pool (which means the second option from your original mail). The point about testOnBorrow would apply to the first option if I understand it correctly.
One issue I see with the second option is that I need to set up datasources using JNDI which could be an issue since we create datasource at runtime in our application (connecting to multiple db servers).
I tried implementing the first option of using the tomcat over the ha-jdbc cluster. But it fails with invalid username/password error since ha-jdbc tries to connect using the cluster data source. The code snippet is as below.
Kindly let me know your inputs.
Thanks.
The authentication information defined by your DataSourceDatabase instances is not used when your application attempts to obtain a connection from the connection pool. The reason for this has to do with the different authorization requirements. The user defined by the DataSourceDatabase should have administrative/superuser privileges on the database (e.g. be able to create/drop schemas/tables, constraints, indexes, etc.) whereas the database user used by your application will typically have a subset of these privileges (e.g. insert/update/delete/select). Consequently, you will need to configure your connection pool with the appropriate username/password.
e.g.
When tomcat's connection pool attempts to create a connection to your actual databases, it will use the username/password defined above. Anytime HA-JDBC needs to access your database on its own (e.g. for database synchronization, when determining the initial cluster state, etc.) it will use the username/password defined in your DatabaseClusterConfiguration.
N.B. While the admin username/password can be different on each database, the username/password used by your application must be the same on each database.
Ok. It works with your suggestion of setting the username/password in the tomcat connection pool configuration.
Do you see any other config options which should be taken care off when I configure with the first option i.e. tomcat connection pool over ha-jdbc cluster. I have made a note of testOnBorrow setting to avoid stale connections.
One downside I realized with the first option is that the tomcat pool could at a time contain connections to different servers. DML operations could be directed to any of the db-servers at runtime. Any replication mechanism used external to ha-jdbc to synchronize the databases in the cluster would have to account for this i.e. multi-directional replication.
Actually, with the 1st option (a pool of HA-JDBC connections), your pool will always contain connections to each database. During runtime, HA-JDBC will always direct DML operations to all databases (hence the need to have connections to each database).
As I explained in another thread, HA-JDBC was not designed to be used in conjunction with an external replication mechanism. If you're looking for a simple connection failover mechanism, I listed a few in the other thread.
Refresh my memory... Exactly which threads were deadlocking? Why would the connection pools get emptied?
The scenario was very heavy load which was using all of the db connections.
Two threads would take the last connection from two pools and then block
waiting to get a connection from the other pool which never got freed up.
Hence the deadlock.
I seem to recall the solution was to make the choosing of the first pool
predictable.
Kev
On 16 Mar 2013 18:10, "Paul Ferraro" ferraro@users.sf.net wrote:
OK - I recall the scenario you described. This was fixed in the 2.1 branch (master) a while ago.
Cool.
On 16 Mar 2013 19:22, "Paul Ferraro" ferraro@users.sf.net wrote: