web-dev-qa-db-fra.com

Haute disponibilité / évolutivité de PostgreSQL avec HAProxy et PGBouncer

J'ai plusieurs serveurs PostgreSQL pour une application Web. Généralement, un maître et plusieurs esclaves en mode de redondance d'UC (réplication de streaming asynchrone).

J'utilise PGBouncer pour la mise en commun des connexions: une instance installée sur chaque serveur PG (port 6432) se connectant à la base de données sur localhost. J'utilise le mode pool de transactions.

Afin d'équilibrer la charge de mes connexions en lecture seule sur les esclaves, j'utilise HAProxy (v1.5) avec une conf plus ou moins comme ceci:

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

Ainsi, mon application Web se connecte à haproxy (port 10001), qui équilibre la charge des connexions sur plusieurs pgbouncer configurés sur chaque esclave PG.

Voici un graphique de représentation de mon architecture actuelle:

haproxy > pgbouncer > postgresql

Cela fonctionne assez bien comme ceci, mais je me rends compte que certains implémentent cela assez différemment: l'application Web se connecte à une seule instance PGBouncer qui se connecte à HAproxy qui équilibre la charge sur plusieurs serveurs PG:

pgbouncer > haproxy > postgresql

Quelle est la meilleure approche? Le premier (mon actuel) ou le second? Y a-t-il des avantages d'une solution par rapport à l'autre?

Merci

18
Nicolas Payart

Votre configuration existante de HAProxy -> PGBouncer -> PGServer est meilleure. Et cela ne fonctionne que. Voici la raison: HAProxy redirige la connexion vers différents serveurs. cela entraîne un changement d'adresse MAC dans la connexion à la base de données. Donc, si PGBouncer est supérieur à HAProxy, chaque fois que les connexions dans le pool sont invalidées en raison d'un changement d'adresse MAC.

10
Jobin Augustine

pgbouncer maintient les connexions dans un pool avec un serveur postgres. TCP les temps d'établissement de connexion sont importants dans un environnement à volume élevé.

Les clients effectuant un grand nombre de demandes de base de données devront établir une connexion avec un PGBouncer distant pour chaque demande. C'est plus cher que d'exécuter PgBouncer localement (donc l'application se connecte localement à pgbouncer) et pgBouncer maintient un pool de connexions avec le serveur PG distant.

Ainsi, IMO, PGBouncer -> HAProxy -> PGServer semble être meilleur que, HAProxy -> PGBouncer -> PGServer, surtout lorsque le PGBouncer est local à l'application cliente.

7
donatello

Je ne suis pas d'accord avec la réponse fournie par donatello.

Vous voyez, si votre application ne gère pas les connexions de base de données à l'aide d'un pool local, elle créera une nouvelle connexion chaque fois qu'elle devra interroger la base de données; cela se produit exactement de la même manière lorsque vous utilisez PgBouncer, vous aurez donc une très bonne amélioration en l'utilisant.

Lorsque PgBouncer gère les connexions PostgreSQL en les regroupant, le temps que votre application passe à ouvrir une connexion diminue considérablement, par rapport à l'ouverture de la connexion directement à la base de données. C'est parce que PG est assez lent pour vérifier et vérifier les informations d'identification et tout à chaque fois qu'une connexion est demandée.

Ainsi, l'approche App -> HAProxy -> [PgBouncer -> PostgreSQL] est la meilleure, car PgBouncer économise le temps de connexion à PG. Le mode de mise en commun est également important à prendre en compte. Vous devez être conscient du comportement de votre application. Est-ce principalement transactionnel? Ou, s'agit-il plutôt d'exécuter un tas de petites phrases SQL avec une concurrence élevée? Tous ces paramètres ont un effet sur les performances.

2
Alvaro