I databaseverdenen er der mange almindelige begreber som High Availability, Failover og Connection pooling. Alle af dem er nyttige ting at implementere på ethvert system, og endda et must i nogle tilfælde.
En forbindelsespooling er en metode til at skabe en pulje af forbindelser og genbruge dem og undgå at åbne nye forbindelser til databasen hele tiden, hvilket vil øge ydeevnen af dine applikationer betydeligt. PgBouncer er en populær forbindelsespooler designet til PostgreSQL, men det er ikke nok til at opnå PostgreSQL High Availability alene, da det ikke har multi-host-konfiguration, failover eller detektion.
Brug af en Load Balancer er en måde at få høj tilgængelighed i din databasetopologi. Det kan være nyttigt til at omdirigere trafik til sunde databasenoder, distribuere trafikken på tværs af flere servere for at forbedre ydeevnen eller bare have et enkelt slutpunkt konfigureret i din applikation for en nemmere konfiguration og failover-proces. Til dette er HAProxy en god mulighed for at komplementere din forbindelsespooler, da det er en open source-proxy, der kan bruges til at implementere høj tilgængelighed, belastningsbalancering og proxy for TCP- og HTTP-baserede applikationer.
I denne blog vil vi bruge begge koncepter, Load Balancer og Connection pooling (HAProxy + PgBouncer), til at implementere et High Availability-miljø til din PostgreSQL-database.
Sådan fungerer PgBouncer
PgBouncer fungerer som en PostgreSQL-server, så du skal bare have adgang til din database ved hjælp af PgBouncer-oplysningerne (IP-adresse/værtsnavn og port), og PgBouncer vil oprette en forbindelse til PostgreSQL-serveren, eller det vil genbrug en, hvis den findes.
Når PgBouncer modtager en forbindelse, udfører den godkendelsen, som afhænger af metoden specificeret i konfigurationsfilen. PgBouncer understøtter alle de godkendelsesmekanismer, som PostgreSQL-serveren understøtter. Herefter søger PgBouncer for en cache-forbindelse med den samme brugernavn+databasekombination. Hvis der findes en cachelagret forbindelse, returnerer den forbindelsen til klienten, hvis ikke, opretter den en ny forbindelse. Afhængigt af PgBouncer-konfigurationen og antallet af aktive forbindelser, kan det være muligt, at den nye forbindelse er i kø, indtil den kan oprettes eller endda afbrydes.
PgBouncer-adfærden afhænger af den konfigurerede pooling-tilstand:
- session pooling (standard):Når en klient opretter forbindelse, vil en serverforbindelse blive tildelt den i hele den varighed, klienten forbliver forbundet. Når klienten afbryder forbindelsen, vil serverforbindelsen blive sat tilbage i puljen.
- transaktionspooling :En serverforbindelse tildeles kun til en klient under en transaktion. Når PgBouncer bemærker, at transaktionen er overstået, vil serverforbindelsen blive sat tilbage i puljen.
- sætningspooling :Serverforbindelsen vil blive sat tilbage i puljen umiddelbart efter, at en forespørgsel er fuldført. Transaktioner med flere erklæringer er ikke tilladt i denne tilstand, da de ville gå i stykker.
For at afbalancere forespørgsler mellem flere servere, på PgBouncer-siden, kan det være en god idé at gøre server_lifetime mindre og også slå server_round_robin til. Som standard genbruges inaktive forbindelser af LIFO-algoritmen, som muligvis ikke fungerer så godt, når der bruges en load-balancer.
Sådan installeres PgBouncer
Vi antager, at du har din PostgreSQL-klynge og HAProxy installeret, og den er oppe og køre, ellers kan du følge dette blogindlæg for nemt at implementere PostgreSQL for høj tilgængelighed.
Du kan installere PgBouncer på hver databasenode eller på en ekstern maskine, under alle omstændigheder vil du have noget som dette:
For at få PgBouncer-softwaren kan du gå til PgBouncer-downloadsektionen eller brug RPM- eller DEB-lagrene. Til dette eksempel vil vi bruge CentOS 8 og installere det fra det officielle PostgreSQL-lager.
Først skal du downloade og installere det tilsvarende lager fra PostgreSQL-webstedet (hvis du ikke har det på plads endnu):
$ 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
Installer derefter PgBouncer-pakken:
$ yum install pgbouncer
Bekræft installationen:
$ 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
Når det er gennemført, vil du have en ny konfigurationsfil placeret i /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
Lad os se disse parametre én efter én:
- Databasesektionen [databaser]: Dette indeholder key=value-par, hvor nøglen tages som et databasenavn og værdien som en libpq-forbindelsesstrengstilliste med key=value-par.
- Brugersektion [brugere]: Dette indeholder nøgle=værdi-par, hvor nøglen tages som et brugernavn og værdien som en libpq-forbindelsesstrengstilliste over nøgle=værdi-par af konfigurationsindstillinger, der er specifikke for denne bruger.
- logfil :Specificerer logfilen. Logfilen holdes åben, så efter rotation dræb -HUP eller på konsollen RELOAD; skal gøres.
- pidfil :Specificerer PID-filen. Uden pid-filen er dæmonen ikke tilladt.
- listen_addr :Angiver en liste over adresser, hvor der skal lyttes efter TCP-forbindelser. Du kan også bruge *, der betyder "lyt på alle adresser". Når den ikke er indstillet, accepteres kun Unix-stikforbindelser.
- lytteport: Hvilken port at lytte på. Gælder både TCP- og Unix-stik. Standardporten er 6432.
- auth_type: Sådan godkendes brugere.
- auth_file :Navnet på filen, der skal indlæses brugernavne og adgangskoder fra.
- admin_users :Kommasepareret liste over databasebrugere, der har tilladelse til at oprette forbindelse og køre alle kommandoer på konsollen.
- stats_users :Kommasepareret liste over databasebrugere, der har tilladelse til at oprette forbindelse og køre skrivebeskyttede forespørgsler på konsollen.
Dette er kun et eksempel på standardkonfigurationsfilen, da originalen har 359 linjer, men resten af linjerne er kommenteret ud som standard. For at få alle de tilgængelige parametre kan du tjekke den officielle dokumentation.
Sådan bruges PgBouncer
Lad os nu se en grundlæggende konfiguration for at få det til at fungere.
Pgbouncer.ini-konfigurationsfilen:
$ 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
Og godkendelsesfilen:
$ cat /etc/pgbouncer/userlist.txt
"admindb" "root123"
Så i dette tilfælde har jeg installeret PgBouncer i den samme databaseknude, lyttende på alle IP-adresser, og den forbinder til en PostgreSQL-database kaldet "verden". Jeg administrerer også de tilladte brugere i filen userlist.txt med en almindelig tekstadgangskode, der kan krypteres, hvis det er nødvendigt.
For at starte PgBouncer-tjenesten skal du blot køre følgende kommando:
$ pgbouncer -d /etc/pgbouncer/pgbouncer.ini
Hvor -d betyder "dæmon", så den kører i baggrunden.
$ 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
Som du kan se, er PgBouncer oppe og venter på forbindelser i port 6432. For at få adgang til PostgreSQL-databasen skal du køre følgende kommando ved hjælp af dine lokale oplysninger (port, vært, brugernavn og databasenavn) :
$ psql -p 6432 -h 127.0.0.1 -U admindb world
Password for user admindb:
psql (12.4)
Type "help" for help.
world=#
Husk, at databasenavnet (verden) er den database, der er konfigureret i din PgBouncer-konfigurationsfil:
[databases]
world = host=127.0.0.1 port=5432 dbname=world
Overvågning og administration af PgBouncer
I stedet for at få adgang til din PostgreSQL-database, kan du oprette forbindelse direkte til PgBouncer for at administrere eller overvåge den. Til dette, brug den samme kommando, som du brugte tidligere, men skift databasen til "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
Nu kan du køre forskellige PgBouncer-kommandoer for at overvåge det:
VIS STATS_TOTALER:
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)
VIS SERVERE:
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)
VIS KLIENTER:
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)
VIS POOLS:
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)
Og for at administrere det...
GENLÆS:
pgbouncer=# RELOAD;
RELOAD
PAUSE:
pgbouncer=# PAUSE world;
PAUSE
GENOPTAG:
pgbouncer=# RESUME world;
RESUME
Disse kommandoer er blot et eksempel. For en komplet liste over kommandoer, se venligst den officielle dokumentation.
Konklusion
Brug af en kombination af PgBouncer + HAProxy + PostgreSQL er en god måde at opnå høj tilgængelighed for din PostgreSQL-klynge og forbedre din databaseydeevne på samme tid.
Som du kan se, hvis du har dit PostgreSQL-miljø på plads, som du kan implementere ved hjælp af ClusterControl med blot et par klik, kan du nemt tilføje PgBouncer for at drage fordel af at have en forbindelsespooler til dine systemer.