In de databasewereld zijn er veel algemene concepten zoals hoge beschikbaarheid, failover en pooling van verbindingen. Het zijn allemaal nuttige dingen om op elk systeem te implementeren, en in sommige gevallen zelfs een must.
Een pooling van verbindingen is een methode om een pool van verbindingen te maken en deze opnieuw te gebruiken, waarbij wordt vermeden dat er steeds nieuwe verbindingen met de database moeten worden geopend, wat de prestaties van uw toepassingen aanzienlijk zal verbeteren. PgBouncer is een populaire pooler voor verbindingen die is ontworpen voor PostgreSQL, maar het is niet voldoende om alleen PostgreSQL High Availability te bereiken, aangezien het geen configuratie voor meerdere hosts, failover of detectie heeft.
Het gebruik van een Load Balancer is een manier om hoge beschikbaarheid in uw databasetopologie te hebben. Het kan handig zijn om verkeer om te leiden naar gezonde databaseknooppunten, om het verkeer over meerdere servers te verdelen om de prestaties te verbeteren, of om een enkel eindpunt in uw toepassing te configureren voor een eenvoudiger configuratie- en failoverproces. Hiervoor is HAProxy een goede optie om uw verbindingspooler aan te vullen, aangezien het een open-sourceproxy is die kan worden gebruikt voor het implementeren van hoge beschikbaarheid, taakverdeling en proxying voor op TCP en HTTP gebaseerde toepassingen.
In deze blog zullen we beide concepten, Load Balancer en Connection pooling (HAProxy + PgBouncer), gebruiken om een High Availability-omgeving voor uw PostgreSQL-database te implementeren.
Hoe PgBouncer werkt
PgBouncer fungeert als een PostgreSQL-server, dus u hoeft alleen maar toegang te krijgen tot uw database met behulp van de PgBouncer-informatie (IP-adres/hostnaam en poort), en PgBouncer zal een verbinding maken met de PostgreSQL-server, anders zal het hergebruik er een als deze bestaat.
Wanneer PgBouncer een verbinding ontvangt, voert het de authenticatie uit, die afhangt van de methode gespecificeerd in het configuratiebestand. PgBouncer ondersteunt alle authenticatiemechanismen die de PostgreSQL-server ondersteunt. Hierna controleert PgBouncer op een gecachte verbinding, met dezelfde gebruikersnaam + database-combinatie. Als er een verbinding in de cache wordt gevonden, wordt de verbinding naar de client geretourneerd, zo niet, dan wordt een nieuwe verbinding gemaakt. Afhankelijk van de PgBouncer-configuratie en het aantal actieve verbindingen, kan het zijn dat de nieuwe verbinding in de wachtrij wordt geplaatst totdat deze kan worden gemaakt of zelfs wordt afgebroken.
Het PgBouncer-gedrag hangt af van de geconfigureerde poolmodus:
- sessie poolen (standaard):Wanneer een client verbinding maakt, wordt er een serververbinding aan toegewezen voor de hele duur dat de client verbonden blijft. Wanneer de client de verbinding verbreekt, wordt de serververbinding weer in de pool gezet.
- transactie pooling :Een serververbinding wordt alleen tijdens een transactie aan een client toegewezen. Wanneer PgBouncer merkt dat de transactie voorbij is, wordt de serververbinding weer in de pool gezet.
- statement pooling :De serververbinding wordt onmiddellijk teruggezet in de pool nadat een query is voltooid. Transacties met meerdere afschriften zijn in deze modus niet toegestaan omdat ze zouden breken.
Om query's tussen verschillende servers te verdelen, kan het aan de PgBouncer-kant een goed idee zijn om server_lifetime kleiner te maken en ook server_round_robin in te schakelen. Standaard worden inactieve verbindingen hergebruikt door het LIFO-algoritme, wat mogelijk niet zo goed werkt wanneer een load-balancer wordt gebruikt.
PgBouncer installeren
We gaan ervan uit dat u uw PostgreSQL-cluster en HAProxy hebt geïmplementeerd en dat deze actief is, anders kunt u deze blogpost volgen om PostgreSQL eenvoudig te implementeren voor hoge beschikbaarheid.
Je kunt PgBouncer op elk databaseknooppunt of op een externe machine installeren, in ieder geval heb je zoiets als dit:
Om de PgBouncer-software te downloaden, gaat u naar de PgBouncer-downloadsectie, of gebruik de RPM- of DEB-repository's. Voor dit voorbeeld gebruiken we CentOS 8 en installeren we het vanuit de officiële PostgreSQL-repository.
Download en installeer eerst de bijbehorende repository van de PostgreSQL-site (als je deze nog niet hebt geïnstalleerd):
$ 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
Installeer vervolgens het PgBouncer-pakket:
$ yum install pgbouncer
Verifieer de installatie:
$ 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
Als het klaar is, heb je een nieuw configuratiebestand in /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
Laten we deze parameters een voor een bekijken:
- Sectie Databases [databases]: Dit bevat sleutel=waarde-paren waarbij de sleutel wordt genomen als een databasenaam en de waarde als een libpq-verbindingsreeksstijllijst van sleutel=waarde-paren.
- Gebruikerssectie [gebruikers]: Dit bevat sleutel=waarde-paren waarbij de sleutel wordt genomen als gebruikersnaam en de waarde als een libpq-verbindingsreeksstijllijst van sleutel=waardeparen van configuratie-instellingen die specifiek zijn voor deze gebruiker.
- logbestand :Specificeert het logbestand. Het logbestand wordt opengehouden, dus kill -HUP of op console RELOAD na het draaien; moet worden gedaan.
- pidfile :Specificeert het PID-bestand. Zonder de pidfile-set is de daemon niet toegestaan.
- listen_addr :specificeert een lijst met adressen waar naar TCP-verbindingen moet worden geluisterd. U kunt ook * gebruiken, wat betekent "luister op alle adressen". Indien niet ingesteld, worden alleen Unix-socketverbindingen geaccepteerd.
- listen_port: Op welke poort te luisteren. Geldt voor zowel TCP- als Unix-sockets. De standaardpoort is 6432.
- auth_type: Gebruikers authenticeren.
- auth_file :De naam van het bestand waaruit gebruikersnamen en wachtwoorden moeten worden geladen.
- admin_users :door komma's gescheiden lijst van databasegebruikers die verbinding mogen maken en alle opdrachten op de console mogen uitvoeren.
- stats_users :door komma's gescheiden lijst van databasegebruikers die verbinding mogen maken en alleen-lezen query's op de console mogen uitvoeren.
Dit is slechts een voorbeeld van het standaardconfiguratiebestand, aangezien het origineel 359 regels heeft, maar de rest van de regels zijn standaard weggelaten. Om alle beschikbare parameters te krijgen, kun je de officiële documentatie raadplegen.
PgBouncer gebruiken
Laten we nu eens een basisconfiguratie bekijken om het te laten werken.
Het pgbouncer.ini-configuratiebestand:
$ 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
En het authenticatiebestand:
$ cat /etc/pgbouncer/userlist.txt
"admindb" "root123"
Dus in dit geval heb ik PgBouncer in hetzelfde databaseknooppunt geïnstalleerd, luisterend naar alle IP-adressen, en het maakt verbinding met een PostgreSQL-database genaamd "world". Ik beheer ook de toegestane gebruikers in het bestand userlist.txt met een wachtwoord in platte tekst dat indien nodig kan worden versleuteld.
Om de PgBouncer-service te starten, hoeft u alleen maar de volgende opdracht uit te voeren:
$ pgbouncer -d /etc/pgbouncer/pgbouncer.ini
Waar -d "daemon" betekent, dus het zal op de achtergrond draaien.
$ 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
Zoals u kunt zien, is PgBouncer klaar voor verbindingen in poort 6432. Om toegang te krijgen tot de PostgreSQL-database, voert u de volgende opdracht uit met uw lokale informatie (poort, host, gebruikersnaam en databasenaam) :
$ psql -p 6432 -h 127.0.0.1 -U admindb world
Password for user admindb:
psql (12.4)
Type "help" for help.
world=#
Houd er rekening mee dat de databasenaam (wereld) de database is die is geconfigureerd in uw PgBouncer-configuratiebestand:
[databases]
world = host=127.0.0.1 port=5432 dbname=world
PgBouncer bewaken en beheren
In plaats van toegang te krijgen tot uw PostgreSQL-database, kunt u rechtstreeks verbinding maken met PgBouncer om deze te beheren of te bewaken. Gebruik hiervoor hetzelfde commando dat je eerder gebruikte, maar verander de database in "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
Je kunt nu verschillende PgBouncer-commando's uitvoeren om het te controleren:
SHOW STATS_TOTALS:
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)
SERVERS TONEN:
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)
TOEN KLANTEN:
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)
TOON ZWEMBADEN:
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)
En om het te beheren...
HERLADEN:
pgbouncer=# RELOAD;
RELOAD
PAUZE:
pgbouncer=# PAUSE world;
PAUSE
RESUME:
pgbouncer=# RESUME world;
RESUME
Deze commando's zijn slechts een voorbeeld. Raadpleeg de officiële documentatie voor een volledige lijst met opdrachten.
Conclusie
Het gebruik van een combinatie van PgBouncer + HAProxy + PostgreSQL is een goede manier om hoge beschikbaarheid voor uw PostgreSQL-cluster te bereiken en tegelijkertijd uw databaseprestaties te verbeteren.
Zoals u kunt zien, kunt u, als u over uw PostgreSQL-omgeving beschikt, die u met ClusterControl in slechts een paar klikken kunt implementeren, eenvoudig PgBouncer toevoegen om te profiteren van een verbindingspooler voor uw systemen.