Una introducción a los pools de conexiones en Payara Server

Photo of Andy Overton by Andy Overton

En este articulo vamos a realizar una introducción general a los pools de conexiones y las mejores practicas de configuración para Payara Server.

 

Qué es un pool de conexiones?

Un pool de conexiones es un almacén de conexiones de bases de datos relacionales que se pueden utilizar y, más importante, reutilizar para conectar a una base de datos relacional.

 

See here for the original version in English language. 

 

Porqué son necesarios los pools de conexiones?

Las conexiones a bases de datos suelen ser caras en su creación y mantenimiento. Esto se debe generalmente al esfuerzo que el servidor debe realizar para:

  • Establecer una conexión de red al servidor de la base de datos.
  • Analizar la información de la cadena de conexión.
  • Realizar la autenticación del usuario.
  • Inicializar la conexión de la base de datos.
  • Establecer los contextos de transaccionalidad.

Ahora, si tienes una aplicación web con sólo un usuario puedes simplemente crear una conexión a la base de datos al comienzo de la sesión de usuario y cerrarla al final de esta. Sin embargo, este es un escenario altamente improbable.

Ahora, imagina un escenario más realista donde tu aplicación web va a ser accedida por cientos o miles de usuarios. Si cada sesión de usuario crea una conexión a la base de datos, tus usuarios experimentarán un retardo mientras esa conexión se configura y el funcionamiento general de tu sistema se deteriorará.

 

Entonces, la respuesta a la pregunta sobre porque son necesarios los pools de conexiones, es porque mejoran tanto el rendimiento como la escalabilidad de tu sistema.

 

Cómo funcionan los pools de conexiones?

En lugar de crear nuevas conexiones cada vez que una es requerida, un pool de conexiones se crea cuando el servidor de aplicaciones es puesto en marcha. Estas conexiones se pueden utilizar y reutilizar cuantas veces sea necesario. Cuando una nueva conexión se necesita se busca una conexión disponible en el pool de conexiones. Si hay una disponible se devuelve al solicitante. En caso contrario, el pool crea una nueva conexión en caso de que haya conexiones disponibles de acuerdo a su configuración; de no ser así, la solicitud quedará encolada hasta que haya conexiones disponibles. Una vez que se ha terminado con la conexión, en lugar de cerrarla se devuelve al pool de conexiones para ser utilizada para un nuevo solicitante.

 

De acuerdo, esta es la teoría, pero, como funciona en la práctica?

 

Pools de conexiones en Payara Server

Para esta demostración práctica los siguientes elementos serán utilizados:

  • Sistema Operativo - Ubuntu 12
  • Java Version - 1.7.0_05
  • App Server - Payara 4.1.1.161
  • Database - Derby

Si estas utilizando diferentes versiones de estos elementos, los resultados pueden variar.

 

Instalación

Primero, extraer los ficheros zip del JDK y Payara Server en un directorio de tu elección. Para el propósito de esta demo los he instalado en mi directorio de inicio:

 

/home/andy

 

Por conveniencia añade los directorios bin de Java y Payara Server al PATH y establece la variable de entorno JAVA_HOME al directorio donde has descomprimido Java.

 

En mi máquina están configuradas de la siguiente manera:

 

PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/andy/jdk1.7.0_05/bin:/home/andy/payara41/bin
JAVA_HOME=/home/andy/jdk1.7.0_05

 

 

Creando el pool de conexiones - Desde la consola web de administración

Lo primero, es arrancar una instancia Payara Server. Esto se puede hacer desde una terminal de línea de comandos con el siguiente comando:

 

asadmin start-domain

 

Una vez que está arrancado puedes acceder a la consola en http://localhost:4848

En el panel izquierdo seleccionar Resources - JDBC - JDBC Connection Pools

Haz click en New e introducir los siguientes valores:

  • Pool Name - test-pool
  • Resource Type - javax.sql.DataSource
  • Driver Vendor - Derby30

Haz click en Next y después en Finish en la siguiente pantalla, aceptando los valores por defecto.

 connection_pools_1.jpg

 

Añade las propiedades mostradas en la siguiente imagen al pool de conexiones entrando en la pestaña de propiedades adicionales del pool de conexiones.

 

connection_pools_2.jpg

 

Probando la conexión

Haz click en el nombre del pool de conexiones (test-pool).

Haz click en el botón Ping en la parte superior de la pantalla.

Deberías ver un mensaje indicando que el ping ha tenido éxito (Ping Succeeded).

 

connection_pools_3.jpg

 

Creando el pool de conexiones - Desde la línea de comandos

También puedes crear un pool de conexiones utilizando la herramienta de línea de comandos asadmin como se muestra a continuación, sustituyendo tu password por la de test:

 

asadmin create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlDataSource --restype javax.sql.DataSource --property user=root:password=test:DatabaseName=test:ServerName=localhost:port=3306 test-pool

 

Para probar la conexión desde la línea de comandos ejecuta el siguiente comando:

 

asadmin ping-connection-pool test-pool

 

De acuerdo, ahora que tenemos creado el pool de conexiones vamos a ver algunas buenas prácticas respecto a como configurarlo.

 

Tamaño del pool de conexiones

Los pools de conexiones deben ser dimensionados de forma apropiada para atender al máximo número de conexiones concurrentes.

El tamaño máximo debe establecerse en concordancia con el número máximo de peticiones de clientes que tu sistema puede procesar. Si tu aplicación recibe 100 peticiones y cada una de ellas requiere una conexión a base de datos, si tu pool de conexiones es menor que 100, algunas de esas peticiones tendrán que esperar a que una nueva conexión esté disponible.

 

El tamaño mínimo de un pool de conexiones asegura que el número más pequeño de conexiones a la base de datos siempre se establece al iniciar el servidor, esto quiere decir que si tienes un pool con un tamaño mínimo de 10 y recibes 10 peticiones, entonces todas pueden recuperar una conexión a la base de datos sin esperar a que el pool cree una nueva conexión.

 

Siempre hay una compensación al configurar estos valores, ya que el valor mínimo requiere que dichas conexiones se mantengan activas a pesar de la carga del sistema, mientras que el valor máximo puede requerir un potencial número alto de conexiones concurrentes a la base de datos.

 

Estos valores serán diferentes para todos los casos. No hay números mágicos por lo que es necesario que entiendas tu aplicación, cuál será carga esperada, tanto en escenarios estables como en el peor escenario, monitorizando detectar cambios en ésta y configurar los valores de la manera adecuada.

 

Configurando los tamaños mínimo y máximo - a través de la consola web de administración

Haz click en el nombre del pool de conexiones y bajo Pool Settings encontrarás Initial and Minimum Pool Size and Maximum Pool size. Establecelos a los tamaños que necesites.

 

connection_pools_4.jpg

 

Configurando los tamaños mínimo y máximo - a través de la línea de comandos

Para establecer el tamaño inicial y mínimo del pool

 

asadmin set resources.jdbc-connection-pool.test-pool.steady-pool-size=10

 

Para establecer el tamaño máximo del pool

 

asadmin set resources.jdbc-connection-pool.test-pool.max-pool-size=200

 

Validación de la conexión

Validar la conexión asegura que una conexión no sea asignada a aplicaciones que la soliciten en caso de que esta se encuentre en un estado "incorrecto".

La validación de la conexión siempre es una compensación entre la garantía de la validez de una conexión y el impacto en el desempeño causado por esta validación. Habrá un impacto negativo en el funcionamiento por tener que devolver una conexión no válida para la aplicación y solicitar una nueva, por lo que encontrar el equilibrio correcto es la clave.

 

Antes de utilizar una conexión del pool se envía una consulta simple para probar la conexión. Si hay algún problema con la conexión esta se borra del pool y se utiliza otra. El problema aquí es que si existe una situación tal como si la base de datos no se encuentre disponible mientras se tenga un numero alto de conexiones cada una de estas conexiones serán probadas y eliminadas.

 

Para evitar esto puedes establecer la validación de la conexión para que en el caso de que una conexión falle, todas las conexiones serán cerradas.

 

Validación de la conexión - a través de la consola web de administración

Hacer click en el nombre del pool, seleccionar la pestaña Advanced, desplazarse hacia abajo en la pantalla hasta Connection Validation y seleccionar las siguientes configuraciones:

  • Connection Validation requerida.
  • Validation Method - custom-validation
  • Validation Class Name - org.glassfish.api.jdbc.validation.DerbyConnectionValidation

Desde la misma pantalla también puedes establecer si cerrar todas las conexiones en caso de fallo.

 

connection_pools_4.jpg

 

Validación de la conexión - a través de la línea de comandos

Para encender la validación de la conexión:

 

asadmin set resources.jdbc-connection-pool.test-pool.connection-validation-method=custom-validation
asadmin set resources.jdbc-connection-pool.test-pool.validation-classname= org.glassfish.api.jdbc.validation.DerbyConnectionValidation
asadmin set resources.jdbc-connection-pool.test-pool.is-connection-validation-required=true

 

 

También puedes configurar si cerrar todas las conexiones en caso de fallo con el siguiente comando:

 

asadmin set resources.jdbc-connection-pool.test-pool.fail-all-connections=true

 

Detección de fugas de conexiones y sentencias no cerradas

La detección de fugas de sentencias y conexiones no cerradas te permite establecer tiempos de espera para que en el evento de que una sentencia SQL o una conexión no haya sido cerrada por una aplicación, el evento pueda ser registrado y/o estas sean cerradas de forma automática.

 

En un entorno de pruebas recomendaría hacer uso de esta funcionalidad para registrar las fugas detectadas pero NO cerrarlas de forma automática. Sin embargo, en producción recomendaría que las fugas sean cerradas. Si has probado lo suficiente no debería haber ninguna, pero si hay no quieres dejar fugas abiertas. Un software de monitorización debe ser configurado para alertar todas las fugas detectadas para que una investigación profunda pueda ser llevada a cabo de forma que se puedan aplicar las correcciones necesarias.

 

Por defecto estos valores están configurados a 0 por lo que a detección está apagada.

 

Configurar la detección de fugas de sentencias y conexiones no cerradas - a través de la consola web de administración

Hacer click en el nombre del pool, seleccionar la pestaña Advanced, desplazarse hacia abajo en la pantalla hasta Connection Settings y establecer los valores para Connection Leak Timeout y Statement Leak Timeout

 

connection_pools_6.jpg

 

Puedes establecer los valores de tiempo de espera con los siguientes comandos:

 

asadmin set resources.jdbc-connection-pool.test-pool.statement-leak-timeout-in-seconds=5
asadmin set resources.jdbc-connection-pool.test-pool.connection-leak-timeout-in-seconds=5

 

 

Una vez estos valores son configurados si pérdidas de conexión o sentencia son detectadas verás mensajes similares al siguiente en la siguiente entrada del log del servidor.

 

WARNING: A potential connection leak detected for connection pool test-pool. The stack trace of the thread is provided below:

WARNING: A potential statement leak detected for connection pool test-pool. The stack trace of the thread is provided below:

 

En este punto puedes volver a tu equipo de desarrollo y y hacer que investiguen la causa inicial, o golpearlos en la cabeza, dependiendo de tu estilo de gestión :) 

 

Conclusión

Bien, eso es todo para este blog. Hemos dado un vistazo corto a los pools de conexiones, como crearlos y configurarlos en Payara Server junto algunas pocas de las buenas practicas a seguir que se deben considerar.

 

Como con toda configuración de servidor siempre debes mirar de cerca las necesidades de tu aplicación antes de realizar cambios. Siempre se deben realizar pruebas de desempeño y pruebas de carga de tu aplicación para determinar la mejor configuración, particularmente antes de hacer cambios en producción. Un tamaño no sirve para todos! 

 

Una vez hayas decidido sobre la configuración óptima deberías monitorizar y reevaluar regularmente para asegurarte de que siempre estás utilizando la configuración óptima.

 

 

See the English language version here.

 

Comments