Когато четете PostgreSQL как да започнете, виждате реда:„Сървърът на PostgreSQL може да обработва множество едновременни връзки от клиенти. За да постигне това, той стартира („разклонява“) нов процес за всяка връзка. От този момент нататък клиентът и новият сървърен процес комуникират без намеса от оригиналния postgres процес. По този начин процесът на главния сървър винаги работи и чака клиентски връзки, докато процесите на клиента и свързаните сървъри идват и си отиват. ”
Чудесна идея. И все пак това означава, че всяка нова връзка завърта нов процес, резервирайки RAM и вероятно става твърде тежък с множество сесии. За да избегне проблеми, postgres има настройка max_connections със 100 връзки по подразбиране. Разбира се, можете да го увеличите, но такова действие ще изисква рестартиране (pg_settings.context е „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
Някои вълнуващи четива Използване на PgBouncer Какъв е смисълът на отскачането? PgBouncer Changelog Публикации, съдържащи „pgbouncer“ в Stack Overflow Публикации с етикет „pgbouncer“ във 2ndQuadrant И дори след увеличаване - в даден момент може да се нуждаете от повече връзки (разбира се спешно, както винаги при работещ prod). Защо увеличаването му е толкова неудобно? Защото ако беше удобно, вероятно щяхте да завършите с неконтролирано спонтанно увеличаване на броя, докато клъстерът започне да изостава. Това означава, че старите връзки са по-бавни - така че отнемат повече време, така че имате нужда от още и още нови. За да избегнем подобна възможна лавина и да добавим известна гъвкавост, имаме superuser_reserved_connections - за да можем да се свързваме и да коригираме проблеми със SU, когато max_connections е изчерпан. И очевидно виждаме нуждата от някакъв пул за връзки. Тъй като искаме новите кандидати за връзка да чакат на опашка, вместо да се провалят с изключение ФАТАЛНО:съжаляваме, вече има твърде много клиенти и не рискуваме администратора на пощата.
Пулирането на връзки се предлага на някакво ниво от много популярни „клиенти“. Можете да го използвате с jdbc за известно време. Наскоро node-postgres предложи свой собствен node-pg-pool. Повече или по-малко реализацията е проста (както е идеята):pooler стартира връзките към базата данни и ги запазва. Клиентът, свързващ се с db, получава само „споделена“ съществуваща връзка и след като я затвори, връзката се връща обратно към пула. Имаме и много по-сложен софтуер, като pgPool. И все пак pgbouncer е изключително популярен избор за тази задача. Защо? Защото изпълнява само частта за обединяване, но го прави правилно. Безплатно е. Доста лесно се настройва. И вие го срещате при повечето най-големи доставчици на услуги, както са препоръчани или използвани, напр. citusdata, aws, heroku и други високо уважавани ресурси.
Така че нека разгледаме по-отблизо какво може и как го използвате. В моята настройка използвам по подразбиране pool_mode =транзакция (секция [pgbouncer]), което е много популярен избор. По този начин ние не просто поставяме в опашка връзките, надвишаващи max_connections, а по-скоро използваме повторно сесиите, без да чакаме предишната връзка да се затвори:
[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
Кратък преглед на най-популярните настройки и съвети и трикове:
-
server_reset_query е много удобен и важен. В режим на обединяване на сесии, той „изтрива“ „артефактите“ на предходната сесия. В противен случай ще имате проблеми със същите имена за подготвени оператори, настройки на сесията, засягащи следващите сесии и т.н. По подразбиране е ИЗХВЪРЛИ ВСИЧКИ, което „нулира“ всички състояния на сесията. И все пак можете да изберете по-сложни стойности, например НУЛИРАНЕ НА ВСИЧКИ; ОТДЕЛИ ВСИЧКИ; да забравите само SET SESSION и подготвени изявления, като запазите TEMP таблици и планове „споделени“. Или обратното – може да искате да направите подготвени изявления „глобални“ от всяка сесия. Такава конфигурация е изпълнима, макар и рискована. Трябва да накарате pgbouncer да използва повторно сесията за всички (по този начин или да направите много малък размер на басейна, или да свалите сесиите), което не е напълно надеждно. Както и да е – това е полезна способност. Особено в настройки, при които искате клиентските сесии в крайна сметка (не веднага) да се променят към конфигурирани настройки на обединена сесия. Много важен момент тук е режимът на сесиен пул. Преди 1.6 тази настройка засягаше и други режими на пул, така че ако сте разчитали на нея, трябва да използвате новата настройка server_reset_query_always =1. Вероятно в един момент хората ще искат server_reset_query да бъде още по-гъвкав и конфигурируем за двойка db/user ( и вместо това client_reset_query). Но към настоящия момент, март 2018 г., това не е опция. Идеята зад тази настройка да бъде валидна по подразбиране само за режим на сесия беше – ако споделяте връзка на ниво транзакция или изявление – изобщо не можете да разчитате на настройката на сесията.
-
Auth_type =hba. Преди 1.7 големият проблем с pgbouncer беше липсата на удостоверяване, базирано на хост - „postgres firewall“. Разбира се, все още го имахте за връзка с клъстер на postgres, но pgbouncer беше „отворен“ за всеки източник. Сега можем да използваме същия hba.conf, за да ограничим връзките за хост/db/user въз основа на мрежата за свързване.
-
connect_query не се изпълнява при всяка клиентска „връзка“ към pgbouncer, а по-скоро когато pgbouncer се свързва с екземпляр на Postgres. По този начин не можете да го използвате за настройка или отмяна на настройките по подразбиране. В режим на сесия другите сесии не се влияят една на друга и при прекъсване на връзката, заявката за нулиране отхвърля всички - така че не е нужно да се забърквате с нея. В режим на обединяване на транзакции бихте се надявали да го използвате за отмяна на настройки, зададени погрешно от други сесии, но няма да работи, уви. напр. искате да споделяте подготвено изявление между „сесии“ в режим на транзакция, така че задавате нещо като
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;'
и наистина - всеки нов клиент вижда подготвените оператори (освен ако не сте оставили server_reset_query_always включен, така че pgbouncer го изхвърля при комит). Но ако някой клиент стартира DISCARD s; в своята сесия, той засяга всички клиенти в тази връзка и новите клиенти, които се свързват с нея, няма да виждат вече подготвени изявления. Но ако искате да имате някаква първоначална настройка за postgres връзки, идващи от pgbouncer, тогава това е мястото.
-
application_name_add_host беше добавен в 1.6, има подобно ограничение. Той „поставя“ IP клиентския IP към application_name, така че можете лесно да получите своя лош източник на заявка, но лесно се отменя от простото зададено име_на_приложение ТО „не бях аз“; Все пак можете да „излекувате“ това с помощта на изгледи - следвайте тази публикация, за да получите идеята или дори използвайте тези кратки инструкции. Основната идея е, че показват клиенти; ще покаже IP адреса на клиента, така че можете да го заявите директно от базата данни на pgbouncer при всеки избор от pg_stat_activity, за да проверите дали е нулиран. Но, разбира се, използването на проста настройка е много по-просто и по-удобно. Въпреки че не гарантира резултата...
-
pool_mode може да бъде зададен както по подразбиране, за база данни, така и за потребител, което го прави много гъвкав. Режимите на смесване правят pgbouncer изключително ефективен за обединяване. Това е мощна функция, но трябва да бъдете внимателни, когато я използвате. Често потребителите го използват без да разбират резултатите за абсолютно атомарни миксове на транзакция/на сесия/на потребител/на база данни/глобални настройки, работещи по различен начин за един и същ потребител или база данни, поради различните режими на обединяване с pgbouncer. Това е кутията кибрит, която не давате на деца без надзор. Също така много други опции могат да се конфигурират по подразбиране и за db и за потребител.
-
Моля, не го приемайте буквално, но можете да „сравните“ различни секции на ini с SET и ALTER:SET LOCAL засяга транзакциите и е добре да се използва, когато poll_mode=transaction , SET SESSION засяга сесиите и е безопасен за използване, когато poll_mode=session , ALTER USER SET засяга роли и ще пречи на pgbouncer.ini част от секция [users], ALTER DATABASE SET засяга бази данни и ще пречи на pgbouncer.ini част от раздел [databases], ALTER SYSTEM SET или редактирането на postgres.conf глобално засяга настройките по подразбиране. и е сравним по ефект със секцията по подразбиране на pgbouncer.ini.
-
Още веднъж - използвайте режима на басейна отговорно. Подготвените отчети или настройките за цялата сесия ще бъдат бъркотия в режима на обединяване на транзакции. Същото като SQL транзакцията няма смисъл в режим на обединяване на изрази. Изберете подходящ режим на обединяване за подходящи връзки. Добра практика е създаването на роли с идеята, че:
- някои ще изпълняват само бързи избори, така че могат да споделят една сесия без транзакции за стотици едновременни малки, неважни селектирания.
- Някои членове на ролите са безопасни за паралелност на ниво сесия и ВИНАГИ използват транзакции. Така те могат безопасно да споделят няколко сесии за стотици едновременни транзакции.
- Някои роли са твърде разхвърляни или сложни, за да споделят сесията си с други. Затова използвате режима на обединяване на сесии за тях, за да избегнете грешки при връзката, когато всички „слотове“ вече са заети.
-
Не го използвайте вместо HAProxy или друг инструмент за балансиране на натоварването. Въпреки факта, че pgbouncer има няколко конфигурируеми функции, адресиращи това, което адресира балансьорът на натоварване, като dns_max_ttl и можете да настроите DNS конфигурация за него, повечето prod среди използват HAProxy или някакъв друг балансьор на натоварване за HA. Това е така, защото HAProxy е наистина добър в балансирането на натоварването между сървърите на живо по кръгов начин, по-добре от pgbouncer. Въпреки че pgbouncer е по-добър за обединяване на връзки на postgres, може би е по-добре да използвате един малък демон, който изпълнява перфектно една задача, вместо по-голям, който изпълнява две задачи, но по-лош.
-
Промените в конфигурацията могат да бъдат трудни. Някои промени в pgbouncer.ini изискват рестартиране (listen_port и други), докато други като admin_users изискват презареждане или SIGHUP. Промените в auth_hba_file изискват презареждане, докато промените в auth_file не.
Изключително краткият преглед на настройките по-горе е ограничен от формата. Каня ви да разгледате пълния списък. Pgbouncer е вид софтуер с много малко количество „скучни настройки“ – всички те имат огромен потенциал и представляват невероятен интерес.
Изтеглете Бялата книга днес Управление и автоматизация на PostgreSQL с ClusterControl Научете какво трябва да знаете, за да внедрите, наблюдавате, управлявате и мащабирате PostgreSQLD Изтеглете Бялата книгаИ накрая, преминаване от кратък ентусиазиран преглед към нещо, където може да сте по-малко доволни - инсталацията. Процесът е ясно описан в този раздел на документацията. Единствената описана опция е изграждане от git източници. Но всеки знае, че има пакети! Изпробвате и двете най-популярни:
sudo yum install pgbouncer
sudo apt-get install pgbouncer
може да работи. Но понякога трябва да направите допълнителна стъпка. Например, когато няма наличен пакет pgbouncer, опитайте това.
Или дори:
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
Разбира се добавянето на pgdg към /etc/yum.repos.d/ вече няма да помогне. Нито --skip-broken, нито rpm -Va --nofiles --nodigest. Прост
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
би било твърде лесно. Така че трябва сами да изградите libevent2, връщайки ви в положението, когато трябва сами да компилирате нещата. Или е pgbouncer, или някоя от неговите зависимости.
Отново - твърде дълбокото ровене с особеностите на монтажа е извън обхвата. Трябва да знаете, че имате голям шанс да го инсталирате като пакет.
И накрая - въпроси като „защо postgres не предлага вграден пул за сесии“ идват отново и отново. Има дори много свежи предложения и мисли по въпроса. Но досега най-популярният подход тук е използването на pgbouncer.