sql >> Database >  >> RDS >> PostgreSQL

Een handleiding voor het gebruik van pgBouncer voor PostgreSQL

Wanneer u PostgreSQL aan de slag leest, ziet u de regel:“De PostgreSQL-server kan meerdere gelijktijdige verbindingen van clients aan. Om dit te bereiken, start het (“forks”) een nieuw proces voor elke verbinding. Vanaf dat moment communiceren de client en het nieuwe serverproces zonder tussenkomst van het oorspronkelijke postgresproces. Het master-serverproces is dus altijd actief, wachtend op clientverbindingen, terwijl client- en bijbehorende serverprocessen komen en gaan.

Briljant idee. En toch betekent het dat elke nieuwe verbinding een nieuw proces laat draaien, RAM reserveert en mogelijk te zwaar wordt met meerdere sessies. Om problemen te voorkomen, heeft postgres de max_connections-instelling met standaard 100 verbindingen. Natuurlijk kunt u het verhogen, maar voor een dergelijke actie moet opnieuw worden opgestart (pg_settings.context is 'postmaster'):

t=# select name,setting,short_desc,context from pg_settings where name = 'max_connections';
-[ RECORD 1 ]--------------------------------------------------
name       | max_connections
setting    | 100
short_desc | Sets the maximum number of concurrent connections.
context    | postmaster
Enkele spannende lezingen PgBouncer Gebruik Wat is het nut van stuiteren? PgBouncer Changelog Berichten met 'pgbouncer' op Stack Overflow Berichten getagd met 'pgbouncer' op 2ndQuadrant

En zelfs na het verhogen - op een gegeven moment heb je misschien meer verbindingen nodig (natuurlijk dringend zoals altijd bij het uitvoeren van prod). Waarom is het zo ongemakkelijk om het te verhogen? Want als het comfortabel was, zou je waarschijnlijk eindigen met een ongecontroleerde spontane toename van het aantal totdat het cluster achterblijft. Dit betekent dat oude verbindingen langzamer zijn - dus ze nemen meer tijd in beslag, dus je hebt steeds meer nieuwe nodig. Om een ​​dergelijke mogelijke lawine te vermijden en enige flexibiliteit toe te voegen, hebben we superuser_reserved_connections - om verbinding te kunnen maken en problemen met SU op te lossen wanneer max_connections uitgeput is. En we zien duidelijk de behoefte aan een verbindingspooler. Omdat we willen dat nieuwe verbindingskandidaten in een wachtrij wachten in plaats van te falen, met uitzondering van FATAL:sorry, al te veel klanten en zonder de postmaster te riskeren.

Pooling van verbindingen wordt op een bepaald niveau aangeboden door veel populaire "klanten". Je zou het een tijdje kunnen gebruiken met jdbc. Onlangs bood node-postgres zijn eigen node-pg-pool aan. De implementatie is min of meer eenvoudig (zoals het idee is):pooler start de verbindingen naar de database en houdt deze bij. De client die verbinding maakt met db krijgt alleen een "gedeelde" bestaande verbinding en na het sluiten gaat de verbinding terug naar de pool. We hebben ook veel geavanceerdere software, zoals pgPool. En toch is pgbouncer een extreem populaire keuze voor deze taak. Waarom? Omdat het alleen het poolgedeelte doet, maar het goed doet. Het is gratis. Het is vrij eenvoudig in te stellen. En je ontmoet het bij de meeste grootste serviceproviders zoals aanbevolen of gebruikt, bijvoorbeeld citusdata, aws, heroku en andere zeer gerespecteerde bronnen.

Dus laten we eens nader bekijken wat het kan en hoe je het gebruikt. In mijn setup gebruik ik standaard pool_mode =transactie ([pgbouncer] sectie), wat een erg populaire keuze is. Op deze manier zetten we niet alleen de verbindingen die max_connections overschrijden in de wachtrij, maar hergebruiken we sessies liever zonder te wachten tot de vorige verbinding is gesloten:

[databases]
mon = host=1.1.1.1 port=5432 dbname=mon
mons = host=1.1.1.1 port=5432 dbname=mon pool_mode = session pool_size=2 max_db_connections=2
monst = host=1.1.1.1 port=5432 dbname=mon pool_mode = statement
[pgbouncer]
listen_addr = 1.1.1.1
listen_port = 6432
unix_socket_dir = /tmp
auth_file = /pg/pgbouncer/bnc_users.txt
auth_type = hba
auth_hba_file = /pg/pgbouncer/bnc_hba.conf
admin_users = root vao
pool_mode = transaction
server_reset_query = RESET ALL; --DEALLOCATE ALL; /* custom */
ignore_startup_parameters = extra_float_digits
application_name_add_host = 1
max_client_conn = 10000
autodb_idle_timeout = 3600
default_pool_size = 100
max_db_connections = 100
max_user_connections = 100
#server_reset_query_always = 1 #uncomment if you want older global behaviour

Kort overzicht van de meest populaire instellingen en tips en trucs:

  • server_reset_query is erg handig en belangrijk. In de modus voor sessiepooling "wist" het "artefacten" uit de vorige sessie. Anders zou u problemen krijgen met dezelfde namen voor voorbereide verklaringen, sessie-instellingen die van invloed zijn op volgende sessies, enzovoort. De standaardwaarde is DISCARD ALL, die alle sessiestatussen "reset". Toch kunt u meer geavanceerde waarden kiezen, bijv. RESET ALL; ALLES VERWIJDEREN; om alleen SET SESSION en voorbereide verklaringen te vergeten, waarbij TEMP-tabellen en -plannen "gedeeld" blijven. Of het tegenovergestelde - misschien wilt u vanuit elke sessie voorbereide uitspraken 'globaal' doen. Een dergelijke configuratie is uitvoerbaar, hoewel riskant. Je moet ervoor zorgen dat pgbouncer de sessie voor iedereen hergebruikt (waardoor je ofwel een zeer kleine poolgrootte maakt of de sessies overspoelt), wat niet helemaal betrouwbaar is. Hoe dan ook - het is een nuttige vaardigheid. Vooral in opstellingen waar u wilt dat clientsessies uiteindelijk (niet onmiddellijk) veranderen naar geconfigureerde instellingen voor gepoolde sessies. Een heel belangrijk punt hier is de sessiepoolmodus. Vóór 1.6 had deze instelling ook invloed op andere poolmodi, dus als u erop vertrouwde, moet u de nieuwe instelling server_reset_query_always =1 gebruiken. Waarschijnlijk zullen mensen op een gegeven moment willen dat server_reset_query nog flexibeler en configureerbaarder is per db/user-paar ( en client_reset_query in plaats daarvan). Maar vanaf het huidige schrijven, maart 2018, is het geen optie. Het idee achter het standaard geldig maken van deze instelling voor alleen de sessiemodus was - als u de verbinding deelt op transactie- of afschriftniveau - u helemaal niet op de sessie-instelling kunt vertrouwen.

  • Auth_type =hba. Vóór 1.7 was het grote probleem met pgbouncer de afwezigheid van hostgebaseerde authenticatie - "postgres-firewall". Natuurlijk had je het nog steeds voor postgres-clusterverbinding, maar pgbouncer was "open" voor elke bron. Nu kunnen we dezelfde hba.conf gebruiken om verbindingen voor host/db/gebruiker te beperken op basis van verbindingsnetwerk.

  • connect_query wordt niet uitgevoerd op elke "verbinding" van een client met pgbouncer, maar eerder wanneer pgbouncer verbinding maakt met een Postgres-instantie. U kunt het dus niet gebruiken voor het instellen of overschrijven van "standaard" instellingen. In de sessiemodus hebben andere sessies geen invloed op elkaar en bij het verbreken van de verbinding, verwijdert u alle query's opnieuw - u hoeft er dus niet mee te rotzooien. In de transactiepooling-modus zou je hopen het te gebruiken voor instellingen die ten onrechte zijn ingesteld door andere sessies, maar het zal helaas niet werken. bijv. u wilt een voorbereide verklaring delen tussen "sessies" in transactiemodus, dus u stelt zoiets in als

    trns = dbname=mon pool_mode = transaction connect_query = 'do $$ begin raise warning $w$%$w$, $b$new connection$b$; end; $$; prepare s(int) as select $1;'

    en inderdaad - elke nieuwe client ziet de voorbereide statements (tenzij je server_reset_query_always aan hebt gelaten, dus pgbouncer negeert het bij commit). Maar als een client DISCARD s uitvoert; in zijn sessie heeft het invloed op alle clients op deze verbinding en nieuwe clients die ermee verbinding maken, zullen geen voorbereide verklaringen meer zien. Maar als je een initiële instelling wilt hebben voor postgres-verbindingen afkomstig van pgbouncer, dan is dit de plek.

  • application_name_add_host is toegevoegd in 1.6, het heeft een vergelijkbare beperking. Het "zet" het IP-adres van de client op toepassingsnaam, zodat u gemakkelijk uw slechte querybron kunt krijgen, maar het kan gemakkelijk worden overschreven door een eenvoudige toepassingsnaam in te stellen op 'was' ik niet'; Toch kun je dit "genezen" met behulp van views - volg dit bericht om het idee te krijgen of gebruik zelfs deze korte instructies. Eigenlijk is het idee dat klanten laten zien; zal het IP-adres van de klant tonen, zodat u het rechtstreeks vanuit de pgbouncer-database kunt opvragen bij elke selectie uit pg_stat_activity om te controleren of het opnieuw is ingesteld. Maar een simpele instelling gebruiken is natuurlijk veel eenvoudiger en gezelliger. Hoewel het het resultaat niet garandeert...

  • pool_mode kan zowel als standaard, per database en per gebruiker worden gespecificeerd - waardoor het zeer flexibel is. Het mixen van modi maakt pgbouncer uiterst effectief voor poolen. Dit is een krachtige functie, maar men moet voorzichtig zijn bij het gebruik ervan. Vaak gebruiken gebruikers het zonder de resultaten te begrijpen tot absoluut atomaire mixen van per transactie/per sessie/per gebruiker/per database/algemene instellingen die anders werken voor dezelfde gebruiker of database, vanwege de verschillende pooling-modi met pgbouncer. Dit is de doos met lucifers die je niet zonder toezicht aan kinderen geeft. Er zijn ook veel andere opties configureerbaar voor standaard en per db en per gebruiker.

  • Neem het alsjeblieft niet letterlijk, maar je kunt verschillende secties van ini "vergelijken" met SET en ALTER:SET LOCAL beïnvloedt transacties en is goed om te gebruiken wanneer poll_mode=transactie , SET SESSION beïnvloedt sessies en is veilig voor gebruik wanneer poll_mode=session , ALTER USER SET heeft invloed op rollen en interfereert met pgbouncer.ini deel van sectie [gebruikers], ALTER DATABASE SET beïnvloedt databases en zal interfereren met pgbouncer.ini deel van sectie [databases], ALTER SYSTEM SET of bewerken van postgres.conf beïnvloedt globaal de standaardinstellingen en is qua effect vergelijkbaar met de standaardsectie van pgbouncer.ini.

  • Nogmaals - gebruik de zwembadmodus op verantwoorde wijze. Voorbereide verklaringen of sessiebrede instellingen zullen een puinhoop zijn in de transactiepoolingmodus. Hetzelfde als SQL-transactie heeft geen zin in de modus voor het poolen van instructies. Kies een geschikte poolingmodus voor geschikte verbindingen. Een goede gewoonte is het creëren van rollen met het idee dat:

    • sommigen zullen alleen snelle selecties uitvoeren, en kunnen dus één sessie delen zonder transacties voor honderd gelijktijdige kleine, niet belangrijke selecties.
    • Sommige rolleden zijn veilig voor gelijktijdigheid op sessieniveau en gebruiken ALTIJD transacties. Zo kunnen ze veilig meerdere sessies delen voor honderden gelijktijdige transacties.
    • Sommige rollen zijn gewoon te rommelig of ingewikkeld om hun sessie met anderen te delen. Dus je gebruikt de sessie-pooling-modus voor hen om fouten bij de verbinding te voorkomen wanneer alle "slots" al bezet zijn.
  • Gebruik het niet in plaats van HAProxy of een andere load balancer. Ondanks het feit dat pgbouncer verschillende configureerbare functies heeft die aanpakken wat een load balancer adresseert, zoals dns_max_ttl en je kunt er een DNS-configuratie voor instellen, gebruiken de meeste prod-omgevingen HAProxy of een andere load balancer voor HA. Dit komt omdat HAProxy echt goed is in het verdelen van de belasting over live servers in round robin-mode, beter dan pgbouncer. Hoewel pgbouncer beter is voor postgres-verbindingspooling, is het misschien beter om één kleine daemon te gebruiken die één taak perfect uitvoert, in plaats van een grotere die twee taken uitvoert, maar erger.

  • Configuratiewijzigingen kunnen lastig zijn. Sommige wijzigingen aan pgbouncer.ini vereisen herstart (listen_port en dergelijke), terwijl andere, zoals admin_users, herladen of SIGHUP vereisen. Wijzigingen in auth_hba_file moeten opnieuw worden geladen, terwijl wijzigingen in auth_file dat niet doen.

Het extreem korte overzicht van instellingen hierboven wordt beperkt door het formaat. Ik nodig u uit om de volledige lijst te bekijken. Pgbouncer is het soort software met een zeer kleine hoeveelheid "saaie instellingen" - ze hebben allemaal een enorm potentieel en zijn van verbazingwekkend belang.

Download de whitepaper vandaag PostgreSQL-beheer en -automatisering met ClusterControlLees wat u moet weten om PostgreSQL te implementeren, bewaken, beheren en schalenDownload de whitepaper

En als laatste, de overgang van een korte enthousiaste review naar iets waar je misschien minder blij mee bent - de installatie. Het proces wordt duidelijk beschreven in dit gedeelte van de documentatie. De enige beschreven optie is bouwen vanuit git-bronnen. Maar iedereen weet dat er pakketten zijn! Probeer beide meest populaire:

sudo yum install pgbouncer
sudo apt-get install pgbouncer

kan werken. Maar soms moet je een extra stap doen. Als er bijvoorbeeld geen pgbouncer-pakket beschikbaar is, probeer dit dan.

Of zelfs:

sudo yum install pgbouncer
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main                                                                                                                    | 2.1 kB  00:00:00
amzn-updates                                                                                                                 | 2.5 kB  00:00:00
docker-ce-edge                                                                                                               | 2.9 kB  00:00:00
docker-ce-stable                                                                                                             | 2.9 kB  00:00:00
docker-ce-test                                                                                                               | 2.9 kB  00:00:00
pgdg10                                                                                                                       | 4.1 kB  00:00:00
pgdg95                                                                                                                       | 4.1 kB  00:00:00
pgdg96                                                                                                                       | 4.1 kB  00:00:00
pglogical                                                                                                                    | 3.0 kB  00:00:00
sensu                                                                                                                        | 2.5 kB  00:00:00
(1/3): pgdg96/x86_64/primary_db                                                                                              | 183 kB  00:00:00
(2/3): pgdg10/primary_db                                                                                                     | 151 kB  00:00:00
(3/3): pgdg95/x86_64/primary_db                                                                                              | 204 kB  00:00:00
50 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package pgbouncer.x86_64 0:1.8.1-1.rhel6 will be installed
--> Processing Dependency: libevent2 >= 2.0 for package: pgbouncer-1.8.1-1.rhel6.x86_64
--> Processing Dependency: c-ares for package: pgbouncer-1.8.1-1.rhel6.x86_64
--> Processing Dependency: libcares.so.2()(64bit) for package: pgbouncer-1.8.1-1.rhel6.x86_64
--> Running transaction check
---> Package c-ares.x86_64 0:1.13.0-1.5.amzn1 will be installed
---> Package pgbouncer.x86_64 0:1.8.1-1.rhel6 will be installed
--> Processing Dependency: libevent2 >= 2.0 for package: pgbouncer-1.8.1-1.rhel6.x86_64
--> Finished Dependency Resolution
Error: Package: pgbouncer-1.8.1-1.rhel6.x86_64 (pgdg10)
           Requires: libevent2 >= 2.0
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

Natuurlijk helpt het niet meer om pgdg toe te voegen aan /etc/yum.repos.d/. Noch de --skip-broken of rpm -Va --nofiles --nodigest. Een eenvoudige

sudo yum install libevent2
Loaded plugins: priorities, update-motd, upgrade-helper
50 packages excluded due to repository priority protections
No package libevent2 available.
Error: Nothing to do

te gemakkelijk zou zijn. Dus je moet libevent2 zelf bouwen, waardoor je weer terugkomt in de positie waarin je dingen zelf moet compileren. Of het is pgbouncer of een van zijn afhankelijkheden.

Nogmaals - te diep graven met de bijzonderheden van de installatie valt buiten het bereik. Je moet weten dat je een grote kans hebt om het als pakket te installeren.

Ten slotte komen vragen als "waarom postgres geen native session pooler aanbiedt" steeds weer terug. Er zijn zelfs zeer frisse suggesties en gedachten over. Maar tot nu toe is de meest populaire aanpak hier het gebruik van pgbouncer.


  1. MySQL Unieke beperking toevoegen

  2. Hoe installeer ik MySQLdb (Python data access library to MySQL) op Mac OS X?

  3. Transformatie van rijen naar kolommen in Oracle

  4. Microsoft Access 2010, 2013, 2016 en 2019 zelfstudie