Alta disponibilidade / escalabilidade do PostgreSQL usando HAProxy e PGBouncer

17

Eu tenho vários servidores PostgreSQL para uma aplicação web. Normalmente, um mestre e vários escravos no modo de espera ativa (replicação de streaming assíncrona).

Uso o PGBouncer para o pool de conexões: uma instância instalada em cada servidor PG (porta 6432) conectando-se ao banco de dados no host local. Eu uso o modo de pool de transações.

Para balancear a carga de minhas conexões somente leitura em escravos, eu uso o HAProxy (v1.5) com um conf mais ou menos assim:

listen pgsql_pool 0.0.0.0:10001
        mode tcp
        option pgsql-check user ha
        balance roundrobin
        server master 10.0.0.1:6432 check backup
        server slave1 10.0.0.2:6432 check
        server slave2 10.0.0.3:6432 check
        server slave3 10.0.0.4:6432 check

Portanto, meu aplicativo da Web se conecta ao haproxy (porta 10001), que conexões de balanceamento de carga em vários pgbouncer configurados em cada escravo PG.

Aqui está um gráfico de representação da minha arquitetura atual:

haproxy> pgbouncer> postgresql

Isso funciona muito bem assim, mas percebo que alguns implementam isso de maneira bem diferente: o aplicativo da web se conecta a uma única instância do PGBouncer que se conecta ao HAproxy, que balança a carga em vários servidores PG:

pgbouncer> haproxy> postgresql

Qual é a melhor abordagem? O primeiro (meu atual) ou o segundo? Existem vantagens de uma solução em relação à outra?

obrigado

Nicolas Payart
fonte

Respostas:

10

Sua configuração existente do HAProxy -> PGBouncer -> PGServer é melhor. E isso só funciona. Aqui está o motivo: HAProxy redireciona a conexão para diferentes servidores. isso resulta na alteração do endereço MAC na conexão com o banco de dados. Portanto, se o PGBouncer estiver acima do HAProxy, sempre que as conexões no pool forem invalidadas devido à alteração do endereço MAC.

Jobin Augustine
fonte
7

O pgbouncer mantém conexões em um pool com um servidor postgres. Os tempos de estabelecimento da conexão TCP são significativos em um ambiente de alto volume.

Os clientes que fizerem um grande número de solicitações de banco de dados precisarão configurar uma conexão com um PGBouncer remoto para cada solicitação. Isso é mais caro do que executar o PgBouncer localmente (para que o aplicativo se conecte ao pgbouncer localmente) e o pgBouncer mantenha um conjunto de conexões com o servidor PG remoto.

Portanto, IMO, PGBouncer -> HAProxy -> PGServer parece ser melhor que, HAProxy -> PGBouncer -> PGServer, especialmente quando o PGBouncer é local para o aplicativo cliente.

donatello
fonte
1

Eu tenho que discordar da resposta fornecida por donatello.

Veja bem, se seu aplicativo não gerenciar conexões de banco de dados usando um pool local, ele criará uma nova conexão sempre que precisar consultar o banco de dados; isso acontece exatamente da mesma maneira ao usar o PgBouncer, portanto você terá uma melhoria muito boa ao usá-lo.

Quando o PgBouncer está gerenciando as conexões do PostgreSQL agrupando-as, o tempo que o aplicativo gasta na abertura de uma conexão cai significativamente, em comparação com o momento em que a conexão é aberta diretamente no DB. Isso ocorre porque o PG é muito lento para verificar e verificar credenciais e tudo sempre que uma conexão é solicitada.

Portanto, a abordagem App -> HAProxy -> [PgBouncer -> PostgreSQL] é a melhor, porque o PgBouncer economiza o tempo de conexão com o PG. O modo de agrupamento também é importante de levar em consideração. Você precisa estar ciente da maneira como seu aplicativo se comporta. É principalmente transacional? Ou, é mais executar um monte de pequenas frases SQL com alta simultaneidade? Todos esses parâmetros afetam o desempenho.

Alvaro
fonte