I experienced an outage with my application the other day and I need to understand how to avoid this in the future.
We have a Java based web application running on Tomcat 7. The application connected to several different data sources including an Oracle database.
Here are the details, the Oracle database server went down and had to be rebooted. My simple understanding tells me this would have severed the application's connections to the database, and in fact the users reported errors in the application.
The Oracle data source is setup in Tomcat's sever.xml as a GlobalNaming Resource:
<Resource name="datasource"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
....
initialSize="4"
minIdle="2"
maxIdle="8"
maxActive="8"
maxAge="28800000"
maxWait="30000"
testOnBorrow="false"
testOnReturn="false"
testWhileIdle="false"
validationQuery="SELECT 1 FROM dual"
validationQueryTimeout="10"
validationInterval="600000"
timeBetweenEvictionRunsMillis="60000"
minEvictableIdleTimeMillis="900000"
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"
jmxEnabled="true" />
So here is what I understand regarding connection validation.
Connections are not validated while idle (testWhileIdle = false), when borrowed (testOnBorrow = false), when returned (testOnReturn = false)
The PoolSweeper is enabled because timeBetweenEvictionRunsMillis > 0, removeAbandoned is true, and removeAbandonedTimeout > 0
What confuses me is the inclusion of the validation query and the validationInterval > 0. Since all of the tests are disabled, does the pool sweeper then use the validation query to check the connections? Or is the validation query irrelevant?
So when the database server went down, I believe the connection pool would not have tried to reestablish connections because there are no validation tests enabled. In my opinion, had testOnBorrow been enabled then when the database server came back up valid connections would have been established and the web application (meaning tomcat) would not have required a restart.
Do I have a correct understanding of how connection validation works?
Let us take a look at the relevant part of your configuration to avoid invalid connections in your pool.
maxAge="28800000"
The connections regardless if valid or not will be kept open for 8 hrs. After 8 hrs the connection is closed and a new connection will be established if requested and no free connection is available in the pool. [1]
testOnBorrow="false"
testOnReturn="false"
testWhileIdle="false"
A connection in the pool will not be tested if it is valid when or while it's been borrowed, returned and idle. [1]
validationInterval="600000"
This property has no effect since all connection tests are set to false. This interval defines when a connection is needed to be tested. In your example, a connection will be tested every 10 minutes in case a test property would be set to true. [1]
An invalid connection can stay open up to 8 hrs with your current configuration. To enable validation tests of opened connections you have to set at least one test property (testOnBorrow, testOnReturn, testWhileIdle) to true.
Please note, in case of validationInterval="600000" a connection test/validation will be done every 10 minutes. So, an invalid connection could be up to 10 minutes available in the pool regardless which test property is set.
For more information about the individual properties please take a look at [1]: Apache Tomcat 7: The Tomcat JDBC Connection Pool.
you must lower the maxAge="28800000" parameter, in addition to this your instance crashes due to application errors and you should use jdbc interceptor
Related
I added setMaxActive(8) on org.apache.tomcat.jdbc.pool.PoolProperties. Every time the DB restarts, the application is unusable because the established connections remain. I get the following error:
org.postgresql.util.PSQLException: This connection has been closed
I've tried using some other settings on the pool to no avail...
Thank you for help!
Use the validationQuery property which will check if the connection is valid before returning the connection.
Ref: Tomcat 6 JDBC Connection Pool
This property is available on latest tomcat versions.
Look at this link:
Postgres connection has been closed error in Spring Boot
Very valid question and this problem is usually faced by many. The
exception generally occurs, when network connection is lost between
pool and database (most of the time due to restart). Looking at the
stack trace you have specified, it is quite clear that you are using
jdbc pool to get the connection. JDBC pool has options to fine-tune
various connection pool settings and log details about whats going on
inside pool.
You can refer to to detailed Apache documentation on pool
configuration to specify abandon timeout
Check for removeAbandoned, removeAbandonedTimeout, logAbandoned parameters
Additionally you can make use of additional properties to further
tighten the validation
Use testXXX and validationQuery for connection validity.
My own $0.02: use these two parameters:
validationQuery=<TEST SQL>
testOnBorrow=true
I have a mysql database configured with a max_connections value of 150. I also have a Java 6 web application running in Tomcat 5.5 configured with the following setup:
<Resource name="jdbc/myDB"
type="javax.sql.DataSource"
driver="com.mysql.jdbc.Driver"
username="username"
password="password"
maxActive="100"
maxIdle="100"
maxWait="-1"
removeAbandoned="true"
removeAbandonedTimeout="300"
logAbandoned="true"
url="jdbc:mysql://localhost:3306/myDB?autoreconnect=true"
validationQuery="SELECT 1" />
This application is not using any 3rd party framework just basic java servlets. I have a bug in some code in the java app that is not properly releasing opened mysql connections from the pool. I am working on identifying and fixing these. But in the meantime I need to figure out why at most there is only 25 connections being allowed to mysql. After these 25 connections are used up, the application becomes unresponsive.
Can someone please help me figure out why both mysql and tomcat are configured for 100+ connections but it is only allowing 25 at a time?
Tomcat JDBC Connection Pool
What connection pool do you use?
Do you use the Tomcat JDBC Connection Pool, rather than the Apache Commons pool? It has properties to detect connection leaks or abandon connection that are open for a long time than the configured timeout.
MySQL's max_connections was set to 150 but the max_user_connections was set to 25 which was the limiting factor here. I removed this setting from my.cnf to restore it to the default value of unlimited.
I seem to have stumbled across a weird behavior with tomcat 7 and connection pooling...
In my app, I have the following 3 data sources - connecting to the same database, but different services ( and are the same across all 3)
jdbc:sybase:Tds:<db_ip_address>:<db_port>/service1
jdbc:sybase:Tds:<db_ip_address>:<db_port>/service2
jdbc:sybase:Tds:<db_ip_address>:<db_port>/service3
In my context.xml, I have the 3 data sources listed as a separate resource as usual, with all neccessary options set, including
<Resource
name="jdbc/dbDataSource1"
type="javax.sql.DataSource"
driverClassName="com.sybase.jdbc3.jdbc.SybDriver"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
maxActive="20"
initialSize="1"
minIdle="5"
maxIdle="10"
<Resource
name="jdbc/dbDataSource2"
<!-- Rest is same as above -->
<Resource
name="jdbc/dbDataSource3"
<!-- Rest is same as above -->
What I have noticed is, because the 3 data sources connect to the same database, tomcat only seems to be creating and using one connection pool and sharing between all 3. This can be seen at startup, where if I change initialSize to say 10, the first 2 data sources are created no problem - on the 3rd, I get an exception saying
java.sql.SQLException: JZ00L: Login failed.
Examine the SQLWarnings chained to this exception for the reason(s).
Am I missing something obvious here on how to set up the connection pool? I have looked at the tomcat documentation and stuff related to global connection pools, however from what I can gather this seems to be related to sharing the connections between multiple apps?
Any help is much appreciated!
Indeed seems to be too many idle connection. Try to increase the idle Connection properties or check whether you are closing all the opened connection.
Please refer to this link
We use OpenEJB on Tomcat (used to run on JBoss, Weblogic, etc.). While running load tests we experience significant performance problems with handling JMS messages (queues). Problem was localized to blocking on database connection pool getting or releasing connection to the pool. Blocking prevented concurrent MDB instances (threads) from running hence performance suffered 10-fold and worse. The same code used to run on application servers (with their respective connection pool implementations) with no blocking at all.
Example of thread blocked:
Name: JMS Resource Adapter-worker-23
State: BLOCKED on org.apache.commons.pool.impl.GenericObjectPool#1ea6b4a owned by: JMS Resource Adapter-worker-19
Total blocked: 18,426 Total waited: 0
Stack trace:
org.apache.commons.pool.impl.GenericObjectPool.returnObject(GenericObjectPool.java:916)
org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:91)
- locked org.apache.commons.dbcp.PoolableConnection#1bcba8
org.apache.commons.dbcp.managed.ManagedConnection.close(ManagedConnection.java:147)
com.xxxxx.persistence.DbHelper.closeConnection(DbHelper.java:290)
....
Couple of questions.
I am almost certain that some transactional attributes and properties contribute to this blocking, but MDBs are defined as non-transactional (we use both annotations and ejb-jar.xml). Some EJBs do use container-managed transactions though (and we can observe blocking there as well). Are there any DBCP configurations that may fix blocking?
Is DBCP connection pool implementation replaceable in OpenEJB? How easy (difficult) to replace it with another library?
Just in case this is how we define data source in OpenEJB (openejb.xml):
<Resource id="MyDataSource" type="DataSource">
JdbcDriver oracle.jdbc.driver.OracleDriver
JdbcUrl ${oracle.jdbc}
UserName ${oracle.user}
Password ${oracle.password}
JtaManaged true
InitialSize 5
MaxActive 30
ValidationQuery SELECT 1 FROM DUAL
TestOnBorrow true
</Resource>
My 2 cts...
1 - Are there any DBCP configurations that
may fix blocking?
Although I cannot see it in the doc, I think there should also be a setting attribute named 'WhenExaustedAction' in the Resource node that could take a value "GROW" (value 2) as opposed to "BLOCK" (value 1) or "FAIL" (value 0). This comes straight from the Pools common.
Both Hibernate and Cayenne do use this DBCP setting. Don't know about OpenEJB though.
No need to say that this would work only if all connections are dutifully closed of course (which is sometimes hard to guarantee).
Then you could probably see through JMX how many connections you need at peak activity time and you could then set the maxActive to a higher value evolved from these measures.
2 - Is DBCP connection pool implementation
replaceable in OpenEJB? How easy
(difficult) to replace it with another
library?
Sorry no idea. Would imagine yes. Or possibly DBCP allows another connection pool manager.
UPDATE: Just had a look in the code and it seems DBCP is the only option for connection pooling.
Incidentally I've seen that the whenExhaustedAction settings. is not supported by openejb.xml.
There would however, still be one option left, since you are using an Oracle Database.
One thing you could try is to use Oracle implicit connection caching (assuming version 10g) and leave DBCP with an arbitrary "sufficient" amount of connections.
To do so, you would need to configure in the openejb.xml resource block, ConnectionProperties properties and use Oracle JDBC connection properties. That is connectionCachingEnabled=true and at least connectionCacheName and connectionCacheProperties. In this way I would lure DBCP into believing it's doing the real job and actually using Oracle's pooling mechanism. That would also mean taking little risks with DBCP and thereby a more liberal sizing of the maxActive setting.
Resolved issue with dbcp blocking by changing pool configuration (openejb.xml):
TestOnBorrow false
Thank you, Andy, from OpenEJB team!
I have a tomcat instance setup but the database connection I have configured in context.xml keeps dying after periods of inactivity.
When I check the logs I get the following error:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
The last packet successfully received from the server was68051 seconds
ago. The last packet sent successfully to the server was 68051 seconds
ago, which is longer than the server configured value of
'wait_timeout'. You should consider either expiring and/or testing
connection validity before use in your application, increasing the
server configured values for client timeouts, or using the Connector/J
connection property 'autoReconnect=true' to avoid this problem.
Here is the configuration in context.xml:
<Resource name="dataSourceName"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="username"
password="********"
removeAbandoned = "true"
logAbandoned = "true"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/databasename?autoReconnect=true&useEncoding=true&characterEncoding=UTF-8" />
I am using autoReconnect=true like the error says to do, but the connection keeps dying. I have never seen this happen before.
I have also verified that all database connections are being closed properly.
Tomcat Documentation
DBCP uses the Jakarta-Commons Database Connection Pool. It relies on number of Jakarta-Commons components:
* Jakarta-Commons DBCP
* Jakarta-Commons Collections
* Jakarta-Commons Pool
This attribute may help you out.
removeAbandonedTimeout="60"
I'm using the same connection pooling stuff and I'm setting these properties to prevent the same thing it's just not configured through tomcat.
But if the first thing doesn't work try these.
testWhileIdle=true
timeBetweenEvictionRunsMillis=300000
Just to clarify what is actually causing this. MySQL by default terminates open connections after 8 hours of inactivity. However the database connection pool will retain connections for longer than that.
So by setting timeBetweenEvictionRunsMillis=300000 you are instructing the connection pool to run through connections and evict and close idle ones every 5 minutes.
The removeAbandoned option is deprecated as of DBCP 1.2 (though still present in the 1.3 branch). Here's a non-official explanation.
I do not know whether the above answer does basically the same thing, but some of our systems use the DB connection about once a week and I've seen that we provide a -Otimeout flag or something of that sort to mysql to set the connection timeout.