sql >> Databáze >  >> RDS >> PostgreSQL

Průvodce používáním pgBouncer pro PostgreSQL

Když čtete PostgreSQL Začínáme, vidíte řádek:„Server PostgreSQL dokáže zpracovat více souběžných připojení od klientů. Aby toho dosáhl, zahájí („rozvětví“) nový proces pro každé připojení. Od tohoto okamžiku klient a nový serverový proces komunikují bez zásahu původního postgresového procesu. Proces hlavního serveru tedy stále běží a čeká na připojení klientů, zatímco procesy klienta a souvisejícího serveru přicházejí a odcházejí.

Výborný nápad. A přesto to znamená, že každé nové připojení spustí nový proces, rezervuje RAM a může být příliš těžké s více relacemi. Aby se předešlo problémům, má postgres nastavení max_connections s výchozími 100 připojeními. Samozřejmě ji můžete zvýšit, ale taková akce by vyžadovala restart (pg_settings.context je ‘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
Několik vzrušujících čtení Použití PgBouncer Jaký je smysl skákání? PgBouncer Changelog Příspěvky obsahující 'pgbouncer' na Stack Overflow Příspěvky označené 'pgbouncer' na 2ndQuadrant

A to i po zvýšení - v určitém okamžiku můžete potřebovat více připojení (samozřejmě naléhavě jako vždy na běžícím produktu). Proč je jeho zvyšování tak nepříjemné? Protože pokud by to bylo pohodlné, pravděpodobně byste skončili s nekontrolovaným samovolným zvyšováním počtu, dokud se shluk nezačne zpožďovat. To znamená, že stará připojení jsou pomalejší - takže zaberou více času, takže potřebujete ještě více a více nových. Abychom se vyhnuli takové možné lavině a přidali určitou flexibilitu, máme superuser_reserved_connections - abychom se mohli připojit a opravit problémy s SU, když je vyčerpán max_connections. A evidentně vidíme potřebu nějakého sdružovače připojení. Protože chceme, aby noví kandidáti na připojení čekali ve frontě, místo aby selhali, s výjimkou FATAL:Omlouváme se, ale už je příliš mnoho klientů a neriskují poštmistra.

Sdružování připojení na určité úrovni nabízí mnoho oblíbených „klientů“. Dalo by se to používat s jdbc docela dlouho. Nedávno node-postgres nabídl svůj vlastní node-pg-pool. Implementace je víceméně jednoduchá (jak je myšlenka zní):pooler zahájí připojení k databázi a uchová je. Klient připojující se k db získá pouze „sdílené“ existující připojení a po jeho uzavření se připojení vrátí zpět do fondu. Máme také mnohem sofistikovanější software, jako je pgPool. A přesto je pgbouncer extrémně oblíbenou volbou pro tento úkol. Proč? Protože dělá pouze sdružovací část, ale dělá to správně. Je to zdarma. Je poměrně jednoduché nastavit. A setkáte se s ním u většiny největších poskytovatelů služeb, jak je doporučeno nebo používáno, např. citusdata, aws, heroku a další vysoce respektované zdroje.

Pojďme se tedy blíže podívat na to, co umí a jak ji používáte. V mém nastavení používám výchozí pool_mode =transakce (sekce [pgbouncer]), což je velmi oblíbená volba. Tímto způsobem nejen zařazujeme do fronty připojení překračující max_connections, ale spíše znovu používáme relace bez čekání na uzavření předchozího připojení:

[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

Krátký přehled nejoblíbenějších nastavení a tipů a triků:

  • server_reset_query je velmi praktický a důležitý. V režimu sdružování relací „smaže“ „artefakty“ předchozí relace. Jinak byste měli problémy se stejnými názvy pro připravené příkazy, nastavení relace ovlivňující další relace a tak dále. Výchozí hodnota je DISCARD ALL, která „resetuje“ všechny stavy relace. Přesto si můžete vybrat sofistikovanější hodnoty, např. RESET ALL; DEALOCATE VŠECHNO; zapomenout pouze na SET SESSION a připravené výkazy, přičemž tabulky a plány TEMP budou „sdílené“. Nebo naopak – možná budete chtít udělat připravená prohlášení „globální“ z jakékoli relace. Taková konfigurace je proveditelná, i když riskantní. Musíte zajistit, aby pgbouncer znovu použil relaci pro všechny (čímž vytvoříte buď velmi malou velikost bazénu nebo lavinu relací), což není zcela spolehlivé. Každopádně - je to užitečná schopnost. Zejména v nastaveních, kde chcete, aby se klientské relace nakonec (ne okamžitě) změnily na nakonfigurovaná nastavení sdružených relací. Velmi důležitým bodem je režim fondu relací. Před verzí 1.6 toto nastavení ovlivnilo i další režimy fondu, takže pokud jste na něj spoléhali, musíte použít nové nastavení server_reset_query_always =1. Pravděpodobně v určitém okamžiku budou lidé chtít, aby byl server_reset_query ještě flexibilnější a konfigurovatelný pro pár db/uživatel ( a client_reset_query místo toho). Ale podle aktuálního psaní, března 2018, to není možnost. Myšlenka, která stojí za tím, aby toto nastavení bylo ve výchozím nastavení platné pouze pro režim relace, bylo - pokud sdílíte připojení na úrovni transakce nebo výpisu - nemůžete se na nastavení relace vůbec spolehnout.

  • Auth_type =hba. Před 1.7 byla velkým problémem pgbouncer absence autentizace založené na hostiteli – „postgres firewall“. Samozřejmě jste ho stále měli pro připojení clusteru postgres, ale pgbouncer byl „otevřený“ pro jakýkoli zdroj. Nyní můžeme použít stejný hba.conf k omezení připojení pro hostitele/db/uživatele na základě sítě připojení.

  • connect_query se neprovádí při každém „připojení“ klienta k pgbouncer, ale spíše když se pgbouncer připojí k instanci Postgres. Nemůžete jej tedy použít k nastavení nebo přepsání „výchozích“ nastavení. V režimu relace se ostatní relace navzájem neovlivňují a při odpojení resetovací dotaz vše zahodí – takže se s tím nemusíte bortit. V režimu sdružování transakcí byste doufali, že jej použijete pro nastavení přepisující chybně nastavená jinými relacemi, ale bohužel to nebude fungovat. Např. chcete sdílet připravený výpis mezi „sessions“ v transakčním režimu, takže nastavíte něco jako

    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;'

    a skutečně - každý nový klient vidí připravené příkazy (pokud jste nenechali server_reset_query_always zapnuté, takže pgbouncer to při odevzdání zahodí). Ale pokud nějaký klient spustí DISCARD s; ve své relaci ovlivní všechny klienty na tomto připojení a noví klienti, kteří se k němu připojují, již neuvidí připravené výpisy. Ale pokud chcete mít nějaké počáteční nastavení pro postgresová připojení přicházející z pgbouncer, pak je to místo.

  • application_name_add_host byl přidán v 1.6, má podobné omezení. „Vloží“ IP klienta na název_aplikace, takže můžete snadno získat svůj špatný zdroj dotazů, ale lze jej snadno přepsat jednoduchým nastavením název_aplikace TO „nebyl jsem“; Stále to můžete „vyléčit“ pomocí zobrazení - postupujte podle tohoto příspěvku, abyste získali nápad, nebo dokonce použijte tyto krátké pokyny. V zásadě jde o to, ukázat klientům; zobrazí IP klientů, takže se můžete dotazovat přímo z databáze pgbouncer při každém výběru z pg_stat_activity a zkontrolovat, zda je resetován. Ale samozřejmě použití jednoduchého nastavení je mnohem jednodušší a útulnější. I když to nezaručuje výsledek...

  • pool_mode lze zadat jako výchozí, pro databázi i pro uživatele – což je velmi flexibilní. Režimy míchání činí pgbouncer extrémně efektivním pro sdružování. Toto je výkonná funkce, ale při jejím používání je třeba být opatrný. Uživatelé to často používají, aniž by rozuměli výsledkům, k naprosto atomickým mixům na transakci/na relaci/na uživatele/na databázi/globální nastavení fungující odlišně pro stejného uživatele nebo databázi, kvůli různým režimům sdružování s pgbouncer. Toto je krabička sirek, kterou nedáváte dětem bez dozoru. Také mnoho dalších možností je konfigurovatelných pro výchozí a pro db a pro uživatele.

  • Neberte to prosím doslovně, ale můžete „porovnat“ různé části ini pomocí SET a ALTER:SET LOCAL ovlivňuje transakce a je dobré ho použít, když poll_mode=transaction , SET SESSION ovlivňuje relace a je bezpečné pro použití, když poll_mode=session , ALTER USER SET ovlivní role a bude ovlivňovat pgbouncer.ini část sekce [uživatelé], ALTER DATABASE SET ovlivní databáze a bude narušovat pgbouncer.ini část sekce [databází], ALTER SYSTEM SET nebo editace postgres.conf globálně ovlivní výchozí nastavení a je srovnatelný s výchozí sekcí pgbouncer.ini.

  • Ještě jednou – režim bazénu používejte zodpovědně. Připravené výpisy nebo nastavení celé relace budou v režimu sdružování transakcí nepořádek. Stejně jako transakce SQL nedává smysl v režimu sdružování příkazů. Vyberte vhodný režim sdružování pro vhodná připojení. Osvědčeným postupem je vytváření rolí s myšlenkou, že:

    • Některé budou spouštět pouze rychlé výběry, takže mohou sdílet jednu relaci bez transakcí pro sto souběžných drobných nedůležitých výběrů.
    • Někteří členové role jsou bezpečné pro souběžnost na úrovni relace a VŽDY používají transakce. Mohou tak bezpečně sdílet několik relací pro stovky souběžných transakcí.
    • Některé role jsou příliš chaotické nebo komplikované na to, aby mohli sdílet svou relaci s ostatními. Takže pro ně používáte režim sdružování relací, abyste se vyhnuli chybám při připojení, když jsou všechny „sloty“ již obsazeny.
  • Nepoužívejte jej místo HAProxy nebo jiného load balanceru. Navzdory skutečnosti, že pgbouncer má několik konfigurovatelných funkcí, které řeší to, co load balancer adresuje, jako dns_max_ttl a můžete pro něj nastavit konfiguraci DNS, většina prod prostředí používá HAProxy nebo nějaký jiný load balancer pro HA. Je to proto, že HAProxy je opravdu dobrý ve vyvažování zátěže mezi živými servery způsobem kruhového provozu, lepší než pgbouncer. Přestože je pgbouncer lepší pro postgresové sdružování připojení, může být lepší použít jednoho malého démona, který perfektně plní jednu úlohu, místo většího, který dělá dvě úlohy, ale hůř.

  • Změny konfigurace mohou být složité. Některé změny v pgbouncer.ini vyžadují restart (listen_port a podobně), zatímco jiné jako admin_users vyžadují reload nebo SIGHUP. Změny uvnitř auth_hba_file vyžadují opětovné načtení, zatímco změny v auth_file nikoli.

Extrémně krátký přehled výše uvedených nastavení je omezen formátem. Zvu vás, abyste se podívali na úplný seznam. Pgbouncer je druh softwaru s velmi malým množstvím „nudných nastavení“ – všechny mají obrovský potenciál a jsou úžasné.

Stáhněte si Whitepaper Today Správa a automatizace PostgreSQL s ClusterControlZjistěte, co potřebujete vědět k nasazení, monitorování, správě a škálování PostgreSQLStáhněte si Whitepaper

A nakonec přechod od krátké nadšené recenze k něčemu, co by vás mohlo potěšit méně – k instalaci. Proces je jasně popsán v této části dokumentace. Jedinou popsanou možností je sestavení ze zdrojů git. Ale každý ví, že existují balíčky! Vyzkoušení obou nejoblíbenějších:

sudo yum install pgbouncer
sudo apt-get install pgbouncer

může pracovat. Někdy ale musíte udělat krok navíc. Pokud například není k dispozici žádný balíček pgbouncer, zkuste toto.

Nebo dokonce:

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

Přidání pgdg do /etc/yum.repos.d/ už samozřejmě nepomůže. Ani --skip-broken nebo rpm -Va --nofiles --nodigest. Jednoduché

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

bylo by to příliš snadné. Takže musíte vytvořit libevent2 sami, což vás přivede zpět do pozice, kdy musíte věci kompilovat sami. Buď je to pgbouncer nebo jedna z jeho závislostí.

Opět – přílišné rýpání ve zvláštnostech instalace je mimo rozsah. Měli byste vědět, že máte velkou šanci jej nainstalovat jako balíček.

A konečně – otázky jako „proč postgres nenabízí nativní sdružovač relací“ přicházejí znovu a znovu. Existují dokonce velmi čerstvé návrhy a myšlenky na to. Ale zatím nejoblíbenějším přístupem je použití pgbouncer.


  1. Jak nakonfigurovat Ruby on Rails s Oracle?

  2. Dotazování na názory:Jedna sekvence pro všechny tabulky

  3. Převést „datetime“ na „datetimeoffset“ v SQL Server (příklady T-SQL)

  4. Jak mohu nasadit aplikaci .NET, která používá ODAC, aniž bych uživateli instaloval celou komponentu?