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:
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:
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
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.
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.
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.