¡Esta es una revisión vieja del documento!
El pool de conexiones es una técnica usada en aplicaciones Web para mejorar el rendimiento de éstas.
Antes de ver en que consiste veamos como funciona la creación de conexiones en una aplicación clásica de escritorio cliente-servidor y luego veamos los problemas se seguir con dicha estructura en una aplicación web.
En una aplicación de escritorio se crea una conexión de base de datos al iniciar la aplicación y se cierra al finalizar la aplicación. Es decir que cada usuario que inicia la aplicación tiene una conexión en exclusiva para él. Y obviamente sería imposible de compartirlas ya que cada aplicación estará en un ordenador independiente.
En una aplicación Web podríamos seguir un esquema similar , en el que cada usuario nuevo que se conecta a nuestra aplicación se le crea una conexión y al salir de la aplicación que se cierre la conexión.
Esto que aparentemente es sencillo tiene unos problemas debido a la diferente naturaleza de las aplicaciones de escritorio y las web.
Característica | Escritorio | Web | Problemas |
---|---|---|---|
Número de usuarios | Bajo. Suele estar limitado por el tamaño de una oficina o edificio. | Muy alto. Potencialmente toda internet. | En la Web si cada usuario tiene una conexión propia para él se podría saturar el servidor de base de datos |
Momento de cierre de la conexión | Claramente definido al cerrar la aplicación | Vagamente definido | En Web es complejo saber cuando el usuario abandona el portal (que no la página) para en ese momento cerrar la página |
Si siguiéramos el mismo patrón de creación de conexiones de aplicaciones de escritorio en aplicaciones web acabaríamos con una cantidad enorme de conexiones activas (debido al gran número de usuarios) y con gran cantidad de conexiones abiertas sin usar (debido a usuarios que abandonan el portal y no lo hemos detectado)
Consecuencia de los anterior al tener tantas conexiones a la base de datos se acabaría cayendo el servidor de base de datos debido a los recursos consumidos por todas las conexiones.
Podemos pensar que nuestro servidor puede aguantar todas esas conexiones debido que tenemos pocos usuarios pero no suele ser así debido a:
Una solución chapuza que nos evitaría las conexiones sin usar sería creara la conexión al iniciar cada petición web y cerrarla al finalizar dicha petición web. ¿El problema de eso? Crear y cerrar una conexión es muy costoso. Lo que tendríamos es una aplicación lentísima.
La solución del pool de conexiones tiene que solucionar dos problemas:
La solución de cerrar la conexión se solucionaría fácilmente con la técnica de crearla al inicio de la petición y de cerrarla al final de la petición. Pero como ya hemos visto tiene el problema de lo lenta que sería la aplicación. Pero eso se puede solucionar con el Pool de conexiones
Así que por fin pasemos a explicar en que consiste el pool de conexiones:
El pool de conexiones consiste en tener un conjunto (pool) de conexiones a la base de datos que puedan ser reutilizadas entre distintas peticiones.
Veamos como funciona:
¿Que hemos conseguido con el pool?
En la siguiente gráfica vemos como evolucionan las conexiones de una aplicación web:
Tiempo (s) | Maximo | Activas | Esperando |
---|
10 | 200 | 100 | 50 |
20 | 200 | 120 | 30 |
30 | 200 | 140 | 10 |
40 | 200 | 140 | 50 |
50 | 200 | 140 | 50 |
60 | 200 | 100 | 90 |
70 | 200 | 100 | 50 |
80 | 200 | 70 | 80 |
90 | 200 | 70 | 50 |
100 | 200 | 110 | 10 |
110 | 200 | 110 | 50 |
Desde Java podemos acceder al pool de conexiones usando la interfaz javax.sql.DataSource
. Al llamar al método getConnection()
se obtendrá una conexión del pool de conexiones y no se creará nueva en ese momento. Cuando llamemos al método java.sql.Connection.close()
realmente la conexión no se cerrará sino que se devolverá al pool de conexiones.
DataSource dataSource; Connection connection=dataSource.getConnection(); //Obtener la conexión del pool //Usar la conexión connection.close(); //No se cierra realmente la conexión sino que se retorna al pool
Ahora nos queda saber como obtener un objeto DataSource
. Para obtener un objeto DataSource
necesitamos primero configurar el pool de conexiones mediante el fichero context.xml
, cosa que vamos a ver en el siguiente apartado. Ahora simplemente debemos saber que en un mismo servidor web puede haber muchos pool de conexiones por lo que cada uno de ellos tiene un nombre único. Para obtener el DataSource
asociado a un pool de conexiones debemos incluir el siguiente código:
InitialContext initCtx=new InitialContext();; Context envCtx = (Context) initCtx.lookup("java:comp/env"); DataSource ds = (DataSource)envCtx.lookup("jdbc/hibernate1");
Siendo jdbc/hibernate1
el nombre del pool de conexiones.
Por último nos queda configurar el pool de conexiones. Cada servidor web puede usar su propia implementación del pool de conexiones y se configura de forma específica. Nosotros vamos a explicar como configurar el pool que viene incluido en Tomcat 7.
El pool se configura añadiendo un fichero llamado context.xml
en la carpeta META-INF
.
1: <?xml version="1.0" encoding="UTF-8"?> 2: <Context path="/ejemplo05"> 3: <Resource 4: type="javax.sql.DataSource" 5: auth="Container" 6: name="jdbc/hibernate1" 7: driverClassName="com.mysql.jdbc.Driver" 8: url="jdbc:mysql://localhost:3306/hibernate1" 9: username="hibernate1" 10: password="hibernate1" 11: 12: maxActive="100" 13: maxIdle="30" 14: maxWait="10000" 15: validationQuery="SELECT 1 FROM dual" 16: /> 17: </Context>
envCtx.lookup(name)
Hasta ahora solo hemos indicado los atributo básicos de conexión a la base de datos, veamos ahora los atributos concretos del pool:
maxIdle
para ahorrar recursos del servidor de base de datos.SELECT
que lanza Tomcat para comprobar que la conexión aun está conectada a la base de datos y que ésta ultima no la ha cerrado unilateralmente.