PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Pool de conexões PostgreSQL com PgBouncer


O pool de conexões é uma maneira simples, mas eficaz, de melhorar o desempenho de seus aplicativos e diminuir a carga em seus servidores PostgreSQL. Continue lendo para saber mais sobre como usar o PgBouncer para agrupar conexões PostgreSQL.

Por que o pool de conexões?


O PostgreSQL tem uma arquitetura de manipulação de conexão bastante pesada. Para cada conexão de entrada, o postmaster (o daemon principal do Postgres) cria um novo processo (convencionalmente chamado de backend ) para lidar com isso. Embora esse design forneça melhor estabilidade e isolamento, não o torna particularmente eficiente no manuseio de conexões de curta duração. Uma nova conexão de cliente Postgres envolve configuração TCP, criação de processos e inicialização de back-end – todos custosos em termos de tempo e recursos do sistema.

Obviamente, isso só é um problema se as conexões forem criadas com muita frequência e descartadas sem reutilização. Infelizmente, não é incomum ter um cluster de nós da web executando aplicativos escritos em PHP ou outras linguagens que precisam se conectar ao banco de dados uma vez por carregamento de página. Trabalhos em lote que rapidamente fazem um monte de conexões em rápida sucessão também são comuns. Empregando connectionpooling em tais cenários pode reduzir drasticamente a carga em seu servidor PostgreSQL e melhorar drasticamente as latências de consulta.

Com o pool de conexões, os clientes se conectam a um servidor proxy que mantém um conjunto de conexões diretas com o servidor PostgreSQL real. Normalmente, os clientes não percebem (e não devem) perceber que estão conectados a um servidor proxy e não ao servidor real. O proxy pode ser executado no mesmo nó que o cliente (por exemplo, em cada nó da web), caso em que os clientes podem se conectar ao proxy através de soquetes de domínio Unix que têm uma sobrecarga de conexão muito baixa. Mesmo que o proxy esteja em outro nó e o cliente precise de uma conexão TCP para alcançar o proxy, a sobrecarga de um novo backend Postgres pode ser evitada.

O que é o PgBouncer?


O PgBouncer é um pool de conexões binárias simples, leve e de código aberto para PostgreSQL. Ele pode agrupar conexões com um ou mais bancos de dados (em servidores possivelmente diferentes) e atender clientes em soquetes de domínio TCP e Unix.

O PgBouncer mantém um pool de conexões para cada usuário único, par de banco de dados. Normalmente, ele é configurado para distribuir uma dessas conexões para uma nova conexão de cliente recebida e devolvê-la ao pool quando o cliente se desconecta. Você pode configurar o PgBouncer para fazer um pool de forma mais agressiva, para que ele possa pegar e retornar a conexão ao pool nos limites de transação ou instrução em vez de limites de conexão. Há algumas consequências potencialmente indesejáveis ​​para isso, no entanto.

Você deve conseguir instalar o PgBouncer com o gerenciador de pacotes da sua distribuição:
# RedHat/CentOS/..
$ sudo yum install pgbouncer

# Debian/Ubuntu/..
$ sudo apt-get install pgbouncer

Ele também está disponível nos repositórios padrão Postgres APT e YUM, que podem ser usados ​​se os pacotes da sua distribuição forem antigos ou quebrados.

O PgBouncer depende de um arquivo de configuração principal, normalmente armazenado como/etc/pgbouncer/pgbouncer.ini . Você pode invocar o pgbouncer como um serviço do systemd, ou simplesmente executá-lo mesmo sem privilégios de superusuário com o caminho para este arquivo de configuração.

Para dar uma olhada, vamos criar um banco de dados db1 e um usuário user1 em nosso servidor:
$ sudo -u postgres psql
psql (10.6 (Debian 10.6-1.pgdg90+1))
Type "help" for help.

postgres=# create user user1 password 'user1pass';
CREATE ROLE
postgres=# create database db1 owner user1;
CREATE DATABASE
postgres=#

Os clientes se conectarão ao banco de dados db1 com o nome de usuário user1 e senha user1pass . Nosso objetivo é fazer com que os clientes se conectem ao PgBouncer, que fará o proxy e agrupará as conexões com o servidor real.

Agora vamos criar um arquivo (em qualquer lugar) com este conteúdo:
[databases]
db1 = host=localhost dbname=db1

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 16432
auth_file = userlist.txt

Também precisamos criar um arquivo “userlist.txt” no mesmo diretório, com o nome de usuário e senhas (com hash) dos usuários que o PgBouncer permitirá conectar. Crie “userlist.txt” com o seguinte conteúdo:
"user1" "md5638b81c77071ea624d1ad4adb1433540"

O segundo valor é o MD5 de “user1passuser1”, prefixado com “md5”. Esta é a convenção usual do Postgres.

Agora vamos iniciar o PgBouncer em primeiro plano:
$ /usr/sbin/pgbouncer pgbouncer.ini
2019-02-05 11:46:18.011 10033 LOG file descriptor limit: 1024 (H:1048576), max_client_conn: 100, max fds possible: 130
2019-02-05 11:46:18.012 10033 LOG listening on 127.0.0.1:16432
2019-02-05 11:46:18.013 10033 LOG listening on unix:/tmp/.s.PGSQL.16432
2019-02-05 11:46:18.014 10033 LOG process up: pgbouncer 1.9.0, libevent 2.0.21-stable (epoll), adns: c-ares 1.12.0, tls: OpenSSL 1.1.0j  20 Nov 2018

Iniciamos agora um PgBouncer que está escutando na porta TCP 16432 127.0.0.1, bem como no soquete de domínio Unix /tmp/.s.PGSQL.16432 . O único “banco de dados” disponível neste servidor proxy é db1 . O único usuário que pode se conectar a este servidor é user1 . Vamos tentar conectar com psql :
$ psql -U user1 -p 16432 -h localhost db1
Password for user user1:
psql (10.6 (Debian 10.6-1.pgdg90+1))
Type "help" for help.

db1=> select inet_server_addr(), inet_server_port();
 inet_server_addr | inet_server_port
------------------+------------------
 127.0.0.1        |             5432
(1 row)

db1=>

O cliente (psql) se conecta com sucesso ao localhost:16432, mas você pode ver que a conexão está realmente sendo proxy para localhost:5432.

Você pode tentar desconectar e conectar novamente algumas vezes e, em seguida, verificar quantas conexões ainda existem no servidor real:
postgres=# select count(*) from pg_stat_activity
postgres-#   where datname='db1' and usename='user1';
 count
-------
     1
(1 row)

O PgBouncer não desconectará a conexão real quando o cliente se desconectar. Você pode configurar as conexões mínimas, máximas e reservadas que o PgBouncer manterá para cada pool no arquivo de configuração.

Implantando o PgBouncer


Onde você instala e executa o PgBouncer? Existem diferentes respostas, com diferentes vantagens:
  • No nó do servidor Postgres :Você pode instalá-lo junto com o próprio PostgreSQLserver, no mesmo nó. Os clientes se conectam à porta PgBouncer em vez da porta Postgres. Isso tem o efeito de um Postgres “aprimorado” que faz o pool de conexões internamente. Você também só precisa manter uma cópia dos arquivos de configuração do PgBouncer. Por outro lado, isso envolve realmente executar outra coisa também no nó do servidor PostgreSQL, o que pode não ser fácil ou permitido (firewalls, políticas) ou mesmo possível (AWSRDS).
  • Nos nós do cliente :Você pode instalar o PgBouncer em cada nó cliente, por exemplo, cada nó da web executa Apache e PHP, e os scripts PHP se conectam ao localPgBouncer. Isso tem a vantagem de não ter que atrapalhar a configuração do servidor, e a configuração do pool pode ser usada para manter a carga do servidor previsível. tráfego, o servidor pode ficar sobrecarregado rapidamente.
  • Como um cluster autônomo :a terceira opção para ter um cluster de nós PgBouncer independentes e sem estado, liderados por um balanceador de carga TCP como o HAProxy. Esta configuração, embora seja mais complicada do que as outras duas opções, oferece o máximo de controle e configurabilidade.

Administração


O PgBouncer permite que usuários marcados como administradores se conectem a um banco de dados virtual chamado “pgbouncer” e emitam comandos para controlar o servidor e ver estatísticas. Para tentar isso, vamos primeiro marcar “user1” como administrador modificando o arquivo pgbouncer.ini:
[databases]
db1 = host=localhost dbname=db1

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 16432
auth_file = userlist.txt
admin_users = user1

Agora user1 pode se conectar ao banco de dados chamado “pgbouncer”:
$ psql -U user1 -p 16432 -h localhost pgbouncer
Password for user user1:
psql (10.6 (Debian 10.6-1.pgdg90+1), server 1.9.0/bouncer)
Type "help" for help.

pgbouncer=#

A partir daqui, você pode fazer várias coisas, como habilitar ou desabilitar um determinado banco de dados, inspecionar e recarregar a configuração e muito mais:
pgbouncer=# RELOAD;
RELOAD
pgbouncer=# DISABLE db1;
DISABLE
pgbouncer=# ENABLE db1;
ENABLE
pgbouncer=# SHOW FDS;
 fd |  task  | user  | database |   addr    | port  |     cancel     | link | client_encoding | std_strings | datestyle | timezone  | pa
----+--------+-------+----------+-----------+-------+----------------+------+-----------------+-------------+-----------+-----------+---
  6 | pooler |       |          | 127.0.0.1 | 16432 |              0 |    0 |                 |             |           |           |
  7 | pooler |       |          | unix      | 16432 |              0 |    0 |                 |             |           |           |
  9 | server | user1 | db1      | 127.0.0.1 |  5432 | 45404395804679 |    0 | UTF8            | on          | ISO, MDY  | localtime |
(3 rows)

Monitoramento


Existem também comandos para mostrar várias estatísticas sobre o PgBouncer, incluindo:
  • Estatísticas por banco de dados sobre duração da consulta, tempo de espera do cliente, uso da rede, contagens de transações
  • Estatísticas por pool sobre o número de clientes ativos e em espera, conexões ociosas e de servidor usado

As estatísticas são recuperadas com comandos de estilo “SHOW xyz”, como este para obter estatísticas relacionadas ao pool:
pgbouncer=# SHOW POOLS;
-[ RECORD 1 ]---------
database   | db1
user       | user1
cl_active  | 0
cl_waiting | 0
sv_active  | 0
sv_idle    | 0
sv_used    | 1
sv_tested  | 0
sv_login   | 0
maxwait    | 0
maxwait_us | 0
pool_mode  | session
-[ RECORD 2 ]---------
database   | pgbouncer
user       | pgbouncer
cl_active  | 1
cl_waiting | 0
sv_active  | 0
sv_idle    | 0
sv_used    | 0
sv_tested  | 0
sv_login   | 0
maxwait    | 0
maxwait_us | 0
pool_mode  | statement

Leitura complementar


A Home Page do PgBouncer tem mais detalhes sobre todos os vários recursos e opções de configuração do PgBouncer.
  • Página inicial do PgBouncer
  • Repositório GitHub do PgBouncer
  • Postgres Wikitem informações sobre pool de conexões
  • Pgpool é outra opção para pool de conexões