IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Hibernate Java Discussion :

Problème de connexions ouvertes - Oracle / c3p0


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Janvier 2005
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Janvier 2005
    Messages : 18
    Par défaut Problème de connexions ouvertes - Oracle / c3p0
    Bonjour à tous,

    nous utilisons Hibernate au travail pour un programme comprenant un front et un back-end.
    Le back-end se connecte à deux bases distinctes (une Oracle et une Sybase).
    Nous avons malheureusement des problèmes avec la base Oracle.

    En effet les DBA nous ont averti d'un trop grand nombre de connexions restant ouvertes à la base de données (nous utilisions alors le pool de connection builtin d'Hibernate). Nous sommes donc passés à l'utilisation de c3p0 pour qu'il gère correctement le pool.
    Je vais vous mettre directement la config d'hibernate / c3p0:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
     
    <hibernate-configuration>
        <session-factory>
            <!-- Database connection settings --> 
            <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
            <property name="connection.url">jdbc:oracle:thin:@url</property>
            <property name="connection.username">username</property>
            <property name="connection.password">password</property>
     
            <!-- Database connection pool -->
            <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
            <property name="c3p0.min_size">0</property> 
            <property name="c3p0.max_size">10</property> 
            <property name="c3p0.timeout">60</property> 
            <property name="c3p0.max_statements">0</property>
            <property name="c3p0.idle_test_period">60</property>
            <property name="c3p0.acquire_increment">1</property>
            <property name="hibernate.connection.aggressive_release">true</property>
            <!-- This is for debug purpose only -->
            <property name="c3p0.unreturnedConnectionTimeout">60</property>
            <property name="c3p0.debugUnreturnedConnectionStackTraces">true</property>
            <property name="org.apache.commons.logging.Log">org.apache.commons.logging.impl.Log4JLogger</property>
     
            <property name="dialect">org.hibernate.dialect.OracleDialect</property> 
            <property name="current_session_context_class">thread</property>
            <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> 
            <mapping ... />
        </session-factory>
    </hibernate-configuration>
    Le problème est donc comme je l'ai dis plus haut qu'Hibernate laisserait des connexions à la base de données ouvertes, pourtant c3p0 est configuré pour gérer un pool de [0; 10] connexions ouvertes, avec un timeout réglé à une minute pour les release plus rapidement.
    Tout à l'air de bien se passer pendant quelques heures, et le problème reviens à nouveau...
    J'ai donc regardé dans les log du backend et voila une erreur qui est lancé des centaines de fois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    INFO: Illegal access: this web application instance has been stopped already.  Could not load oracle.net.ns.Message11.  The eventual following stack trace
     is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional
    impact.
    java.lang.IllegalStateException
            at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1273)
            at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
            at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
            at java.lang.Class.forName0(Native Method)
            at java.lang.Class.forName(Class.java:164)
            at oracle.net.ns.NetException.<init>(Unknown Source)
            at oracle.net.ns.Packet.receive(Unknown Source)
            at oracle.net.ns.NSProtocol.connect(Unknown Source)
            at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:858)
            at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:268)
            at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:441)
            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:134)
            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)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    WARN: com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@677154 -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception:
    java.lang.NullPointerException
            at oracle.sql.CharacterSet.make(CharacterSet.java:441)
            at oracle.jdbc.driver.DBConversion.init(DBConversion.java:152)
            at oracle.jdbc.driver.DBConversion.<init>(DBConversion.java:116)
            at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:892)
            at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:268)
            at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:441)
            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:134)
            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)
    Je précise que tout fonctionne vraiment correctement pendant un long moment et puis ça commence à se crasher petit à petit, y compris la base elle même à laquelle on ne peut plus se connecter tant qu'on n'a pas tué tomcat qui héberge l'application (plus de place dispo sur Oracle pour une nouvelle connexion).

    Pour plus d'infos je vous montre le schéma de code Java qui est toujours utilisé pour faire des accès à la base de données via Hibernate, peut-être y a t il une coquille dedans et c'est le bout de code qui oublierais de fermer les connexions dans certains cas ?
    J'utilise la classe SessionManager que j'ai trouvé dans la doc hibernate: https://www.hibernate.org/238.html ou via google cache car le site n'a pas l'air de répondre ce matin...
    et nous l'utilisons ainsi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SessionManager mgr = new SessionManager(HibernateUtil.getSessionFactory());
    		mgr.runSession(new DBAction() {
    			public void run(final Session session) throws HibernateException {
    				Person foo= session.createQuery("select p from Person p where p.name = 'foo'").uniqueResult();
                                    // do something
    			}
    		});
    J'aurai vraiment besoin d'aide car je suis totalement perdu sur la cause de ces connexions fantômes qui restent en vie alors qu'hibernate/c3p0 devrait les couper quand il n'en a plus besoin .

    Merci d'avances à tous

  2. #2
    Membre averti
    Inscrit en
    Janvier 2005
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Janvier 2005
    Messages : 18
    Par défaut
    Rebonjour,

    je reviens aux nouvelles, finalement j'ai l'impression après pas mal de monitoring que les connexions se ferment bien au fur et a mesure du laps indiqué dans les propriétés de c3p0 (60 secondes).
    Par contre le problème c'est qu'il ne respecte pas du tout le nombres de connexions maximum indiqué par le pool.

    En effet comme je le disais dans le précédent post, plusieurs utilisateurs utilisent un front, le front appelle des web services qui eux utilisent hibernate pour récupérer des données, de plus on utilise le moteur de workflow JBPM qui utilise en interne hibernate, chacun ont un fichier de configuration hibernate, pour JBPM j'autorise 5 connexions maximum, et pour hibernate j'en autorise 10.
    Ce qui devrait donc porter à 15 connexions au total.

    Les utilisateurs utilisent donc le front pour insérer des données, en modifier etc, et tout un coup pendant le monitoring j'ai détecté 37 connexions ouvertes au même instant, sachant que je n'utilise que les sessions hibernate + c3p0 je m'attends à ce que le nombre de connexions ouvertes soient limitées au nombre fixé dans le fichier de config.
    Je précise qu'une fois les insert/update finis par le front, au fil des 60 secondes (timeout de c3p0) les connexions se ferment bien et on tombe de nouveau à un nombre normal.

    Voyez-vous d'où le problème peut venir ? Ai-je quelquechose à gérer moi même au niveau du web service, une config spéciale pour la réutilisation des sessions d'hibernate ? Si 30 utilisateurs sont connectés sur le front, vais-je avoir 30 sessions crées et donc 30 connexions ouvertes à la bdd ?

    Merci d'avance, car moi je n'avance plus trop sur le sujet

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Il faudrait lire la doc de c3p0 pour voir ce que veut dire exactement le paramètre c3p0.max_size.
    Il s'agit peut-être simplement de la taille max du pool, ce qui ne veut pas dire le nombre maximum de connexions simultanées.
    Je veux dire par là que si cette taille est atteinte, les connexions sont peut-être obtenues directement auprès de la base et non plus du pool, ce qui permet de dépasser cette taille max.

    Si tu veux paramétrer le nombre max de connexions, il faut plutôt regarder du côté du datasource de ton serveur d'application.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 104
    Par défaut
    Salut,

    la propriété max_size définit le nombre max de connexions dans le pool et non le nombre max de connexions ouvertes.
    De plus la config de ton pool est un peu étrange :
    - max_statements à 0, tu n'actives pas le cache pour les preparedStatement, cela peut être intéressant car on a souvent les mêmes requêtes
    - min_size à 0 : quand toutes les connexions sont fermées, il n'y a pas plus de connexions dans le pool, tu perds donc l'intérêt du pool car chaque nouvelle connexion doit être de nouveau créée
    - acquire_increment à 1 : quand le pool doit créer de nouvelles connexions, il le fait 1 par 1, il peut être plus intéressant de les créer 3 par 3 voire plus
    - unreturnedConnectionTimeout à 60 : si tu dois définir cette valeur c'est que tu as un pb dans ta gestion des connexions (ie. tu ne fermes pas les connexions), la valeur normale est 0

  5. #5
    Membre averti
    Inscrit en
    Janvier 2005
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Janvier 2005
    Messages : 18
    Par défaut
    Salut à tous,

    La propriété unreturnedConnectionTimeout était intentionnellement fixée en plus de celle qui me renvoie la stacktrace le temps des tests afin de déterminer si je perdais des connexions quelque part, mais ça n'a pas l'air d'arriver...
    Je me suis donc mis à monitorer la classe SessionManager dont je parlais plus haut, pour vérifier qu'elle ferme bien à chaque fois les sessions qu'elle ouvre, et c'est bien le cas.

    Par contre il m'arrive parfois d'avoir (via des méthodes utilitaires) des sessionOpen dans d'autres sessionOpen, je me suis donc mis à les corriger pour voir si ça n'engendrais pas moins de problème, ça à l'air d'ouvrir déjà pas mal de sessions (donc de connexions?) en moins... mais ça ne règle pas tout à fait le problème, même s'il n'est pas survenu depuis hier pour le moment.

    Afin d'utiliser un datasource je dois déclarer ça comme JNDI au niveau du fichier web ou context de tomcat ? Je n'ai jamais fais cela, mais d'après ce que je viens de lire dans la documentation je dois aussi y setter des propriétés pour le pool de connexions que voudra gérer Tomcat.
    Ne va-t-il pas y avoir conflit avec c3p0 ? De plus je n'ai pas vu de propriétés spécifiant le nombre maximal de connexions, mais plutôt un max poolsize comme l'a expliqué Kirua12.

    Aurais-tu quelques docs sur ce sujet fr1man ?

    Merci pour vos réponses

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 104
    Par défaut
    Le fait d'utiliser une datasource accessible depuis jndi ne change rien. Au lieu que ce soit configuré au niveau d'hibernate, c'est configuré au niveau de Tomcat. Et tu peux avoir le pool fournit par c3p0
    Que ce soit c3p0 ou DBCP, rien n'interdit de créer plus de connexions que la taille du pool.
    Au passage, il me semble que tes propriétés pour la config de c3p0 soient incorrectes. Voir la doc

Discussions similaires

  1. [CR 2008] Problème de connexion Crystal <-> oracle
    Par lordpatate dans le forum Connectivité
    Réponses: 1
    Dernier message: 25/05/2009, 10h15
  2. Problème de connexion JAVA-Oracle
    Par harous dans le forum Oracle
    Réponses: 8
    Dernier message: 23/04/2009, 21h23
  3. Problème de connexion java oracle
    Par flora001 dans le forum Débuter avec Java
    Réponses: 9
    Dernier message: 31/03/2008, 16h13
  4. Problème de connexion ODBC Oracle
    Par Nary dans le forum Connexions aux bases de données
    Réponses: 0
    Dernier message: 30/01/2008, 15h20
  5. [ASP.Net C# 2]Problèmes de connexion avec Oracle
    Par Taichin dans le forum ASP.NET
    Réponses: 2
    Dernier message: 07/05/2007, 14h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo