En el mundo de las bases de datos, hay muchos conceptos comunes como alta disponibilidad, conmutación por error y agrupación de conexiones. Todas ellas son cosas útiles para implementar en cualquier sistema, e incluso imprescindibles en algunos casos.
Una agrupación de conexiones es un método para crear un conjunto de conexiones y reutilizarlas evitando abrir nuevas conexiones a la base de datos todo el tiempo, lo que aumentará considerablemente el rendimiento de sus aplicaciones. PgBouncer es un agrupador de conexiones popular diseñado para PostgreSQL, pero no es suficiente para lograr la alta disponibilidad de PostgreSQL por sí solo, ya que no tiene configuración de múltiples hosts, conmutación por error ni detección.
Usar un Load Balancer es una forma de tener alta disponibilidad en la topología de su base de datos. Podría ser útil para redirigir el tráfico a nodos de bases de datos en buen estado, distribuir el tráfico entre varios servidores para mejorar el rendimiento o simplemente tener un punto final único configurado en su aplicación para una configuración más sencilla y un proceso de conmutación por error. Para esto, HAProxy es una buena opción para complementar su agrupador de conexiones, ya que es un proxy de código abierto que se puede usar para implementar alta disponibilidad, equilibrio de carga y proxy para aplicaciones basadas en TCP y HTTP.
En este blog, utilizaremos ambos conceptos, Load Balancer y Connection pooling (HAProxy + PgBouncer), para implementar un entorno de alta disponibilidad para su base de datos PostgreSQL.
Cómo funciona PgBouncer
PgBouncer actúa como un servidor PostgreSQL, por lo que solo necesita acceder a su base de datos utilizando la información de PgBouncer (dirección IP/nombre de host y puerto), y PgBouncer creará una conexión con el servidor PostgreSQL, o reutilice uno si existe.
Cuando PgBouncer recibe una conexión, realiza la autenticación, que depende del método especificado en el archivo de configuración. PgBouncer admite todos los mecanismos de autenticación que admite el servidor PostgreSQL. Después de esto, PgBouncer busca una conexión en caché, con la misma combinación de nombre de usuario y base de datos. Si se encuentra una conexión en caché, devuelve la conexión al cliente, si no, crea una nueva conexión. Según la configuración de PgBouncer y la cantidad de conexiones activas, es posible que la nueva conexión se ponga en cola hasta que se pueda crear o incluso cancelar.
El comportamiento de PgBouncer depende del modo de agrupación configurado:
- agrupación de sesiones (predeterminado):cuando un cliente se conecta, se le asignará una conexión de servidor durante todo el tiempo que el cliente permanezca conectado. Cuando el cliente se desconecte, la conexión del servidor se volverá a colocar en el grupo.
- agrupación de transacciones :Una conexión de servidor se asigna a un cliente solo durante una transacción. Cuando PgBouncer se dé cuenta de que la transacción ha terminado, la conexión del servidor se volverá a colocar en el grupo.
- combinación de sentencias :la conexión del servidor se volverá a colocar en el grupo inmediatamente después de que se complete una consulta. Las transacciones de estados de cuenta múltiples no están permitidas en este modo porque se romperían.
Para equilibrar las consultas entre varios servidores, en el lado de PgBouncer, puede ser una buena idea hacer que server_lifetime sea más pequeño y también activar server_round_robin. De forma predeterminada, el algoritmo LIFO reutiliza las conexiones inactivas, lo que puede no funcionar tan bien cuando se utiliza un equilibrador de carga.
Cómo instalar PgBouncer
Supondremos que tiene implementado su clúster de PostgreSQL y HAProxy, y que está en funcionamiento; de lo contrario, puede seguir esta publicación de blog para implementar fácilmente PostgreSQL para alta disponibilidad.
Puede instalar PgBouncer en cada nodo de la base de datos o en una máquina externa, en cualquier caso, tendrá algo como esto:
Para obtener el software PgBouncer puede ir a la sección de descargas de PgBouncer, o utilice los repositorios RPM o DEB. Para este ejemplo, usaremos CentOS 8 y lo instalaremos desde el repositorio oficial de PostgreSQL.
Primero, descargue e instale el repositorio correspondiente del sitio de PostgreSQL (si aún no lo tiene instalado):
$ wget https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
$ rpm -Uvh pgdg-redhat-repo-latest.noarch.rpm
Luego, instale el paquete PgBouncer:
$ yum install pgbouncer
Verificar la instalación:
$ pgbouncer --version
PgBouncer 1.14.0
libevent 2.1.8-stable
adns: c-ares 1.13.0
tls: OpenSSL 1.1.1c FIPS 28 May 2019
Cuando se complete, tendrá un nuevo archivo de configuración ubicado en /etc/pgbouncer/pgbouncer.ini:
[databases]
[users]
[pgbouncer]
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = trust
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres
stats_users = stats, postgres
Veamos estos parámetros uno por uno:
- Sección de bases de datos [bases de datos]: Esto contiene pares clave=valor donde la clave se tomará como un nombre de base de datos y el valor como una lista de pares clave=valor al estilo de cadena de conexión libpq.
- Sección de usuario [usuarios]: Esto contiene pares clave=valor donde la clave se tomará como un nombre de usuario y el valor como una lista de estilo de cadena de conexión libpq de pares clave=valor de ajustes de configuración específicos para este usuario.
- archivo de registro :especifica el archivo de registro. El archivo de registro se mantiene abierto, así que después de la rotación matar -HUP o en la consola RECARGAR; debe hacerse.
- pidfile :especifica el archivo PID. Sin el conjunto pidfile, el daemon no está permitido.
- dirección_de_escucha :Especifica una lista de direcciones donde escuchar conexiones TCP. También puede usar * que significa "escuchar en todas las direcciones". Cuando no se establece, solo se aceptan conexiones de socket Unix.
- puerto de escucha: En qué puerto escuchar. Se aplica a los sockets TCP y Unix. El puerto predeterminado es 6432.
- auth_type: Cómo autenticar usuarios.
- archivo_autenticación :El nombre del archivo desde el que cargar nombres de usuario y contraseñas.
- usuarios_administradores :lista separada por comas de los usuarios de la base de datos que pueden conectarse y ejecutar todos los comandos en la consola.
- estadísticas_usuarios :lista separada por comas de los usuarios de la base de datos que pueden conectarse y ejecutar consultas de solo lectura en la consola.
Esta es solo una muestra del archivo de configuración predeterminado, ya que el original tiene 359 líneas, pero el resto de las líneas están comentadas de forma predeterminada. Para obtener todos los parámetros disponibles, puede consultar la documentación oficial.
Cómo usar PgBouncer
Ahora, veamos una configuración básica para que funcione.
El archivo de configuración pgbouncer.ini:
$ cat /etc/pgbouncer/pgbouncer.ini
[databases]
world = host=127.0.0.1 port=5432 dbname=world
[pgbouncer]
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
admin_users = admindb
Y el archivo de autenticación:
$ cat /etc/pgbouncer/userlist.txt
"admindb" "root123"
Entonces, en este caso, instalé PgBouncer en el mismo nodo de la base de datos, escuchando todas las direcciones IP, y se conecta a una base de datos PostgreSQL llamada "mundo". También administro los usuarios permitidos en el archivo userlist.txt con una contraseña de texto sin formato que se puede cifrar si es necesario.
Para iniciar el servicio PgBouncer, solo necesita ejecutar el siguiente comando:
$ pgbouncer -d /etc/pgbouncer/pgbouncer.ini
Donde -d significa "demonio", por lo que se ejecutará en segundo plano.
$ netstat -pltn
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6432 0.0.0.0:* LISTEN 4274/pgbouncer
tcp6 0 0 :::6432 :::* LISTEN 4274/pgbouncer
Como puede ver, PgBouncer está activo y esperando conexiones en el puerto 6432. Para acceder a la base de datos PostgreSQL, ejecute el siguiente comando usando su información local (puerto, host, nombre de usuario y nombre de la base de datos) :
$ psql -p 6432 -h 127.0.0.1 -U admindb world
Password for user admindb:
psql (12.4)
Type "help" for help.
world=#
Recuerde que el nombre de la base de datos (mundo) es la base de datos configurada en su archivo de configuración de PgBouncer:
[databases]
world = host=127.0.0.1 port=5432 dbname=world
Supervisión y administración de PgBouncer
En lugar de acceder a su base de datos PostgreSQL, puede conectarse directamente a PgBouncer para administrarla o monitorearla. Para esto, usa el mismo comando que usaste anteriormente, pero cambia la base de datos a “pgbouncer”:
$ psql -p 6432 -h 127.0.0.1 -U admindb pgbouncer
Password for user admindb:
psql (12.4, server 1.14.0/bouncer)
Type "help" for help.
pgbouncer=# SHOW HELP;
NOTICE: Console usage
DETAIL:
SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|USERS|VERSION
SHOW FDS|SOCKETS|ACTIVE_SOCKETS|LISTS|MEM
SHOW DNS_HOSTS|DNS_ZONES
SHOW STATS|STATS_TOTALS|STATS_AVERAGES|TOTALS
SET key = arg
RELOAD
PAUSE [<db>]
RESUME [<db>]
DISABLE <db>
ENABLE <db>
RECONNECT [<db>]
KILL <db>
SUSPEND
SHUTDOWN
SHOW
Ahora, puede ejecutar diferentes comandos de PgBouncer para monitorearlo:
MOSTRAR ESTADÍSTICAS_TOTALES:
pgbouncer=# SHOW STATS_TOTALS;
database | xact_count | query_count | bytes_received | bytes_sent | xact_time | query_time | wait_time
-----------+------------+-------------+----------------+------------+-----------+------------+-----------
pgbouncer | 1 | 1 | 0 | 0 | 0 | 0 | 0
world | 2 | 2 | 59 | 234205 | 8351 | 8351 | 4828
(2 rows)
MOSTRAR SERVIDORES:
pgbouncer=# SHOW SERVERS;
type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time
| wait | wait_us | close_needed | ptr | link | remote_pid | tls
------+---------+----------+--------+-----------+------+------------+------------+-------------------------+-------------------------
+------+---------+--------------+----------------+----------------+------------+-----
S | admindb | world | active | 127.0.0.1 | 5432 | 127.0.0.1 | 45052 | 2020-09-09 18:31:57 UTC | 2020-09-09 18:32:04 UTC
| 0 | 0 | 0 | 0x55b04a51b3d0 | 0x55b04a514810 | 5738 |
(1 row)
MOSTRAR CLIENTES:
pgbouncer=# SHOW CLIENTS;
type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time
| wait | wait_us | close_needed | ptr | link | remote_pid | tls
------+---------+-----------+--------+-----------+-------+------------+------------+-------------------------+-----------------------
--+------+---------+--------------+----------------+----------------+------------+-----
C | admindb | pgbouncer | active | 127.0.0.1 | 46950 | 127.0.0.1 | 6432 | 2020-09-09 18:29:46 UTC | 2020-09-09 18:55:11 UT
C | 1441 | 855140 | 0 | 0x55b04a5145e0 | | 0 |
C | admindb | world | active | 127.0.0.1 | 47710 | 127.0.0.1 | 6432 | 2020-09-09 18:31:41 UTC | 2020-09-09 18:32:04 UT
C | 0 | 0 | 0 | 0x55b04a514810 | 0x55b04a51b3d0 | 0 |
(2 rows)
MOSTRAR PISCINAS:
pgbouncer=# SHOW POOLS;
database | user | cl_active | cl_waiting | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us | pool_
mode
-----------+-----------+-----------+------------+-----------+---------+---------+-----------+----------+---------+------------+------
-----
pgbouncer | pgbouncer | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | state
ment
world | admindb | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | sessi
on
(2 rows)
Y gestionarlo...
VOLVER A CARGAR:
pgbouncer=# RELOAD;
RELOAD
PAUSA:
pgbouncer=# PAUSE world;
PAUSE
REANUDAR:
pgbouncer=# RESUME world;
RESUME
Esos comandos son solo un ejemplo. Para obtener una lista completa de comandos, consulte la documentación oficial.
Conclusión
Usar una combinación de PgBouncer + HAProxy + PostgreSQL es una buena forma de lograr alta disponibilidad para su clúster de PostgreSQL mejorando al mismo tiempo el rendimiento de su base de datos.
Como puede ver, si tiene instalado su entorno PostgreSQL, que puede implementar usando ClusterControl con solo unos pocos clics, puede agregar fácilmente PgBouncer para aprovechar las ventajas de tener un agrupador de conexiones para sus sistemas.