简体   繁体   中英

Database Connection Timeout Tomcat7

Where can I set timeout for getting database connection: javax.sql.DataSource.getConnection() in tomcat 7 application server ?

Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup(DBManagerConstants.CONTEXT_NAME);
DataSource ds = (DataSource) envContext.lookup(DBManagerConstants.DS_NAME);
conn = ds.getConnection();

I have java web application on Tomcat 7 which connection to Oracle database. One day our Net Admin changed something in Firewall after this application was unable to get database connection but still there was no timeout and error. After removing this change(after 1,5 hours) in Firewall application continued to work as if nothing happened. These delayed connections finished all operations successfully.

This is my datasource

<Context>
     <Resource
        name="jdbc/pds"
        auth="Container"
        driverClassName="oracle.jdbc.driver.OracleDriver"
        factory="our.encryptor.EncryptedDataSourceFactory"
        logAbandoned="true"
        maxActive="30"
        maxIdle="10"
        maxWait="1000"
        password="my_password"
        removeAbandoned="true"
        removeAbandonedTimeout="60"
        type="javax.sql.DataSource"
        url="jdbc:oracle:thin:@127.0.0.1:8080:SID"
        username="my_user"
        accessToUnderlyingConnectionAllowed="true"
    validationQuery="select 1 from dual" />
</Context>

Connections are NOT persistent physical links

I think some of the confusion you and some of the other commenters might be having is that when a client terminates a connection to the database the database doesn't know the connection is gone because its not an actual ongoing physical link like the name would imply. A "database connection" is more of an identifier of a foreign IP address the database is willing to accept and send packets to and from. Being "connected" just means the server knows the client and is waiting for data but if the client blows up or goes away the server does not know. For this reason, on databases stale connections have to be manually purged from time to time.

If a client attempts to connect with your database a new connection is created. Now if that client goes away the connection is still on the database because the client going offline doesn't send a "kill connection" or anything like that sort. Now if you put up a firewall or something like that the connections will remain valid. The only time an error will occur is if the client returns and attempts to speak while the firewall is up but if you bring down the firewall and the client returns 9 hours later, so long as the DB has not trashed connection and neither has the client, then everything will pick up where it left off "as if nothing happed" to quote the OP.

You can test this out by running a database locally and trying connecting to it. Look at the connections console and you'll see yourself. Terminate whatever client your using to make connections to the db and check the admin console and you will see the database is still waiting even though your client is not there. The database purges those connections itself.

Connection Pool

Connection pools let your app reuse the same connection for the work it needs to do but if you haven't communicated with the database in a long time, through your app, the connection can go stale and be evicted by the DB and so connection pools have configuration parameters for what to do if you attempt to retrieve a stale connection.

From the OPs connection pool parameters below the validationQuery field is something that is run periodically on your app to periodically check if the connections inside the pool are still valid. All of this is because "Connections" are NOT connections in the physical sense.

<Context>
     <Resource
        name="jdbc/pds"
        auth="Container"
        driverClassName="oracle.jdbc.driver.OracleDriver"
        factory="our.encryptor.EncryptedDataSourceFactory"
        logAbandoned="true"
        maxActive="30"
        maxIdle="10"
        maxWait="1000"
        password="my_password"
        removeAbandoned="true"
        removeAbandonedTimeout="60"
        type="javax.sql.DataSource"
        url="jdbc:oracle:thin:@127.0.0.1:8080:SID"
        username="my_user"
        accessToUnderlyingConnectionAllowed="true"
    validationQuery="select 1 from dual" />
</Context>

You can use a fully qualified connection URL and specify CONNECT_TIMEOUT. Please note that you can use your SCAN IP or service name in this connection URL. You cannot use SID.

jdbc:oracle:thin:@(DESCRIPTION= (CONNECT_TIMEOUT=10)(RETRY_COUNT=3)
(ADDRESS_LIST= (LOAD_BALANCE=on)(FAILOVER=ON)
(ADDRESS=(PROTOCOL=tcp)(HOST=sales1-scan)(PORT=1521))
(ADDRESS=(PROTOCOL=tcp)(HOST=sales2-scan)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME= salesservice.example.com)))

(2) There is a Property in OracleConnection.CONNECTION_PROPERTY_THIN_NET_CONNECT_TIMEOUT which can also be used to set this property. Refer to the Javadoc for more details. http://docs.oracle.com/database/121/JAJDB/toc.htm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM