Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În raportul său, Andrey Borodin vă va spune cum au luat în considerare experiența de scalare a PgBouncer la proiectarea pooler-ului de conexiuni Odiseea, pe măsură ce l-au lansat în producție. În plus, vom discuta ce funcții ale extractorului am dori să vedem în noile versiuni: este important pentru noi nu numai să ne satisfacem nevoile, ci să dezvoltăm comunitatea de utilizatori Odiseea.

video:

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Salutare tuturor! Numele meu este Andrew.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

La Yandex, dezvolt baze de date open source. Și astăzi avem un subiect despre conexiunile pooler de conexiuni.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Dacă știi cum să apelezi la pooler de conexiuni în rusă, atunci spune-mi. Îmi doresc foarte mult să găsesc un termen tehnic bun care să fie stabilit în literatura tehnică.

Subiectul este destul de complicat, deoarece în multe baze de date poolerul de conexiuni este încorporat și nici măcar nu trebuie să știți despre el. Desigur, există unele setări peste tot, dar în Postgres nu funcționează așa. Și în paralel (la HighLoad++ 2019) există un raport al lui Nikolai Samokhvalov despre configurarea interogărilor în Postgres. Și din câte am înțeles, au venit aici oameni care și-au configurat deja interogările perfect și aceștia sunt oameni care se confruntă cu probleme de sistem mai rare legate de rețea și utilizarea resurselor. Și în unele locuri ar putea fi destul de dificil în sensul că problemele nu sunt evidente.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Yandex are Postgres. Multe servicii Yandex trăiesc în Yandex.Cloud. Și avem câțiva petabytes de date care generează cel puțin un milion de solicitări pe secundă în Postgres.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și oferim un cluster destul de standard pentru toate serviciile - acesta este nodul principal principal al nodului, cele două replici obișnuite (sincrone și asincrone), backup, scalarea solicitărilor de citire pe replică.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Fiecare nod de cluster este Postgres, pe care, pe lângă Postgres și sistemele de monitorizare, este instalat și un pooler de conexiuni. Poolerul de conectare este utilizat pentru garduri și pentru scopul său principal.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Care este scopul principal al poolerului de conexiuni?

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Postgres adoptă un model de proces atunci când lucrează cu o bază de date. Aceasta înseamnă că o conexiune este un proces, un backend Postgres. Și în acest backend există o mulțime de cache-uri diferite, care sunt destul de scumpe de făcut diferite pentru diferite conexiuni.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În plus, codul Postgres are o matrice numită procArray. Conține date de bază despre conexiunile la rețea. Și aproape toți algoritmii de procesare procArray au complexitate liniară; rulează pe întreaga gamă de conexiuni de rețea. Este un ciclu destul de rapid, dar cu mai multe conexiuni de rețea de intrare lucrurile devin puțin mai scumpe. Și când lucrurile devin puțin mai scumpe, puteți ajunge să plătiți un preț foarte mare pentru o mulțime de conexiuni la rețea.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Există 3 abordări posibile:

  • Pe partea aplicației.
  • Pe partea bazei de date.
  • Și între, adică tot felul de combinații.

Din păcate, poolerul încorporat este în prezent în curs de dezvoltare. Prietenii noștri de la PostgreSQL Professional fac asta mai ales. Când va apărea este greu de prezis. Și, de fapt, avem două soluții dintre care arhitectul poate alege. Acestea sunt grupul de aplicații și grupul de proxy.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Piscina din partea aplicației este cea mai ușoară cale. Și aproape toate driverele client vă oferă o modalitate: prezentați milioane de conexiuni în cod ca câteva zeci de conexiuni la baza de date.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Problema care apare este că, la un anumit moment, doriți să scalați backend-ul, doriți să îl implementați pe multe mașini virtuale.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Apoi realizezi că mai ai câteva zone de disponibilitate, mai multe centre de date. Iar abordarea de punere în comun a clientului duce la un număr mare. Cele mari sunt aproximativ 10 de conexiuni. Aceasta este marginea care poate funcționa normal.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Dacă vorbim despre proxy poolers, atunci există doi pooler care pot face o mulțime de lucruri. Ei nu sunt doar pooleri. Sunt poolers + funcționalitate mai cool. Acest Pgpool и Crunchy-Proxy.

Dar, din păcate, nu toată lumea are nevoie de această funcționalitate suplimentară. Și duce la faptul că poolerii acceptă doar gruparea de sesiuni, adică un client de intrare, un client de ieșire către baza de date.

Acest lucru nu este foarte potrivit pentru scopurile noastre, așa că folosim PgBouncer, care implementează pooling de tranzacții, adică conexiunile la server sunt potrivite cu conexiunile client numai pe durata tranzacției.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și în volumul nostru de muncă, acest lucru este adevărat. Dar există câteva probleme.Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Problemele încep atunci când doriți să diagnosticați o sesiune, deoarece toate conexiunile dvs. de intrare sunt locale. Toată lumea a venit cu un loopback și cumva devine dificil să urmăriți sesiunea.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Desigur, puteți folosi application_name_add_host. Aceasta este o modalitate din partea Bouncer de a adăuga o adresă IP la application_name. Dar application_name este setat de o conexiune suplimentară.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Pe acest grafic, unde linia galbenă este cererile reale și unde linia albastră sunt cererile care zboară în baza de date. Și această diferență este tocmai instalarea aplicației_name, care este necesară doar pentru urmărire, dar nu este deloc gratuită.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În plus, în Bouncer nu puteți limita un singur pool, adică numărul de conexiuni la baze de date pentru un anumit utilizator, pentru o anumită bază de date.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

La ce duce asta? Ai un serviciu încărcat scris în C++ și undeva în apropiere un serviciu mic pe un nod care nu face nimic groaznic cu baza de date, dar driverul său o ia razna. Deschide 20 de conexiuni și totul va aștepta. Chiar și codul tău este normal.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Desigur, am scris un mic patch pentru Bouncer care a adăugat această setare, adică limitând clienții la pool.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Ar fi posibil să faceți acest lucru pe partea Postgres, adică să limitați rolurile din baza de date cu numărul de conexiuni.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Dar apoi pierzi capacitatea de a înțelege de ce nu ai conexiuni la server. PgBouncer nu aruncă o eroare de conexiune, returnează întotdeauna aceleași informații. Și nu puteți înțelege: poate parola dvs. s-a schimbat, poate baza de date tocmai s-a pierdut, poate ceva nu este în regulă. Dar nu există un diagnostic. Dacă o sesiune nu poate fi stabilită, nu veți ști de ce nu poate fi stabilită.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

La un moment dat, te uiți la graficele aplicației și vezi că aplicația nu funcționează.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Uită-te la partea de sus și vezi că Bouncer are un singur fir. Acesta este un punct de cotitură în viața serviciului. Vă dați seama că vă pregătiți să scalați baza de date într-un an și jumătate și trebuie să scalați pooler-ul.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Am ajuns la concluzia că avem nevoie de mai mulți PgBouncers.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

https://lwn.net/Articles/542629/

Bouncer a fost puțin remediat.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și au făcut astfel încât mai mulți Bouncer să poată fi ridicați prin reutilizarea portului TCP. Iar sistemul de operare transferă automat conexiunile TCP de intrare între ele folosind round-robin.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Acest lucru este transparent pentru clienți, ceea ce înseamnă că se pare că aveți un Bouncer, dar aveți o fragmentare a conexiunilor inactive între rularea Bouncers.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și la un moment dat s-ar putea să observați că acești 3 Bouncers își mănâncă fiecare miezul cu 100%. Ai nevoie de câțiva Bouncers. De ce?

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Pentru că aveți TLS. Aveți o conexiune criptată. Și dacă comparați Postgres cu și fără TLS, veți constata că numărul de conexiuni stabilite scade cu aproape două ordine de mărime cu criptarea activată, deoarece handshake-ul TLS consumă resurse CPU.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și în partea de sus puteți vedea destul de multe funcții criptografice care sunt executate atunci când există un val de conexiuni de intrare. Deoarece principalul nostru poate comuta între zonele de disponibilitate, un val de conexiuni de intrare este o situație destul de tipică. Adică, din anumite motive, vechiul primar nu era disponibil, întreaga încărcare a fost trimisă la alt centru de date. Toți vor veni să-l salute pe TLS în același timp.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și un număr mare de strângeri de mână TLS nu-l mai salută pe Bouncer, ci îi vor strânge gâtul. Din cauza expirării, valul de conexiuni de intrare poate deveni neatenuat. Dacă reîncercați la bază fără retragere exponențială, acestea nu vor veni din nou și din nou într-un val coerent.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Iată un exemplu de 16 PgBouncers care încarcă 16 nuclee la 100%.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Am ajuns la cascada PgBouncer. Aceasta este cea mai bună configurație care poate fi realizată pe încărcătura noastră cu Bouncer. Bouncer-urile noastre externe sunt folosite pentru strângere de mână TCP, iar Bouncer-urile interne sunt folosite pentru pooling real, pentru a nu fragmenta prea mult conexiunile externe.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În această configurație, este posibilă o repornire lină. Puteți reporni toți acești 18 Bouncer unul câte unul. Dar menținerea unei astfel de configurații este destul de dificilă. Administratorii de sistem, DevOps și oamenii care sunt de fapt responsabili pentru acest server nu vor fi foarte mulțumiți de acest aranjament.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

S-ar părea că toate îmbunătățirile noastre pot fi promovate la sursă deschisă, dar Bouncer nu este foarte bine susținut. De exemplu, capacitatea de a rula mai multe PgBouncers pe un singur port a fost angajată în urmă cu o lună. A existat o cerere de extragere cu această funcție în urmă cu câțiva ani.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

https://www.postgresql.org/docs/current/libpq-cancel.html

https://github.com/pgbouncer/pgbouncer/pull/79

Sau încă un exemplu. În Postgres, puteți anula o solicitare în curs trimițând secretul la o altă conexiune fără autentificare inutilă. Dar unii clienți pur și simplu trimit o resetare TCP, adică întrerup conexiunea la rețea. Ce va face Bouncer? Nu va face nimic. Va continua să execute cererea. Dacă ați primit un număr mare de conexiuni care au creat o bază de date cu cereri mici, atunci pur și simplu deconectarea conexiunii de la Bouncer nu va fi suficientă; de asemenea, trebuie să finalizați acele solicitări care rulează în baza de date.

Acest lucru a fost corectat și această problemă nu a fost încă îmbinată în amonte Bouncer.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și așa am ajuns la concluzia că avem nevoie de propriul pooler de conexiuni, care va fi dezvoltat, patchizat, în care problemele pot fi corectate rapid și care, desigur, trebuie să fie multi-threaded.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Am stabilit multithreading ca sarcină principală. Trebuie să fim capabili să gestionăm bine valul de conexiuni TLS de intrare.

Pentru a face acest lucru, a trebuit să dezvoltăm o bibliotecă separată numită Machinarium, care este concepută pentru a descrie stările mașinii unei conexiuni de rețea ca cod secvenţial. Dacă vă uitați la codul sursă libpq, veți vedea câteva apeluri destul de complexe care vă pot returna un rezultat și vă pot spune: „Sună-mă mai târziu. Momentan am IO pentru moment, dar când IO-ul dispare, voi avea o încărcare pe procesor.” Și aceasta este o schemă cu mai multe niveluri. Comunicarea în rețea este de obicei descrisă de o mașină de stat. O mulțime de reguli precum „Dacă am primit anterior un antet de pachet de dimensiunea N, acum aștept N octeți”, „Dacă am trimis un pachet SYNC, acum aștept un pachet cu metadate de rezultat”. Rezultatul este un cod destul de dificil, contraintuitiv, de parcă labirintul ar fi convertit la scanare pe linie. Am făcut astfel încât, în loc de o mașină de stări, programatorul să descrie calea principală de interacțiune sub forma unui cod imperativ obișnuit. Doar că în acest cod imperativ trebuie să inserați locuri în care secvența de execuție trebuie întreruptă prin așteptarea datelor din rețea, trecând contextul de execuție la o altă corutine (fir verde). Această abordare este similară cu faptul că notăm la rând cea mai așteptată cale din labirint și apoi îi adăugăm ramuri.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Ca rezultat, avem un fir care acceptă TCP și round-robin transmite conexiunea TPC către mulți lucrători.

În acest caz, fiecare conexiune client rulează întotdeauna pe un procesor. Și acest lucru vă permite să îl faceți prietenos cu memoria cache.

În plus, am îmbunătățit ușor colecția de pachete mici într-un singur pachet mare pentru a ușura stiva TCP a sistemului.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În plus, am îmbunătățit gruparea tranzacțiilor, în sensul că Odyssey, atunci când este configurat, poate trimite CANCEL și ROLLBACK în cazul unei eșecuri a conexiunii la rețea, adică dacă nimeni nu așteaptă o solicitare, Odyssey va spune bazei de date să nu încerce să o facă. satisface cererea care poate risipi resurse prețioase.

Și ori de câte ori este posibil, păstrăm conexiunile cu același client. Acest lucru evită nevoia de a reinstala application_name_add_host. Dacă acest lucru este posibil, atunci nu trebuie să resetam suplimentar parametrii necesari pentru diagnosticare.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Lucrăm în interesul Yandex.Cloud. Și dacă utilizați PostgreSQL gestionat și aveți instalat un pooler de conexiuni, puteți crea o replicare logică spre exterior, adică să ne lăsați, dacă doriți, folosind replicarea logică. Bouncer nu va elibera fluxul de replicare logic în exterior.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Acesta este un exemplu de configurare a replicării logice.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În plus, avem suport pentru replicarea fizică în exterior. În Cloud, desigur, acest lucru este imposibil, deoarece atunci clusterul vă va oferi prea multe informații despre el însuși. Dar în instalațiile dvs., dacă aveți nevoie de replicare fizică prin pooler-ul de conexiuni din Odyssey, acest lucru este posibil.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Odyssey are monitorizare complet compatibilă cu PgBouncer. Avem aceeași consolă care rulează aproape toate aceleași comenzi. Dacă lipsește ceva, trimiteți o cerere de extragere sau cel puțin o problemă pe GitHub și vom finaliza comenzile necesare. Dar avem deja funcționalitatea principală a consolei PgBouncer.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și, desigur, avem redirecționarea erorilor. Vom returna eroarea raportată de baza de date. Veți primi informații despre motivul pentru care nu sunteți inclus în baza de date și nu doar despre faptul că nu sunteți inclus în ea.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Această funcție este dezactivată în cazul în care aveți nevoie de compatibilitate 100% cu PgBouncer. Ne putem comporta la fel ca Bouncer, doar pentru a fi în siguranță.

desen

Câteva cuvinte despre codul sursă Odyssey.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

https://github.com/yandex/odyssey/pull/66

De exemplu, există comenzi „Pauză / Reluare”. Ele sunt de obicei folosite pentru a actualiza baza de date. Dacă trebuie să actualizați Postgres, atunci îl puteți întrerupe în poolerul de conexiuni, faceți pg_upgrade, apoi reluați. Și din partea clientului va arăta ca și cum baza de date pur și simplu încetinește. Această funcționalitate ne-a fost adusă de oameni din comunitate. Nu este încă înghețată, dar în curând totul va fi. (Deja înghețat)

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

https://github.com/yandex/odyssey/pull/73 - deja congelat

În plus, una dintre noile funcții din PgBouncer este suportul pentru autentificarea SCRAM, care ne-a fost adusă și de o persoană care nu lucrează în Yandex.Cloud. Ambele sunt funcționalități complexe și importante.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Prin urmare, aș vrea să vă spun din ce este făcută Odyssey, în cazul în care doriți să scrieți și voi un mic cod acum.

Aveți baza sursă Odyssey, care se bazează pe două biblioteci principale. Biblioteca Kiwi este o implementare a protocolului de mesaje Postgres. Adică, proto 3 nativ al Postgres este mesaje standard pe care front-end-urile și back-end-urile le pot schimba. Ele sunt implementate în biblioteca Kiwi.

Biblioteca Machinarium este o bibliotecă de implementare a firelor. Un mic fragment din acest Machinarium este scris în limbaj de asamblare. Dar nu vă alarmați, sunt doar 15 rânduri.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Arhitectura Odyssey. Există o mașină principală pe care rulează coroutine. Această mașină implementează acceptarea conexiunilor TCP de intrare și distribuirea acestora între lucrători.

Un handler pentru mai mulți clienți poate lucra în cadrul unui singur lucrător. Firul principal rulează, de asemenea, consola și procesarea sarcinilor crone pentru a șterge conexiunile care nu mai sunt necesare în pool.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Odyssey este testat folosind suita standard de testare Postgres. Pur și simplu rulăm instalarea-verificare prin Bouncer și prin Odyssey, obținem un div nul. Există mai multe teste legate de formatarea datei care nu trec exact la fel în Bouncer și în Odyssey.

În plus, există mulți șoferi care au propriile teste. Și folosim testele lor pentru a testa Odyssey.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În plus, datorită configurației noastre în cascadă, trebuie să testăm diverse pachete: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey pentru a fi siguri că dacă Odyssey a ajuns în vreuna din părțile din cascadă, tot funcționează. asa cum ne asteptam.

Rake

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Folosim Odyssey în producție. Și nu ar fi corect dacă aș spune că totul funcționează. Nu, adică da, dar nu întotdeauna. De exemplu, în producție totul a funcționat, apoi au venit prietenii noștri de la PostgreSQL Professional și au spus că am avut o scurgere de memorie. Chiar au fost, le-am corectat. Dar a fost simplu.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Apoi am descoperit că grupul de conexiuni are conexiuni TLS de intrare și conexiuni TLS de ieșire. Și conexiunile necesită certificate de client și certificate de server.

Certificatele de server Bouncer și Odyssey sunt recitite de pcache-ul lor, dar certificatele client nu trebuie recitite din pcache, deoarece Odyssey nostru scalabil se confruntă în cele din urmă cu performanța sistemului de citire a acestui certificat. Acest lucru a fost o surpriză pentru noi, pentru că nu i-a luat mult să reziste. La început s-a scalat liniar, dar după 20 de conexiuni simultane primite, această problemă a apărut.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Metoda de autentificare conectabilă este capacitatea de a se autentifica folosind instrumente Lunux încorporate. În PgBouncer este implementat în așa fel încât să existe un fir separat pentru a aștepta un răspuns de la PAM și există un fir principal PgBouncer care deservește conexiunea curentă și le poate cere să trăiască în firul PAM.

Nu am implementat acest lucru dintr-un motiv simplu. Avem o mulțime de fire. De ce avem nevoie de asta?

Acest lucru poate crea în cele din urmă probleme prin faptul că, dacă aveți autentificare PAM și autentificare non-PAM, atunci un val mare de autentificare PAM poate întârzia semnificativ autentificarea non-PAM. Acesta este unul dintre acele lucruri pe care nu le-am rezolvat. Dar dacă doriți să o remediați, puteți face acest lucru.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Un alt rake a fost că avem un fir care acceptă toate conexiunile de intrare. Și apoi sunt transferați în grupul de lucrători, unde va avea loc strângerea de mână TLS.

În concluzie, dacă aveți un val coerent de 20 de conexiuni la rețea, toate vor fi acceptate. Și din partea clientului, libpq va începe să raporteze timeout-uri. În mod implicit, pare să fie de 000 secunde.

Dacă toți nu pot intra în baza de date în același timp, atunci nu pot intra în baza de date, deoarece toate acestea pot fi acoperite prin reîncercare non-exponențială.

Am ajuns la concluzia că am copiat schema de la PgBouncer aici cu faptul că avem limitarea numărului de conexiuni TCP la care acceptăm.

Dacă vedem că acceptăm conexiuni, dar în cele din urmă nu au timp să strângă mâna, le punem într-o coadă, astfel încât să nu irosească resursele CPU. Acest lucru duce la faptul că este posibil ca o strângere de mână simultană să nu fie efectuată pentru toate conexiunile care au sosit. Dar măcar cineva va intra în baza de date, chiar dacă încărcarea este destul de grea.

Roadmap

Ce ți-ar plăcea să vezi în viitor în Odyssey? Ce suntem pregătiți să ne dezvoltăm și ce așteptăm de la comunitate?

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Din august 2019.

Iată cum arăta foaia de parcurs Odyssey în august:

  • Am vrut autentificare SCRAM și PAM.
  • Am vrut să redirecționăm solicitările de citire în standby.
  • As dori o repornire online.
  • Și capacitatea de a face pauză pe server.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Jumătate din această foaie de parcurs a fost finalizată, și nu de noi. Și asta e bine. Deci haideți să discutăm ce rămâne și să adăugăm mai multe.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În ceea ce privește trimiterea interogărilor doar în citire în standby? Avem replici care pur și simplu vor încălzi aerul fără a executa solicitări. Avem nevoie de ei pentru a furniza failover și comutare. În cazul unor probleme într-unul dintre centrele de date, aș dori să le ocup cu ceva muncă utilă. Pentru că nu putem configura aceleași procesoare centrale, aceeași memorie diferit, pentru că altfel replicarea nu va funcționa.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În principiu, în Postgres, începând de la 10, este posibil să specificați session_attrs la conectare. Puteți enumera toate gazdele bazei de date din conexiune și puteți spune de ce mergeți la baza de date: scrieți sau numai citire. Și șoferul însuși va selecta prima gazdă din listă care îi place cel mai mult, care îndeplinește cerințele session_attrs.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Dar problema cu această abordare este că nu controlează decalajul de replicare. Este posibil să aveți o copie care a rămas în urmă pentru o perioadă inacceptabilă de timp pentru serviciul dvs. Pentru a permite execuția completă a interogărilor de citire pe o replică, trebuie să sprijinim capacitatea Odyssey de a nu rula atunci când nu poate fi citită.

Odyssey trebuie să meargă la baza de date din când în când și să ceară distanța de replicare față de primar. Și dacă a atins valoarea limită, nu permiteți noi cereri în baza de date, spuneți clientului că trebuie să reinițieze conexiunile și, eventual, să selecteze o altă gazdă pentru a executa cereri. Acest lucru va permite bazei de date să restabilească rapid decalajul de replicare și să revină din nou pentru a răspunde cu o solicitare.

Este dificil de dat un interval de timp pentru implementare, deoarece este open source. Dar, sper, nu 2,5 ani ca colegii mei de la PgBouncer. Aceasta este caracteristica pe care aș dori să o văd în Odyssey.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

În comunitate, oamenii au întrebat despre sprijinul pentru declarația pregătită. Acum puteți crea o declarație pregătită în două moduri. În primul rând, puteți executa comanda SQL, și anume „pregătit”. Pentru a înțelege această comandă SQL, trebuie să învățăm să înțelegem SQL-ul din partea Bouncer. Acest lucru ar fi exagerat, pentru că este exagerat, deoarece avem nevoie de întregul parser. Nu putem analiza fiecare comandă SQL.

Dar există o declarație pregătită la nivel de protocol de mesaj pe proto3. Și acesta este locul în care informațiile că o declarație pregătită este creată vin într-o formă structurată. Și am putea înțelege că pe o conexiune la server clientul a cerut să creeze declarații pregătite. Și chiar dacă tranzacția este închisă, trebuie să menținem conectivitatea între server și client.

Dar aici apare o discrepanță în dialog, deoarece cineva spune că trebuie să înțelegeți ce fel de declarații pregătite a creat clientul și să partajați conexiunea la server între toți clienții care au creat această conexiune la server, adică cine a creat o astfel de declarație pregătită.

Andres Freund a spus că dacă vine la tine un client care a creat deja o astfel de declarație pregătită într-o altă conexiune la server, atunci creează-l pentru el. Dar pare puțin greșit să execute interogări în baza de date în locul clientului, dar din punctul de vedere al dezvoltatorului care scrie protocolul de interacțiune cu baza de date, ar fi convenabil dacă i s-ar oferi pur și simplu o conexiune de rețea în care există o astfel de interogare pregătită.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Și încă o caracteristică pe care trebuie să o implementăm. Acum avem monitorizare compatibilă cu PgBouncer. Putem returna timpul mediu de execuție a interogării. Dar timpul mediu este temperatura medie din spital: unele sunt reci, altele sunt calde - în medie, toată lumea este sănătoasă. Nu este adevarat.

Trebuie să implementăm suport pentru percentile care ar indica faptul că există interogări lente care irosesc resurse și fac monitorizarea mai acceptabilă.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Cel mai important lucru este că vreau versiunea 1.0 (versiunea 1.1 a fost deja lansată). Faptul este că Odyssey este acum în versiunea 1.0rc, adică candidatul pentru lansare. Și toate problemele pe care le-am enumerat au fost rezolvate cu exact aceeași versiune, cu excepția scurgerii de memorie.

Ce va însemna versiunea 1.0 pentru noi? Lansăm Odyssey la bazele noastre. Deja rulează pe bazele noastre de date, dar când ajunge la punctul de 1 de solicitări pe secundă, atunci putem spune că aceasta este versiunea de lansare și aceasta este o versiune care poate fi numită 000.

Mai multe persoane din comunitate au cerut ca versiunea 1.0 să includă pauză și SCRAM. Dar acest lucru va însemna că va trebui să lansăm următoarea versiune în producție, deoarece nici SCRAM, nici pauză nu au fost încă distruse. Dar, cel mai probabil, această problemă va fi rezolvată destul de repede.

Foaia de parcurs Odyssey: ce altceva ne dorim de la un pooler de conexiuni. Andrey Borodin (2019)

Astept cererea ta de tragere. De asemenea, aș dori să aud ce probleme aveți cu Bouncer. Să le discutăm. Poate putem implementa unele funcții de care aveți nevoie.

Acesta este sfârșitul părții mele, aș vrea să vă ascult. Mulțumesc!

întrebări

Dacă îmi setez propriul nume_aplicație, va fi redirecționat corect, inclusiv în gruparea tranzacțiilor în Odyssey?

Odiseea sau Bouncer?

În Odiseea. În Bouncer este aruncat.

Vom face un set.

Și dacă conexiunea mea reală sare pe alte conexiuni, va fi transmisă?

Vom face un set cu toți parametrii care sunt listați în listă. Nu pot spune dacă application_name este în această listă. Cred că l-am văzut acolo. Vom seta toți aceiași parametri. Cu o singură solicitare, setul va face tot ce a fost instalat de client în timpul pornirii.

Mulțumesc, Andrei, pentru raport! Bun reportaj! Mă bucur că Odyssey se dezvoltă din ce în ce mai repede în fiecare minut. Vreau sa continui asa. V-am cerut deja să aveți o conexiune cu mai multe surse de date, astfel încât Odyssey să se poată conecta la diferite baze de date simultan, adică un master slave, și apoi să se conecteze automat la un nou master după failover.

Da, se pare că îmi amintesc această discuție. Acum există mai multe depozite. Dar nu există nicio schimbare între ele. De partea noastră, trebuie să chestionăm serverul că este încă în viață și să înțelegem că a avut loc o failover, care va apela pg_recovery. Am un mod standard de a înțelege că nu am venit la stăpân. Și ar trebui să înțelegem cumva din greșeli sau ce? Adică ideea este interesantă, se discută. Scrie mai multe comentarii. Dacă aveți lucrători care cunosc C, atunci este grozav.

Problema scalării peste replici este de asemenea de interes pentru noi, deoarece dorim să facem adoptarea clusterelor replicate cât mai simplă posibil pentru dezvoltatorii de aplicații. Dar aici aș dori mai multe comentarii, adică exact cum se face, cum se face bine.

Întrebarea este și despre replici. Se pare că ai un master și mai multe replici. Și e clar că merg mai rar la replică decât la master pentru conexiuni, pentru că pot avea diferențe. Ați spus că diferența de date poate fi de așa natură încât să nu vă satisfacă afacerea și nu veți merge acolo până nu va fi replicată. În același timp, dacă nu ați mers acolo mult timp și apoi ați început să mergeți, atunci datele necesare nu vor fi disponibile imediat. Adică, dacă mergem constant la master, atunci cache-ul de acolo este încălzit, dar în replică cache-ul rămâne puțin în urmă.

Da este adevarat. Pcache-ul nu va avea blocurile de date pe care le doriți, cache-ul real nu va avea informații despre tabelele pe care le doriți, planurile nu vor avea interogări analizate, nu va exista absolut nimic.

Și când aveți un fel de cluster și adăugați o nouă replică acolo, atunci în timp ce pornește, totul este rău în el, adică își crește memoria cache.

Am prins ideea. Abordarea corectă ar fi să rulați mai întâi un mic procent de interogări pe replica, ceea ce ar încălzi memoria cache. Aproximativ vorbind, avem o condiție ca să rămânem în urma maestrului cu cel mult 10 secunde. Și această condiție nu este inclusă într-un singur val, ci fără probleme pentru unii clienți.

Da, crește greutatea.

Aceasta este o idee bună. Dar mai întâi trebuie să implementăm această oprire. Mai întâi trebuie să oprim și apoi ne vom gândi cum să pornim. Aceasta este o caracteristică excelentă pentru a o activa fără probleme.

Nginx are această opțiune slowly start într-un cluster pentru server. Și el crește treptat sarcina.

Da, o idee grozavă, o vom încerca când vom ajunge la ea.

Sursa: www.habr.com

Adauga un comentariu