2015-12-21 2 views
2

J'utilise c3p0 pour mon pool de connexion. Le ComboPooledDataSource que j'utilise est configuré comme ci-dessous.Quelle est la meilleure façon de fermer les connexions et d'éviter les sessions inactives lors de l'utilisation de C3P0?

@Bean 
public DataSource dataSource() { 

    ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    dataSource.setUser("user"); 
    dataSource.setDriverClass("oracle.jdbc.OracleDriver"); 
    dataSource.setJdbcUrl("test"); 
    dataSource.setPassword("test"); 
    dataSource.setMinPoolSize("10"); 
    dataSource.setMaxPoolSize("20"); 
    dataSource.setMaxStatements("100"); 
    return dataSource; 
} 

Je suis confronté à des problèmes avec ceci. J'ai des avertissements que cela pourrait fuir les connexions. Également l'erreur ci-dessous de temps en temps,

comme toutes les connexions sont utilisées.

java.sql.SQLException: Io exception: Got minus one from a read call 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255) 
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387) 
    at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:439) 
    at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165) 
    at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35) 
    at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801) 
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135) 
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection 

(WrapperConnectionPoolDataSource.java:182) 
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection 

(WrapperConnectionPoolDataSource.java:171) 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource 

(C3P0PooledConnectionPool.java:137) 
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014) 
    at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32) 
    at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810) 
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) 

Et à partir de la base de données DB, pouvait voir près de 290 connexions inactives. J'ai environ 8 applications déployées dans deux serveurs,

se connectant au même DB.

Mes requêtes sont

  1. Comment puis-je assurer que les connexions sont fermées e et de ne pas avoir ces nombreuses connexions inactives?
  2. La configuration du temps d'inactivité et du délai d'attente permet-elle de résoudre ce problème? Que se passerait-il si le serveur est arrêté/si Tomcat est arrêté, les connexions resteront-elles ouvertes?
  3. Les connexions sont principalement utilisées lors du démarrage pour charger le cache, donc est-il possible de ne plus utiliser ces connexions par la suite?
  4. Que faire pour les connexions inactives existantes?

Répondre

6
  • Compte tenu maxPoolSize de 20 et huit déploiements, vous devriez vous attendre à voir jusqu'à 180 connexions qui peuvent être inactives si l'application a connu des périodes de trafic qui a maintenant disparu. Vous n'avez rien configuré pour encourager une réduction rapide de vos pools: définissez maxIdleTime et/ou maxIdleTimeExcessConnections et/ou maxConnectionAge.
  • Vous devriez probablement indiquer à Spring comment fermer le DataSource que vous avez défini. Utilisez @Bean(destroyMethodName="close") au lieu de @Bean seul au dessus de votre méthode dataSource().
  • Vous n'avez configuré aucun type de test de connexion, de sorte que même les connexions rompues peuvent rester dans le pool. S'il vous plaît voir Simple Advice On Connection Testing.
  • Si le problème était une fuite de connexion, les clients finiraient par se bloquer indéfiniment, car le pool serait hors des connexions à extraire, mais aurait déjà atteint maxPoolSize, et ne pourrait donc pas en acquérir davantage à partir du SGBD. Est-ce que vous voyez des clients se bloquer comme ça?
  • La façon dont vous évitez les fuites de connexion est, après Java7, de toujours acquérir des connexions à partir de votre DataSource via try-with-resources. Autrement dit, l'utilisation ...

    try (Connection conn = myDataSource.getConnection()) { 
        ... 
    } 
    

    plutôt que d'appeler getConnection() dans une méthode qui pourrait jeter une exception ou dans un bloc try. Si vous utilisez une ancienne version de Java, vous devez utiliser l'idiome de nettoyage de ressources robuste, c'est-à-dire acquérir la connexion dans un bloc try et être sûr que conn.close() est toujours fermé dans le bloc finally, sans tenir compte des autres échecs dans le enfin bloquer. Si vous ne travaillez pas directement avec le DataSource, mais laissez les utilitaires Spring fonctionner avec, espérons que ces utilitaires font ce qu'il faut.Mais vous devriez poster tout avertissement que vous recevez qui vous met en garde contre des fuites de connexion potentielles!

  • Si votre application a peu d'utilité pour les connexions après avoir « réchauffés », et que vous voulez minimiser l'empreinte des ressources, mis minPoolSize à un très bas et utiliser maxIdleTime et/ou maxIdleTimeExcessConnections et/ou maxConnectionAge comme ci-dessus pour s'assurer que le pool est rapidement réduit lorsque les connexions ne sont plus demandées. Alternativement, vous pouvez utiliser le DataSource lorsque vous avez terminé son travail, mais vous allez probablement le laisser à Spring.