sql >> Base de Datos >  >> RDS >> PostgreSQL

Escalado de conexiones en PostgreSQL mediante la agrupación de conexiones

Abrir una conexión de base de datos es una operación costosa y la agrupación de conexiones se usa para mantener abiertas las conexiones de base de datos para que puedan reutilizarse. Esto evita tener que abrir repetidamente sesiones de red, autenticarse y verificar la autorización. La agrupación mantiene las conexiones activas para que, cuando se solicite una conexión más tarde, se use una de las activas en lugar de tener que crear una desde cero.

Agrupación de conexiones

La agrupación de conexiones se ha convertido en uno de los métodos más comunes para manejar las conexiones de bases de datos antes de una solicitud de consulta. Normalmente pensamos que una conexión a la base de datos es rápida, pero ese no es el caso, especialmente cuando se conecta una gran cantidad de clientes. Sin la agrupación de conexiones, una solicitud tardaría entre 35 y 50 ms en conectarse, pero entre 1 y 2 ms si se emplea la agrupación de conexiones. Por lo tanto, la agrupación de conexiones preasigna conexiones de base de datos y luego las recicla cuando se conectan nuevos clientes

Razones para la agrupación de conexiones

  1. Para evitar colapsar su servidor. Los servidores PostgreSQL están limitados a una cantidad de clientes que manejan a la vez según el parámetro de memoria. Si se supera este número, terminará colapsando el servidor. Con la agrupación de conexiones, los clientes utilizan un número determinado de conexiones.
  2. Facilitar el procesamiento de consultas. Normalmente, las solicitudes de bases de datos se ejecutan de manera serial con un criterio de primeras entradas, primeras salidas. Con un gran conjunto de clientes, llevaría mucho tiempo lograr este proceso. Por lo tanto, el enfoque debe ser hacer una conexión única con solicitudes canalizadas que se pueden ejecutar simultáneamente en lugar de cada una a la vez.
  3. Mejorar la seguridad. A menudo, una conexión implica un apretón de manos que puede tomar un promedio de 25 a 35 ms, durante el cual se establece un SSL, se verifican las contraseñas y se comparte la información de configuración. Todo este trabajo para cada usuario conectado dará como resultado un uso extensivo de la memoria. Sin embargo, con la agrupación de conexiones, la cantidad de conexiones se reduce y, por lo tanto, se ahorra memoria.

Tipos de agrupación de conexiones

Básicamente, existen dos tipos de agrupación de conexiones, sin embargo, existe un tercer tipo de solución alternativa que actúa como una estrategia de agrupación de conexiones conocida como conexiones persistentes.

Agrupación de conexiones persistentes

Este enfoque pretende mantener activa una conexión inicial desde el momento en que se inicia. No mantiene completamente las funciones de agrupación de conexiones, pero lo suficientemente bien como para proporcionar una conexión continua. Es muy útil para un pequeño conjunto de conexiones de clientes cuya sobrecarga puede oscilar entre 25 y 50 ms. Una limitación con este enfoque es que está limitado a una cantidad de conexiones a la base de datos con normalmente una sola conexión por entrada al servidor.

Conjunto de conexiones del marco

La agrupación de conexiones del marco se produce a nivel de aplicación, por lo que, cada vez que se inicia la secuencia de comandos del servidor, se establece un grupo de conexiones para manejar las solicitudes de consulta que llegarán más tarde.

Agrupación de conexiones independientes

Por cada conexión a la base de datos, se utiliza una memoria de sobrecarga de entre 5 y 10 MB para atender una solicitud de consulta. Esto no es del todo bueno para una gran cantidad de conexiones. El uso de la agrupación de conexiones del marco puede estar limitado por esta cantidad de conexiones, ya que puede encontrar un uso de gran tamaño de memoria. Por lo tanto, optamos por utilizar la agrupación de conexiones independiente que se configura de acuerdo con las sesiones, declaraciones y transacciones de Postgres. La principal ventaja asociada con este enfoque es:un costo general mínimo de alrededor de 2 kb por cada conexión.

Cuando crea una clase de agrupación de conexiones, debe cumplir con los siguientes factores para un mayor rendimiento de la base de datos:

  1. Preasignar las conexiones
  2. Supervisar las conexiones que están disponibles
  3. Asignar nuevas conexiones
  4. Espere a que haya una conexión disponible
  5. Cerrar conexión
Descargue el documento técnico hoy Administración y automatización de PostgreSQL con ClusterControlObtenga información sobre lo que necesita saber para implementar, monitorear, administrar y escalar PostgreSQLDescargar el documento técnico

Preasignación de conexiones

Asegurar más conexiones por adelantado facilitará el manejo de las solicitudes en el momento en que se haya iniciado la aplicación. Por ejemplo, si su servidor está desarrollado con Java, puede usar vectores para almacenar conexiones inactivas disponibles usando el código a continuación.

availableConnections = new Vector(connections); 
busyConnections = new Vector();
for(int i=0; i<connections; i++) {
availableConnections.addElement(makeNewConnection()); 
}

Supervisión de conexiones disponibles

La clase debería poder verificar cualquier conexión inactiva en una lista de conexiones ocupadas y devolverla. Esto se hace básicamente para reutilizar una conexión o cerrar conexiones que no están en uso. A veces, las conexiones se agotan, por lo tanto, al devolver una conexión, es muy importante verificar si todavía está abierta. De lo contrario, deberá descartar esta conexión y repetir el proceso. Cuando se descarta una conexión, se abre una ranura que se puede utilizar para procesar una nueva conexión cuando se alcanza el límite. Esto se puede lograr con

public synchronized Connection getConnection() throws SQLException {
if (!availableConnections.isEmpty()) { Connection existingConnection =
(Connection)availableConnections.lastElement(); int lastIndex = availableConnections.size() - 1; availableConnections.removeElementAt(lastIndex); if (existingConnection.isClosed()) {
notifyAll(); // Freed up a spot for anybody waiting.
return(getConnection()); // Repeat process. } else {
busyConnections.addElement(existingConnection);
return(existingConnection); }
} }

Asignación de una nueva conexión

Debería poder iniciar un subproceso en segundo plano para asignar una nueva conexión si no hay inactividad disponible y si casi se está alcanzando el límite de conexión.

if ((totalConnections() < maxConnections) && !connectionPending) { // Pending = connecting in bg
makeBackgroundConnection(); }
try {
wait(); // Give up lock and suspend self.
} catch(InterruptedException ie) {} return(getConnection()); // Try again.

Esperando una nueva conexión

Cuando no hay ninguna conexión inactiva y se ha alcanzado el límite de conexiones, la configuración debería poder esperar a que haya una nueva conexión disponible sin agrupación continua. Podemos hacerlo usando el método de espera que proporciona un bloqueo de sincronización de subprocesos y suspende el subproceso hasta que se proporcione una notificación.

try {
     wait();
} catch(InterruptedException ie) {} 
return(getConnection());

Para una buena ética de la aplicación, los clientes no deben esperar en tiempo real por una conexión, sino que lanzarán una excepción cuando las conexiones no estén presentes con el siguiente código:

throw new SQLException("Connection limit reached");

Cerrar la conexión

Cuando las conexiones se recolectan como basura, debe cerrarlas en lugar de hacerlo explícitamente. Sin embargo, si desea un enfoque explícito para cerrar una conexión, puede usar:

public synchronized void closeAllConnections() {
// The closeConnections method loops down Vector, calling // close and ignoring any exceptions thrown. closeConnections(availableConnections); availableConnections = new Vector(); closeConnections(busyConnections);
busyConnections = new Vector();
}

Conclusión

La agrupación de conexiones para PostgreSQL nos ayuda a reducir la cantidad de recursos necesarios para conectarse a la base de datos y mejora la velocidad de conectividad a la base de datos. Esto se logra agrupando las conexiones a la base de datos, manteniendo estas conexiones y, en consecuencia, reduciendo la cantidad de conexiones que deben abrirse.