Tomcat et pool de connexions

Tomcat et pool de connexions - Java - Programmation

Marsh Posté le 27-07-2004 à 11:07:53    

Voila, j'ai implementé la methode "officielle" pour créer des pools de connexions avec Tomcat :  
 
http://jakarta.apache.org/tomcat/t [...] howto.html  
 
Le probleme, c'est que quand plus de 5 utilisateurs sont en même temps sur l'appli, j'ai pas assez de pools de connexions !!!!!!!!!!! et ça plante l'appli.  
 
J'ai cette erreur :  
 

Citation :

org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted, cause:  
java.util.NoSuchElementException: Timeout waiting for idle object


 
Alors qu'avec ceci cela doit etre suffisant :  
 

Code :
  1. <Context className="org.apache.catalina.core.StandardContext" cachingAllowed="true" charsetMapperClass="org.apache.catalina.util.CharsetMapper" cookies="true" crossContext="false" debug="0" docBase="/usr/local/tomcat/webapps/elearning" mapperClass="org.apache.catalina.core.StandardContextMapper" path="/elearning" privileged="false" reloadable="true" swallowOutput="false" useNaming="true" wrapperClass="org.apache.catalina.core.StandardWrapper">
  2.       <Resource name="jdbc/VM" auth="Container" type="javax.sql.DataSource"/>
  3.       <ResourceParams name="jdbc/VM">
  4.         <parameter>
  5.              <name>factory</name>
  6.              <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  7.         </parameter>
  8.         <parameter>
  9.              <name>driverClassName</name>
  10.              <value>org.postgresql.Driver</value>
  11.         </parameter>
  12.         <parameter>
  13.              <name>url</name>
  14.              <value>jdbc:postgresql://localhost:5432/elearningbase?charset=LATIN1</value>
  15.         </parameter>
  16.         <parameter>
  17.              <name>username</name>
  18.              <value>xxxx</value>
  19.         </parameter>
  20.         <parameter>
  21.              <name>password</name>
  22.              <value>xxxx</value>
  23.         </parameter>
  24.         <parameter>
  25.              <name>maxActive</name>
  26.              <value>100</value>
  27.        </parameter>
  28.         <parameter>
  29.              <name>maxIdle</name>
  30.              <value>20</value>
  31.        </parameter>
  32.         <parameter>
  33.              <name>maxWait</name>
  34.              <value>20000</value>
  35.         </parameter>
  36.       </ResourceParams>
  37.    </Context>

Reply

Marsh Posté le 27-07-2004 à 11:07:53   

Reply

Marsh Posté le 27-07-2004 à 11:09:10    

Voici ma classe pour me connecter :
 

Citation :

/*
 * Created on 3 nov. 2003
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package data;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
 
/**
 *  
 *
 * To change the template for this generated type comment go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
public class myBdConnect {
 public myBdConnect() {
 
 }
 
 public Connection connect() {
  Connection conn= null;
  try {
   Context ctx = new InitialContext();
   if (ctx == null)
    throw new Exception("Boom - No Context" );
   DataSource ds =
    (DataSource) ctx.lookup("java:comp/env/jdbc/VM" );
   if (ds != null) {
    conn = ds.getConnection();
    if (conn != null) {
     return conn;
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  return conn;
 }
 
}


Message édité par Mazda3 le 27-07-2004 à 11:09:35
Reply

Marsh Posté le 27-07-2004 à 11:10:28    

Et un exemple d'utilisation :
 

Citation :

public int insertBd() {
  PreparedStatement pInsert;
  PreparedStatement pMax;
  String insert = "insert into theme (id, tradid) values (?,?)";
  String max = "select max(id) from theme";
  int leMax = 0;
  try {
   myBdConnect m = new myBdConnect();
   Connection conn = m.connect();
   pMax = conn.prepareStatement(max);
   pMax.clearParameters();
   ResultSet rst1 = pMax.executeQuery();
   if (rst1.next()) {
    leMax = rst1.getInt(1);
    this.id = leMax;
   }
   pInsert = conn.prepareStatement(insert);
   pInsert.clearParameters();
   pInsert.setInt(1, this.id);
   pInsert.setInt(2, this.tradid);
   pInsert.executeUpdate();
   conn.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return leMax;
 }


Message édité par Mazda3 le 27-07-2004 à 11:10:39
Reply

Marsh Posté le 27-07-2004 à 11:20:38    

Jamais utilisé le pool de connexions intégré à Tomcat.
Pers j'utilise Protomatter, et tout se passe très bien.

Reply

Marsh Posté le 28-07-2004 à 10:26:34    

Protommater c bien, mais mon appli est quasi-fini et installé chez le client, mais j'ai toujours ce probleme de pool
 

Citation :

org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted, cause:  
java.util.NoSuchElementException: Timeout waiting for idle object


 
Je dois rajouter ceci ?

Citation :

<parameter>
             <name>removeAbandoned</name>
              <value>true</value>
</parameter>


 
Je ne ferme pas toute mes connexions ?


Message édité par Mazda3 le 28-07-2004 à 10:27:27
Reply

Marsh Posté le 28-07-2004 à 10:28:29    

si c'est un pool tu n'es pas censé t'occuper de l'ouverture/fermeture hein. C'est justement le but du pool ...


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 28-07-2004 à 10:32:57    

Sur le site de Tomcat, ils conseillent de fermer :
 
la connexion, le statement et le resultSet.
 
Quand on ferme la connexion, on ferme automatiquement le resultSet et le Statement ????
 
ça peut venir de cela ?

Reply

Marsh Posté le 28-07-2004 à 10:34:00    

mazda3 a écrit :

Quand on ferme la connexion, on ferme automatiquement le resultSet et le Statement ????


 
bin non :heink:


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 28-07-2004 à 10:44:54    

Bon benh ça doit etre ça qui multiple les utilisations de pool ...
 
Tu penses comme moi Darklord ?
 
ça va me faire des grosses modifs ça ...


Message édité par Mazda3 le 28-07-2004 à 10:45:42
Reply

Marsh Posté le 28-07-2004 à 10:49:58    

DarkLord a écrit :

si c'est un pool tu n'es pas censé t'occuper de l'ouverture/fermeture hein. C'est justement le but du pool ...


 
Pardon, je me suis mal exprimé.
 
Quand je fais un conn.close();
 
La connexion utilisée pour "cette requete" va être libéré ? ou il faut aussi que je ferme aussi le Statement et le ResultSet ?


Message édité par Mazda3 le 28-07-2004 à 10:50:31
Reply

Marsh Posté le 28-07-2004 à 10:49:58   

Reply

Marsh Posté le 28-07-2004 à 12:01:02    

Tu dois toujours fermer ton statement et ton resulset, que tu utilises un pool ou pas.  
 
Tu as l'URL où il suggèrent de fermer la connection avec un pool? Ca me parait bizarre (a moins qu'il wrappe l'implémentation avec un truc qui fait autre chose quand tu appelles close)


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 28-07-2004 à 12:06:55    


 
Ben si, en partie.
Enfin, non, mais quand on ferme le Statement, on ferme les ResultSet qui en sont issus.
Cela dit, je parlais de protomatter : et bien pour ce driver, ils conseillent de bien tout fermer, ResultSet compris. Implémentation incorrecte !?

Reply

Marsh Posté le 28-07-2004 à 12:08:18    

DarkLord a écrit :

Tu dois toujours fermer ton statement et ton resulset, que tu utilises un pool ou pas.  
 
Tu as l'URL où il suggèrent de fermer la connection avec un pool? Ca me parait bizarre (a moins qu'il wrappe l'implémentation avec un truc qui fait autre chose quand tu appelles close)


 
Ha !?
 
Extrait de doc de ResultSet :


close
 
public void close()
           throws SQLException
 
    Releases this ResultSet object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed.
 
    Note: A ResultSet object is automatically closed by the Statement object that generated it when that Statement object is closed, re-executed, or is used to retrieve the next result from a sequence of multiple results. A ResultSet object is also automatically closed when it is garbage collected.
 
 

Reply

Marsh Posté le 28-07-2004 à 12:13:13    

El_gringo a écrit :

Ha !?
 
Extrait de doc de ResultSet :


close
 
public void close()
           throws SQLException
 
    Releases this ResultSet object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed.
 
    Note: A ResultSet object is automatically closed by the Statement object that generated it when that Statement object is closed, re-executed, or is used to retrieve the next result from a sequence of multiple results. A ResultSet object is also automatically closed when it is garbage collected.
 
 



 
oui et?  
Qu'est ce que tu veux prouver au juste.
 
J'ai un PreparedStatement que je veux réutiliser pour faire plusierus query. Ca me génère à chaque fois un resultset différent. Quand j'ai choppé mes données je fermes mon resultset et je continue.
 
Si maintenant tu préfères que ce genre d'objet soit cleané via un timeout ou bien en réutilisant le meme objet, fine, c'est ton problème.  
 
Mais je trouve plus propre de montrer explicitement dans le code que tu fermes les ressources que tu utilises.


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 28-07-2004 à 13:34:47    

C'est juste pour dire ce c'est pas une obligation de fermer ses ResultSet.
Cela dit, j'suis d'accord avec toi que c'est plus clean.

Reply

Marsh Posté le 28-07-2004 à 13:47:16    

Reply

Marsh Posté le 28-07-2004 à 13:50:16    

A cette adresse, tout en bas :
 
http://jakarta.apache.org/tomcat/t [...] howto.html
 
Je le mets en commentaires :
 

Citation :

Random Connection Closed Exceptions  
These can occur when one request gets a db connection from the connection pool and closes it twice. When using a connection pool, closing the connection just returns it to the pool for reuse by another request, it doesn't close the connection. And Tomcat uses multiple threads to handle concurrent requests. Here is an example of the sequence of events which could cause this error in Tomcat:  
 
  Request 1 running in Thread 1 gets a db connection.
 
  Request 1 closes the db connection.
 
  The JVM switches the running thread to Thread 2
 
  Request 2 running in Thread 2 gets a db connection
  (the same db connection just closed by Request 1).
 
  The JVM switches the running thread back to Thread 1
 
  Request 1 closes the db connection a second time in a finally block.
 
  The JVM switches the running thread back to Thread 2
 
  Request 2 Thread 2 tries to use the db connection but fails
  because Request 1 closed it.
 
Here is an example of properly written code to use a db connection obtained from a connection pool:  
  Connection conn = null;
  Statement stmt = null;  // Or PreparedStatement if needed
  ResultSet rs = null;
  try {
    conn = ... get connection from connection pool ...
    stmt = conn.createStatement("select ..." );
    rs = stmt.executeQuery();
    ... iterate through the result set ...
    rs.close();
    rs = null;
    stmt.close();
    stmt = null;
    conn.close(); // Return to connection pool
    conn = null;  // Make sure we don't close it twice
  } catch (SQLException e) {
    ... deal with errors ...
  } finally {
    // Always make sure result sets and statements are closed,
    // and the connection is returned to the pool
    if (rs != null) {
      try { rs.close(); } catch (SQLException e) { ; }
      rs = null;
    }
    if (stmt != null) {
      try { stmt.close(); } catch (SQLException e) { ; }
      stmt = null;
    }
    if (conn != null) {
      try { conn.close(); } catch (SQLException e) { ; }
      conn = null;
    }
  }

Reply

Marsh Posté le 28-07-2004 à 13:52:06    

Si j'ai bien compris, mon pb peut venir a cause de ça ? (que je n'ai pas tout fermer )


Message édité par Mazda3 le 28-07-2004 à 13:52:30
Reply

Marsh Posté le 28-07-2004 à 13:54:48    

J'adore ...
 
Le gars il poste parce qu'il a un doute concernant son code et c'est lui qui 20 posts après poste un exemple concret.  
 
Mazda3 > si tu as un stress avec ton code ca t'es pas venu à l'esprit d'utiliser celui que tu viens de poster? Vu que c'est un exemple de tomcat ....  
 
:heink:


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 28-07-2004 à 14:03:51    

DarkLord a écrit :

J'adore ...
 
Le gars il poste parce qu'il a un doute concernant son code et c'est lui qui 20 posts après poste un exemple concret.  
 
Mazda3 > si tu as un stress avec ton code ca t'es pas venu à l'esprit d'utiliser celui que tu viens de poster? Vu que c'est un exemple de tomcat ....  
 
:heink:


 
Bah justement comme je viens de dire, mon appli est quasi-fini, sauf avec ce pb de pool (pas assez de pool ouvert  :heink: , 100 c largement suffisant).
 
Et je suis pas sûr à 100% (mais à 60%, oui) qu'avec le code fourni en exemple sur le site de Tomcat, que celui-ci resoudra mon pb. Si je fais les modifs, j'en ai au moins pour une journée. Pas envie de perdre une journée pour rien.
 
j'ai implementer trop vite, j'aurais du tout lire  :(

Reply

Marsh Posté le 28-07-2004 à 14:36:14    

ben t'as qu'à mettre 2 connexions dans ton pool et regarder ce qui se passe avec un petit test...

Reply

Marsh Posté le 28-07-2004 à 18:07:57    

_guigui_ a écrit :

ben t'as qu'à mettre 2 connexions dans ton pool et regarder ce qui se passe avec un petit test...


 
ça a l'air de fonctionner mais quand je mets le parametre du pool "maxActive" à zero, cela fonctionne egalement. ..
 
Je comprends plus rien .... :pt1cable:  
 
 

Citation :

    <Context className="org.apache.catalina.core.StandardContext" cachingAllowed="true" charsetMapperClass="org.apache.catalina.util.CharsetMapper" cookies="true" crossContext="false" debug="0" docBase="/usr/local/tomcat/webapps/elearning" mapperClass="org.apache.catalina.core.StandardContextMapper" path="/elearning" privileged="false" reloadable="true" swallowOutput="false" useNaming="true" wrapperClass="org.apache.catalina.core.StandardWrapper">  
        <Resource name="jdbc/VM" auth="Container" type="javax.sql.DataSource"/>  
        <ResourceParams name="jdbc/VM">  
          <parameter>  
               <name>factory</name>  
               <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>  
          </parameter>  
          <parameter>  
               <name>driverClassName</name>  
               <value>org.postgresql.Driver</value>  
          </parameter>  
          <parameter>  
               <name>url</name>  
               <value>jdbc:postgresql://localhost:5432/elearningbase?charset=LATIN1</value>  
          </parameter>  
          <parameter>  
               <name>username</name>  
               <value>xxxx</value>  
          </parameter>  
          <parameter>  
               <name>password</name>  
               <value>xxxx</value>  
          </parameter>  
          <parameter>  
               <name>maxActive</name>  
               <value>0</value>  
         </parameter>  
          <parameter>  
               <name>maxIdle</name>  
               <value>0</value>  
         </parameter>  
          <parameter>  
               <name>maxWait</name>  
               <value>0</value>  
          </parameter>  
        </ResourceParams>  
     </Context>


Message édité par Mazda3 le 28-07-2004 à 18:09:26
Reply

Marsh Posté le 28-07-2004 à 18:15:12    

et l'exemple de tomcat te plait pas ?


---------------
IVG en france
Reply

Marsh Posté le 28-07-2004 à 22:01:04    

uriel a écrit :

et l'exemple de tomcat te plait pas ?


 
Si cela marche parfaitement, mais logiquement en mettant MaxActive à 0, je ne devrais avoir aucune connexion ...

Reply

Marsh Posté le 29-07-2004 à 11:17:52    

Re-bonjour.
 
Personne ne sait comment "visualiser" les pools de connexion de Tomcat (ouverts, utilisés, etc ...) ?
 

Reply

Marsh Posté le 29-07-2004 à 11:18:44    

demande à postgres [:spamafote]
la DB est sous quel OS?


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 29-07-2004 à 11:30:26    

DarkLord a écrit :

demande à postgres [:spamafote]
la DB est sous quel OS?


 
PostGreSQL est sous Linux

Reply

Marsh Posté le 29-07-2004 à 13:49:45    

mazda3 a écrit :

Si cela marche parfaitement, mais logiquement en mettant MaxActive à 0, je ne devrais avoir aucune connexion ...


 
Non non t'as mal lu la doc. Ça veut dire aucune limite


---------------
http://anothergeekwebsite.com
Reply

Marsh Posté le 29-07-2004 à 13:54:59    

J'avais lu que c'était -1 aucune limite ....
 
Après relecture : c'est bien 0 pour MaxActive en illimité et -1 pour le parametre MaxWait en illimité.
 
Merci  :jap:


Message édité par Mazda3 le 29-07-2004 à 14:08:09
Reply

Marsh Posté le 29-07-2004 à 14:54:21    

Après un test rapide sur un TOMCAT 4.1.27 si maxActive est à 0 ou -1 cela ne fonctionne pas. On a une exception : DBCP could not obtain an idle db connection. En repassant maxActive à 1 c'est OK.

Reply

Marsh Posté le 29-07-2004 à 19:49:15    

spiman a écrit :

Après un test rapide sur un TOMCAT 4.1.27 si maxActive est à 0 ou -1 cela ne fonctionne pas. On a une exception : DBCP could not obtain an idle db connection. En repassant maxActive à 1 c'est OK.


 
Bizarre ...
 

Citation :

   <!-- Maximum number of dB connections in pool. Make sure you
         configure your mysqld max_connections large enough to handle
         all of your db connections. Set to 0 for no limit.
         -->
    <parameter>
      <name>maxActive</name>
      <value>100</value>
    </parameter>


 
 :??:

Reply

Marsh Posté le 30-07-2004 à 11:26:36    

oui j'ai vu ça aussi c'est dans l'exemple pour mysql mais je pense pas que le fait que ce soit une base PostGres change qqchose. Toujours est t'il que je n'arrive pas à le mettre en oeuvre. Maintenant ça n'a pas un intérêt phénoménal et ce n'est d'ailleurs pas possible de mettre nolimit sur d'autres serveurs d'application comme weblogic. Pour en revenir au sujet du topic le code proposé par tomcat est trés bien. Il faut absolument fermer les connections dans le finally et pas dans le try.

Reply

Marsh Posté le 30-07-2004 à 16:05:22    

Bon et bien cette grosse de journée de modifs a été très utile !!!! Cela a réglé mes pb de pools !

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed