style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

¿Cuántas conexiones simultáneas hechas mediante un pool de conexiones soporta Glassfish ?

Hola buenas tardes, agradezco de antemano la ayuda que pudieran brindarme.

He desplegado una aplicación web hecha en java en Glassfish 3.0.1 mediante un archivo .WAR en mi red local. La aplicación consiste en un cuestionario de 10 preguntas, donde al loguearse el usuario recibe la primera pregunta, y mediante un boton siguiente, recibe la siguiente pregunta, hasta llegar a las 10, para que finalmente le muestre una pantalla con palomitas y taches como resultados.

La aplicación funciona de manera aceptable con dos y tres usuarios que la usen simultáneamente; sin embargo con un cuarto usuario, parece que la conexion a la BD se satura, y ya no le envía respuestas a su petición (se loguea, manda la primera pregunta, y ya no envía mas preguntas). ¿Alguien podría apoyarme diciendo como monitoreo las conexiones de la aplicación con Glassfish? ¿O decirme cuántas conexiones soporta como máximo Glassfish para una aplicación?

Estos son parámetros que especifiqué en el pool de conexiones en Glassfish.

Tamaño de conjunto inicial y mínimo: 10 Conexiones
Tamaño de conjunto máximo: 10 Conexiones
Cantidad de cambio de tamaño del conjunto: 2
Tiempo de espera inactivo: 300 segundos
Tiempo de espera máx.: 6000 milisegundos

Muchas gracias a todos!

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

con una

Para el uso que describes la verdad es que con una sola conexión bastaría, porque incluso si llegaran dos o tres peticiones de manera simultánea, cada una usaría la única conexión disponible en el pool y al final la devuelve, en un tiempo muy corto que no sería notorio para el usuario.

Lo que quiero decir es que seguramente el problema está en otra parte, no en la configuración del pool. Si el problema fuera el pool, el tercer o cuarto usuario verían un error después de 6 segundos. Pero además el tamaño inicial de tu pool es de 10 conexiones, así que sólo es relacionado con el pool si tu aplicación nunca devuelve conexiones al pool y usa varias conexiones para la primera petición. Pero aún así... el tiempo de espera máximo causaría que se arroje un error en tu aplicación cuando le pide una nueva conexión al pool y ya no hay disponibles y nadie devuelve una en 6 segundos.

Ahora, la pregunta: ¿Estás devolviendo las conexiones al pool?

Imagen de neko069

Igual si por ahí tienes

Igual si por ahí tienes métodos sincronizados, checar que no se creen locks si se trata de acceder a ellos de forma concurrente. Es lo primero que se me ocurre, al igual que Enrique, no creo que sea por el lado del consumo de las conexiones a la base de datos.
Por el lado más cansado, sería que hicieras una prueba resolviendo tú misma el formulario y colocar puntos de depuración para checar en dónde se queda atorado tu flujo.

Imagen de marielyen

¿No comprendo como funciona ... devolver conexiones?

Hola ezamudio, muchas gracias por responder.

Mira, la verdad no entiendo con claridad "devolver las conexiones al pool", no se si te refieres con esto a utilizar una conexión en algún método y cerrarla después de haberla utilizado ¿Eso es devolver una conexión al pool?. Tengo una clase que realiza una conexión a la BD, y que es utilizada por los métodos que generan las preguntas de las que he hablado, esta es la siguiente:

public class ConnectionCuestionario {

public Connection getConexion (){

Connection con = null;

try{

InitialContext ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("miRecursoPool");

con = ds.getConnection();

if (con == null){
System.out.println("Error en la Conexion a la BD");
}else{
System.out.println("Conexion exitosa a la BD");
}

}catch (Exception e){
e.printStackTrace();
System.out.println(e.getCause());
System.out.println(e.getMessage());
}

return con;

}

public static Connection getConexionORA (){
ConnectionCuestionario cone = new ConnectionCuestionario ();
return cone.getConexion();
}

}

Los métodos que utilizan dicha clase para hacer la conexión a la BD, lo hacen con esta sentencia:

con = ConnectionCuestionario .getConexionORA();

Posteriormente dentro del bloque try-catch de cada método se ejecutan las consultas necesarias, SELECT, INSERT, UPDATE a la BD, según lo necesiten, y al finalizar las consultas se cierra el objeto del ResultSet rs.colse( ). Posteriormente en el bloque finally cada método cierra los objetos del Statement, ResultSet y, Connection.

}finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (Exception err) {
err.printStackTrace();
System.out.println(err.getMessage());
}
}

¿Podrías decirme si esoty haciendo uso correcto de la conexión a la BD? ¿Estoy cerrando bien la conexión que utilizo en cada método? ¿Estoy devolviendo al pool la conexión que utilizo?Gracias, de antemano!

Imagen de ezamudio

correcto

Correcto pero ineficiente. Tu clase ConnectionCuestionario podría obtener una sola vez la referencia al DataSource, y luego cada que se le pide una conexión, solamente hacer el ds.getConnection().

Cuando usas un pool de conexiones que se presenta como un simple DataSource, cada que invocas getConnection el pool te da una conexión de las que tiene disponibles, o crea una nueva si puede, según como está configurado, etc. Cuando le das close a esa conexión, en realidad no se cierra, sino que se devuelve al pool.

Por la manera en que estás manejando las cosas, la causa de tu problema probablemente sea que no estás cerrando la conexión en alguna parte, por lo tanto no se devuelve al pool y el pool se queda sin conexiones. Pero, como dije al principio, si ese fuera el caso entonces el pool te daría un timeout (pero eso podría quedar oculto si tu código en vez de manejar esas excepciones simplemente "se las traga").

Imagen de marielyen

Obtener una sola vez la referencia al DataSource

Hola, de nueva cuenta gracias por responderme.

"Tu clase ConnectionCuestionario podría obtener UNA SOLA VEZ la referencia al DataSource, y luego cada que se le pide una conexión, solamente hacer el ds.getConnection()."

Cuando dices una sola referencia al DataSource significa que debo crear un único objeto de tipo DataSource dentro de mi clase ConnectionCuestionario, pero entonces si desde afuera mediante algún método solicito una conexión, ¿como hago para utilizar ds.getConnection() sin una referencia al objeto DataSource (estaría haciendo otra referencia al objeto, es correcto)?

Imagen de marielyen

No tengo conocimientos sobre métodos sincronizados, pero...

Hola neko069

No tengo conocimientos sobre métodos sincronizados, ya estoy estudiando un poco acerca de para poder entender lo que me comentas. Mientras tanto, te agradezco mucho el apoyo.

Imagen de ezamudio

*sigh*

Tu clase de conexión guarda la referencia al DataSource y cada que le piden una conexión, la obtiene de ahí. Tus clases de servicio o lo que sean, guardan una referencia a ese componente de conexión usuario y le piden una conexión cuando la necesitan. De ese modo sólo hace la búsqueda del datasource en el JNDI una vez, cuando se crea el componente, y de ahí puedes obtener tantas conexiones como necesites.

class ConexionUsuario {
  private final DataSource ds;

  public ConexionUsuario() throws NoRecuerdoQueCosaException {
    //Aquí obtienes la conexión del JNDI o donde sea
    ds = initialContext.lookup(bla);
  }

  public Connection getConexion() {
    Connection c = null;
    try {
      c = ds.getConnection();
    } catch (Exception ex) {
      log.error("Obteniendo conexion", ex);
    }
    return c;
  }
}

Y para usarla:

class MiServicioOLoQueSea {
  private ConexionUsuario cu;

  public MiServicioOLoQueSea() throws NoRecuerdoQueCosaException {
    cu = new ConexionUsuario();
  }

  public void hazAlgo() {
    Connection c = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      c = cu.getConexion();
      ps = c.prepareStatement("BLA");
      rs = ps.executeQuery();
      //blabla
    } catch (SQLException ex) {
      log.error("broncas", ex);
    } finally {
      if (rs != null) try {
        rs.close();
      } catch (Exception ex) {/*nada que hacer ya*/}
      if (ps != null) try {
        ps.close();
      } catch (Exception ex) {/*nada que hacer ya*/}
      if (c != null) try {
        c.close();
      } catch (Exception ex) {/*nada que hacer ya*/}
    }
  }
}

Imagen de marielyen

Ha funcionado correctamente la aplicación.

Muchas gracias ezamudio y neko069. He estudiado y aplicado mucho de lo que me han comentado sobre el problema que plantee al inicio, y he podido reestructurar varias cosas en favor del rendimiento de mi aplicación, de verdad, mil gracias!

Consulta Acerca de Cierres de conexion

Que tal saludos

Tengo un problema realmente similar.
Se tiene alguna forma de saber cuales son las conexiones que están atoradas ???
Digamos consultando desde la BD se pueden visualizar las conexiones echas por el pool de conexiones
como identificar si estan libres o atoradas ?????

Hay alguna otra forma de cerrar esas conexion por ejemplo por inactividad o si no se encuentra comunicación en
esa conexión ???

Gracias ...

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">