Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Nel suo rapporto, Andrey Borodin vi racconterà come hanno tenuto conto dell'esperienza di scalabilità di PgBouncer durante la progettazione del pooler di connessione Odyssey, mentre lo mettevano in produzione. Inoltre discuteremo di quali funzioni dell'estrattore vorremmo vedere nelle nuove versioni: per noi è importante non solo soddisfare le nostre esigenze, ma sviluppare la comunità degli utenti Одиссея.

Video:

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ciao a tutti! Mi chiamo Andrew.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

In Yandex sviluppo database open source. E oggi abbiamo un argomento sulle connessioni del pool di connessioni.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Se sai come chiamare Connection Pooler in russo, dimmelo. Voglio davvero trovare un buon termine tecnico che dovrebbe essere stabilito nella letteratura tecnica.

L’argomento è piuttosto complicato, perché in molti database il pooler di connessione è integrato e non è nemmeno necessario che tu lo sappia. Naturalmente ci sono alcune impostazioni ovunque, ma in Postgres non funziona in questo modo. E parallelamente (a HighLoad++ 2019) c'è un rapporto di Nikolai Samokhvalov sull'impostazione delle query in Postgres. E a quanto ho capito, sono venute qui persone che avevano già configurato perfettamente le loro query, e queste sono persone che si trovano ad affrontare problemi di sistema più rari legati alla rete e all'utilizzo delle risorse. E in alcuni posti potrebbe essere piuttosto difficile, nel senso che i problemi non sono evidenti.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Yandex ha Postgres. Molti servizi Yandex risiedono in Yandex.Cloud. E abbiamo diversi petabyte di dati che generano almeno un milione di richieste al secondo in Postgres.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E forniamo un cluster abbastanza standard per tutti i servizi: questo è il nodo primario principale del nodo, le solite due repliche (sincrona e asincrona), backup, ridimensionamento delle richieste di lettura sulla replica.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ogni nodo del cluster è Postgres, sul quale, oltre a Postgres e ai sistemi di monitoraggio, è installato anche un pooler di connessioni. Il pooler di connessioni viene utilizzato per la scherma e per il suo scopo principale.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Qual è lo scopo principale del pool di connessioni?

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Postgres adotta un modello di processo quando lavora con un database. Ciò significa che una connessione è un processo, un backend Postgres. E in questo backend ci sono molte cache diverse, che sono piuttosto costose da rendere diverse per connessioni diverse.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Inoltre, il codice Postgres ha un array chiamato procArray. Contiene dati di base sulle connessioni di rete. E quasi tutti gli algoritmi di elaborazione procArray hanno complessità lineare; funzionano sull’intera gamma di connessioni di rete. È un ciclo piuttosto veloce, ma con più connessioni di rete in entrata le cose diventano un po' più costose. E quando le cose diventano un po’ più costose, puoi finire per pagare un prezzo molto alto per molte connessioni di rete.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ci sono 3 approcci possibili:

  • Dal lato dell'applicazione.
  • Lato database.
  • E tra, cioè, tutti i tipi di combinazioni.

Sfortunatamente, il pooler integrato è attualmente in fase di sviluppo. I nostri amici di PostgreSQL Professional si occupano principalmente di questo. Quando apparirà è difficile prevederlo. E infatti abbiamo due soluzioni tra cui l'architetto può scegliere. Si tratta del pool lato applicazione e del pool proxy.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Il pool lato applicazione è il modo più semplice. E quasi tutti i driver client ti offrono un modo: presentare milioni di connessioni nel codice come diverse dozzine di connessioni al database.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Il problema che sorge è che a un certo punto vuoi scalare il backend, vuoi distribuirlo su molte macchine virtuali.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Quindi ti rendi conto che hai molte più zone di disponibilità, diversi data center. E l'approccio di pooling lato client porta a grandi numeri. Quelle grandi sono circa 10 connessioni. Questo è il bordo che può funzionare normalmente.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Se parliamo di proxy pooler, allora ci sono due pooler che possono fare molte cose. Non sono solo pooler. Sono pooler + funzionalità più interessanti. Questo Pgpool и Crunchy-Proxy.

Ma sfortunatamente non tutti hanno bisogno di questa funzionalità aggiuntiva. E questo porta al fatto che i pooler supportano solo il session pooling, cioè un client in entrata, un client in uscita nel database.

Questo non è molto adatto ai nostri scopi, quindi utilizziamo PgBouncer, che implementa il pooling delle transazioni, ovvero le connessioni del server vengono abbinate alle connessioni del client solo per la durata della transazione.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E nel nostro carico di lavoro, questo è vero. Ma ci sono alcuni problemi.Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

I problemi iniziano quando vuoi diagnosticare una sessione, perché tutte le connessioni in entrata sono locali. Tutti sono arrivati ​​con un loopback e in qualche modo diventa difficile tracciare la sessione.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ovviamente puoi usare application_name_add_host. Questo è un modo sul lato Bouncer per aggiungere un indirizzo IP a application_name. Ma application_name è impostato da una connessione aggiuntiva.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

In questo grafico, dove la linea gialla rappresenta le richieste reali e dove la linea blu rappresenta le richieste che entrano nel database. E questa differenza sta proprio nell'installazione di application_name, necessaria solo per il tracciamento, ma non è affatto gratuita.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Inoltre, in Bouncer non è possibile limitare un pool, ovvero il numero di connessioni al database per utente specifico, per database specifico.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Cosa porta questo? Hai un servizio caricato scritto in C++ e da qualche parte nelle vicinanze un piccolo servizio su un nodo che non fa nulla di terribile con il database, ma il suo driver impazzisce. Apre 20 connessioni e tutto il resto aspetterà. Anche il tuo codice è normale.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ovviamente abbiamo scritto una piccola patch per Bouncer che aggiungeva questa impostazione, ovvero limitando i client al pool.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Sarebbe possibile farlo lato Postgres, ovvero limitare i ruoli nel database in base al numero di connessioni.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ma poi perdi la capacità di capire perché non hai connessioni al server. PgBouncer non genera errori di connessione, restituisce sempre le stesse informazioni. E non puoi capire: forse la tua password è cambiata, forse il database è andato perso, forse qualcosa non va. Ma non esiste una diagnosi. Se non è possibile stabilire una sessione, non saprai perché non può essere stabilita.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ad un certo punto guardi i grafici dell'applicazione e vedi che l'applicazione non funziona.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Guarda in alto e vedi che Bouncer è a thread singolo. Questo è un punto di svolta nella vita del servizio. Ti rendi conto che ti stavi preparando a ridimensionare il database in un anno e mezzo e devi ridimensionare il pooler.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Siamo giunti alla conclusione che abbiamo bisogno di più PgBouncer.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

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

Bouncer è stato leggermente patchato.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E hanno fatto in modo che diversi Bouncer potessero essere attivati ​​riutilizzando la porta TCP. E il sistema operativo trasferisce automaticamente le connessioni TCP in entrata tra di loro utilizzando il round robin.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Questo è trasparente per i client, il che significa che sembra che tu abbia un Bouncer, ma hai una frammentazione delle connessioni inattive tra i Bouncer in esecuzione.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E ad un certo momento potresti notare che questi 3 buttafuori mangiano ciascuno il loro nucleo del 100%. Hai bisogno di un bel po' di buttafuori. Perché?

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Perché hai TLS. Hai una connessione crittografata. E se confronti Postgres con e senza TLS, scoprirai che il numero di connessioni stabilite diminuisce di quasi due ordini di grandezza con la crittografia abilitata, perché l'handshake TLS consuma risorse della CPU.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E in alto puoi vedere alcune funzioni crittografiche che vengono eseguite quando c'è un'ondata di connessioni in entrata. Poiché il nostro primario può passare da una zona di disponibilità all'altra, un'ondata di connessioni in entrata è una situazione abbastanza tipica. Cioè, per qualche motivo il vecchio primario non era disponibile, l'intero carico è stato inviato a un altro data center. Verranno tutti a salutare TLS contemporaneamente.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E un gran numero di strette di mano TLS potrebbero non salutare più Bouncer, ma stringergli la gola. A causa del timeout, l'ondata di connessioni in entrata potrebbe non essere smorzata. Se riprovi a raggiungere la base senza un arretramento esponenziale, non torneranno più e più volte in un'onda coerente.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ecco un esempio di 16 PgBouncer che caricano 16 core al 100%.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Siamo arrivati ​​alla cascata PgBouncer. Questa è la migliore configurazione che può essere ottenuta sul nostro carico con Bouncer. I nostri Bouncer esterni vengono utilizzati per l'handshake TCP, mentre i Bouncer interni vengono utilizzati per il vero pooling, in modo da non frammentare troppo le connessioni esterne.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

In questa configurazione è possibile un riavvio graduale. Puoi riavviare tutti questi 18 buttafuori uno per uno. Ma mantenere una tale configurazione è piuttosto difficile. Gli amministratori di sistema, DevOps e le persone effettivamente responsabili di questo server non saranno molto soddisfatti di questa soluzione.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Sembrerebbe che tutti i nostri miglioramenti possano essere promossi all'open source, ma Bouncer non è molto ben supportato. Ad esempio, la possibilità di eseguire più PgBouncer su una porta è stata confermata un mese fa. Diversi anni fa è stata lanciata una richiesta pull con questa funzionalità.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

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

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

O un altro esempio. In Postgres puoi annullare una richiesta in corso inviando il segreto a una connessione diversa senza un'autenticazione non necessaria. Ma alcuni client inviano semplicemente un reset TCP, cioè interrompono la connessione di rete. Cosa farà Bouncer? Non farà nulla. Continuerà a eseguire la richiesta. Se hai ricevuto un numero enorme di connessioni che hanno creato un database con piccole richieste, non sarà sufficiente disconnettere semplicemente la connessione da Bouncer; dovrai anche completare quelle richieste in esecuzione nel database.

Questo è stato corretto e questo problema non è stato ancora integrato nell'upstream di Bouncer.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E così siamo giunti alla conclusione che abbiamo bisogno del nostro pool di connessioni, che sarà sviluppato, patchato, in cui i problemi possono essere risolti rapidamente e che, ovviamente, deve essere multi-thread.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Impostiamo il multithreading come attività principale. Dobbiamo essere in grado di gestire bene l’ondata di connessioni TLS in entrata.

Per fare ciò, abbiamo dovuto sviluppare una libreria separata chiamata Machinarium, progettata per descrivere gli stati macchina di una connessione di rete come codice sequenziale. Se guardi il codice sorgente di libpq, vedrai alcune chiamate piuttosto complesse che possono restituirti un risultato e dire: "Chiamami più tardi. Al momento ho l'I/O, ma quando l'I/O scomparirà avrò un carico sul processore." E questo è uno schema multilivello. La comunicazione di rete è solitamente descritta da una macchina a stati. Molte regole come "Se in precedenza ho ricevuto un'intestazione di pacchetto di dimensione N, ora sto aspettando N byte", "Se ho inviato un pacchetto SYNC, ora sto aspettando un pacchetto con i metadati dei risultati". Il risultato è un codice piuttosto difficile e controintuitivo, come se il labirinto fosse convertito in scansione lineare. Abbiamo fatto in modo che invece di una macchina a stati, il programmatore descriva il percorso principale di interazione sotto forma di codice imperativo ordinario. È solo che in questo codice imperativo è necessario inserire i punti in cui la sequenza di esecuzione deve essere interrotta in attesa dei dati dalla rete, passando il contesto di esecuzione a un'altra coroutine (filo verde). Questo approccio è simile al fatto che annotiamo in fila il percorso più atteso nel labirinto e quindi vi aggiungiamo dei rami.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Di conseguenza, abbiamo un thread che accetta TCP e il round robin passa la connessione TPC a molti lavoratori.

In questo caso, ogni connessione client viene sempre eseguita su un processore. E questo ti consente di renderlo adatto alla cache.

Inoltre, abbiamo leggermente migliorato la raccolta dei pacchetti piccoli in un unico pacchetto grande per alleggerire lo stack TCP del sistema.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Inoltre, abbiamo migliorato il pooling transazionale nel senso che Odyssey, quando configurato, può inviare CANCEL e ROLLBACK in caso di errore di connessione di rete, cioè se nessuno è in attesa di una richiesta, Odyssey dirà al database di non tentare di soddisfare la richiesta che potrebbe sprecare risorse preziose.

E quando possibile, manteniamo le connessioni allo stesso client. Ciò evita di dover reinstallare application_name_add_host. Se ciò è possibile, non è necessario reimpostare ulteriormente i parametri necessari per la diagnostica.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Lavoriamo nell'interesse di Yandex.Cloud. E se utilizzi PostgreSQL gestito e hai installato un pool di connessioni, puoi creare una replica logica verso l'esterno, ovvero lasciarci, se lo desideri, utilizzando la replica logica. Il buttafuori non rilascerà il flusso di replica logica all'esterno.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Questo è un esempio di impostazione della replica logica.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Inoltre, abbiamo il supporto per la replica fisica verso l'esterno. Nel Cloud, ovviamente, questo è impossibile, perché in tal caso il cluster ti fornirà troppe informazioni su se stesso. Ma nelle tue installazioni, se hai bisogno della replica fisica tramite il pool di connessioni in Odyssey, questo è possibile.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Odyssey ha un monitoraggio completamente compatibile con PgBouncer. Abbiamo la stessa console che esegue quasi tutti gli stessi comandi. Se manca qualcosa, invia una richiesta pull, o almeno un problema su GitHub, e completeremo i comandi necessari. Ma abbiamo già le funzionalità principali della console PgBouncer.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E, naturalmente, abbiamo l'inoltro degli errori. Restituiremo l'errore riportato dal database. Riceverai informazioni sul motivo per cui non sei incluso nel database e non solo sul fatto che non sei incluso in esso.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Questa funzionalità è disabilitata nel caso in cui sia necessaria la compatibilità al 100% con PgBouncer. Possiamo comportarci come Bouncer, giusto per essere sicuri.

Разработка

Qualche parola sul codice sorgente di Odyssey.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

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

Ad esempio, ci sono i comandi “Pausa / Riprendi”. Di solito vengono utilizzati per aggiornare il database. Se devi aggiornare Postgres, puoi metterlo in pausa nel pooler di connessione, eseguire pg_upgrade, quindi riprendere. E dal lato del cliente sembrerà che il database stia semplicemente rallentando. Questa funzionalità ci è stata offerta da persone della comunità. Non è ancora congelata, ma presto lo sarà tutto. (Già congelato)

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

https://github.com/yandex/odyssey/pull/73 - già congelato

Inoltre, una delle nuove funzionalità di PgBouncer è il supporto per l'autenticazione SCRAM, che ci è stata offerta anche da una persona che non lavora in Yandex.Cloud. Entrambi sono funzionalità complesse e importanti.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Vorrei quindi raccontarvi di cosa è fatto Odyssey, nel caso in cui anche voi vogliate scrivere un po' di codice adesso.

Hai la base sorgente Odyssey, che si basa su due librerie principali. La libreria Kiwi è un'implementazione del protocollo di messaggi Postgres. Cioè, il proto nativo 3 di Postgres è costituito da messaggi standard che front-end e back-end possono scambiarsi. Sono implementati nella libreria Kiwi.

La libreria Machinarium è una libreria di implementazione dei thread. Un piccolo frammento di questo Machinarium è scritto in linguaggio assembly. Ma non allarmarti, ci sono solo 15 righe.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Architettura dell'Odissea. Esiste una macchina principale su cui sono in esecuzione le coroutine. Questa macchina implementa l'accettazione delle connessioni TCP in entrata e la loro distribuzione tra i lavoratori.

Un gestore per diversi clienti può lavorare all'interno di un lavoratore. Il thread principale esegue anche la console e l'elaborazione delle attività crone per eliminare le connessioni che non sono più necessarie nel pool.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Odyssey viene testato utilizzando la suite di test standard Postgres. Eseguiamo semplicemente install-check tramite Bouncer e tramite Odyssey otteniamo un div nullo. Esistono diversi test relativi alla formattazione della data che non passano esattamente allo stesso modo in Bouncer e in Odyssey.

Inoltre, ci sono molti driver che eseguono i propri test. E usiamo i loro test per testare l'Odyssey.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Inoltre, a causa della nostra configurazione a cascata, dobbiamo testare vari bundle: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey per essere sicuri che se Odyssey finisse in una qualsiasi delle parti della cascata, funzioni ancora come ci aspettiamo.

rastrello

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Usiamo Odyssey in produzione. E non sarebbe giusto se dicessi che tutto funziona e basta. No, cioè sì, ma non sempre. Ad esempio, in produzione tutto ha funzionato, poi sono venuti i nostri amici di PostgreSQL Professional e hanno detto che avevamo una perdita di memoria. Lo erano davvero, li abbiamo corretti. Ma era semplice.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Poi abbiamo scoperto che il pooler di connessioni ha connessioni TLS in entrata e connessioni TLS in uscita. E le connessioni richiedono certificati client e certificati server.

I certificati del server Bouncer e Odyssey vengono riletti dalla loro pcache, ma i certificati client non hanno bisogno di essere riletti dalla pcache, perché il nostro Odyssey scalabile alla fine si scontra con le prestazioni del sistema di lettura di questo certificato. Questa è stata una sorpresa per noi, perché non gli ci è voluto molto per resistere. All'inizio scalava in modo lineare, ma dopo 20 connessioni simultanee in entrata questo problema si è manifestato.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Il metodo di autenticazione collegabile è la capacità di autenticarsi utilizzando gli strumenti Lunux integrati. In PgBouncer è implementato in modo tale che ci sia un thread separato che attende una risposta da PAM e c'è un thread PgBouncer principale che serve la connessione corrente e può chiedere loro di vivere nel thread PAM.

Non l'abbiamo implementato per un semplice motivo. Abbiamo molti thread. perché ne abbiamo bisogno?

Ciò può in definitiva creare problemi in quanto se si dispone dell'autenticazione PAM e dell'autenticazione non PAM, una grande ondata di autenticazione PAM può ritardare in modo significativo l'autenticazione non PAM. Questa è una di quelle cose che non abbiamo risolto. Ma se vuoi aggiustarlo, puoi farlo.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Un altro vantaggio è che abbiamo un thread che accetta tutte le connessioni in entrata. E poi vengono trasferiti al pool di lavoratori, dove avrà luogo l'handshake TLS.

In conclusione, se si dispone di un'onda coerente di 20 connessioni di rete, verranno accettate tutte. E sul lato client libpq inizierà a segnalare i timeout. Per impostazione predefinita sembra che siano 000 secondi.

Se non riescono tutti ad entrare nel database contemporaneamente, non possono entrare nel database, perché tutto ciò può essere coperto da nuovi tentativi non esponenziali.

Siamo giunti alla conclusione che abbiamo copiato qui lo schema di PgBouncer limitando il numero di connessioni TCP a cui accettiamo.

Se vediamo che stiamo accettando connessioni, ma alla fine non hanno tempo per l'handshake, le mettiamo in coda in modo che non sprechino risorse della CPU. Ciò porta al fatto che potrebbe non essere eseguito un handshake simultaneo per tutte le connessioni arrivate. Ma almeno qualcuno entrerà nel database, anche se il carico sarà piuttosto pesante.

Roadmap

Cosa ti piacerebbe vedere in futuro in Odyssey? Cosa siamo pronti a sviluppare noi stessi e cosa ci aspettiamo dalla comunità?

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ad agosto 2019.

Ecco come appariva la tabella di marcia di Odyssey ad agosto:

  • Volevamo l'autenticazione SCRAM e PAM.
  • Volevamo inoltrare le richieste di lettura in standby.
  • Vorrei una ripartenza online.
  • E la possibilità di mettere in pausa sul server.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Metà di questa tabella di marcia è stata completata, e non da noi. E questo è positivo. Quindi discutiamo di ciò che rimane e aggiungiamo altro.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Per quanto riguarda l'inoltro delle query di sola lettura allo standby? Abbiamo repliche che semplicemente riscalderanno l'aria senza eseguire richieste. Ne abbiamo bisogno per fornire failover e switchover. In caso di problemi in uno dei data center, vorrei occuparlo con qualche lavoro utile. Perché non possiamo configurare gli stessi processori centrali, la stessa memoria in modo diverso, perché altrimenti la replica non funzionerà.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

In linea di principio in Postgres, a partire da 10, è possibile specificare session_attrs al momento della connessione. Puoi elencare tutti gli host del database nella connessione e dire perché stai andando al database: scrittura o sola lettura. E l'autista stesso selezionerà il primo host nell'elenco che gli piace di più, che soddisfa i requisiti di session_attrs.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Ma il problema con questo approccio è che non controlla il ritardo di replica. Potresti avere alcune repliche rimaste indietro per un periodo di tempo inaccettabile per il tuo servizio. Per abilitare l'esecuzione completa delle query di lettura su una replica, dobbiamo essenzialmente supportare la capacità di Odyssey di non essere eseguito quando non può essere letto.

Odyssey deve recarsi di tanto in tanto nel database e chiedere la distanza di replica dal primario. E se ha raggiunto il valore limite, non consentire nuove richieste nel database, comunica al client che deve riavviare le connessioni ed eventualmente selezionare un altro host per eseguire le richieste. Ciò consentirà al database di ripristinare rapidamente il ritardo di replica e tornare nuovamente a rispondere con una richiesta.

È difficile fornire un periodo di tempo per l’implementazione, perché è open source. Ma, spero, non 2,5 anni come i miei colleghi di PgBouncer. Questa è la caratteristica che mi piacerebbe vedere nell'Odissea.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Nella comunità, le persone hanno chiesto supporto per la dichiarazione preparata. Ora puoi creare una dichiarazione preparata in due modi. Innanzitutto è possibile eseguire il comando SQL, ovvero "preparato". Per comprendere questo comando SQL, dobbiamo imparare a comprendere l'SQL sul lato Bouncer. Questo sarebbe eccessivo, perché è eccessivo, poiché abbiamo bisogno dell'intero parser. Non possiamo analizzare ogni comando SQL.

Ma c'è una dichiarazione preparata a livello di protocollo di messaggio su proto3. Ed è qui che l'informazione relativa alla creazione di una dichiarazione preparata arriva in forma strutturata. E potremmo supportare la comprensione che su qualche connessione al server il client ha chiesto di creare istruzioni preparate. E anche se la transazione viene chiusa, dobbiamo comunque mantenere la connettività tra il server e il client.

Ma qui sorge una discrepanza nel dialogo, perché qualcuno dice che è necessario capire che tipo di istruzioni preparate ha creato il client e condividere la connessione al server tra tutti i client che hanno creato questa connessione al server, cioè chi ha creato tale istruzione preparata.

Andres Freund ha detto che se viene da te un cliente che ha già creato una dichiarazione così preparata in un'altra connessione al server, creala per lui. Ma sembra un po' sbagliato eseguire query nel database invece che nel client, ma dal punto di vista dello sviluppatore che scrive il protocollo per interagire con il database, sarebbe conveniente se gli fosse semplicemente fornita una connessione di rete in cui esiste una query così preparata.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

E un'altra funzionalità che dobbiamo implementare. Ora abbiamo un monitoraggio compatibile con PgBouncer. Possiamo restituire il tempo medio di esecuzione della query. Ma il tempo medio è la temperatura media in ospedale: alcuni hanno freddo, altri hanno caldo: in media, tutti sono sani. Non è vero.

È necessario implementare il supporto per i percentili che indichino la presenza di query lente che sprecano risorse e rendano il monitoraggio più accettabile.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

La cosa più importante è che voglio la versione 1.0 (la versione 1.1 è già stata rilasciata). Il fatto è che Odyssey è ora nella versione 1.0rc, ovvero release candidate. E tutti i problemi che ho elencato sono stati risolti esattamente con la stessa versione, ad eccezione della perdita di memoria.

Cosa significherà per noi la versione 1.0? Stiamo lanciando Odyssey nelle nostre basi. È già in esecuzione sui nostri database, ma quando raggiunge il punto di 1 di richieste al secondo, allora possiamo dire che questa è la versione di rilascio e questa è una versione che può essere chiamata 000.

Molte persone nella comunità hanno chiesto che la versione 1.0 includa pause e SCRAM. Ma questo significherà che dovremo mettere in produzione la prossima versione, perché né SCRAM né pause sono stati ancora eliminati. Ma, molto probabilmente, questo problema verrà risolto abbastanza rapidamente.

Odyssey roadmap: cos'altro vogliamo da un connection pooler. Andrea Borodin (2019)

Sto aspettando la tua richiesta di pull. Mi piacerebbe anche sapere quali problemi hai con Bouncer. Discutiamone. Forse possiamo implementare alcune funzioni di cui hai bisogno.

Questa è la fine della mia parte, vorrei ascoltarvi. Grazie!

domande

Se imposto il mio application_name, verrà inoltrato correttamente, incluso nel pooling delle transazioni in Odyssey?

Odissea o buttafuori?

Nell'Odissea. In Bouncer viene lanciato.

Faremo una serie.

E se la mia connessione reale salta su altre connessioni, verrà trasmessa?

Creeremo un insieme di tutti i parametri elencati nell'elenco. Non riesco a capire se application_name è in questo elenco. Penso di averlo visto lì. Imposteremo tutti gli stessi parametri. Con una sola richiesta il set eseguirà tutto ciò che è stato installato dal client durante l'avvio.

Grazie, Andrey, per la segnalazione! Buon rapporto! Sono felice che Odyssey si sviluppi sempre più velocemente ogni minuto. Voglio continuare così. Ti abbiamo già chiesto di avere una connessione multi-origine dati in modo che Odyssey possa connettersi a diversi database contemporaneamente, ad esempio un master slave, e quindi connettersi automaticamente a un nuovo master dopo il failover.

Sì, mi sembra di ricordare questa discussione. Ora ci sono diversi depositi. Ma non è possibile passare da uno all'altro. Da parte nostra, dobbiamo interrogare il server per verificare che sia ancora vivo e capire che si è verificato un failover, che chiamerà pg_recovery. Ho un modo standard di capire che non siamo venuti dal maestro. E dovremmo capire in qualche modo dagli errori o cosa? Cioè, l'idea è interessante, è in discussione. Scrivi più commenti. Se hai lavoratori che conoscono C, allora è fantastico.

Anche la questione della scalabilità tra le repliche è di nostro interesse, perché vogliamo rendere l'adozione di cluster replicati il ​​più semplice possibile per gli sviluppatori di applicazioni. Ma qui vorrei più commenti, ad es. esattamente come farlo, come farlo bene.

La questione riguarda anche le repliche. Si scopre che hai un master e diverse repliche. Ed è chiaro che per i collegamenti si rivolgono alla replica meno spesso che al master, perché possono avere delle differenze. Hai detto che la differenza nei dati potrebbe essere tale da non soddisfare la tua attività e non ci andrai finché non verrà replicata. Allo stesso tempo, se non ci sei andato per molto tempo e poi hai iniziato ad andarci, i dati necessari non saranno immediatamente disponibili. Cioè, se andiamo costantemente al master, la cache si riscalda, ma nella replica la cache è leggermente ritardata.

Si è vero. La pcache non avrà i blocchi di dati che desideri, la cache reale non avrà informazioni sulle tabelle che desideri, i piani non avranno query analizzate, non ci sarà nulla.

E quando hai una sorta di cluster e aggiungi una nuova replica lì, mentre si avvia, tutto va male, ad es. aumenta la sua cache.

Ho avuto l'idea. L'approccio corretto sarebbe quello di eseguire prima una piccola percentuale di query sulla replica, il che riscalderebbe la cache. In parole povere, abbiamo una condizione che dobbiamo restare indietro rispetto al master di non più di 10 secondi. E questa condizione non è inclusa in un'ondata, ma per alcuni clienti senza intoppi.

Sì, aumenta il peso.

Questa è una buona idea. Ma prima dobbiamo attuare questa chiusura. Per prima cosa dobbiamo spegnerlo e poi penseremo a come accenderlo. Questa è un'ottima funzionalità da abilitare senza problemi.

Nginx ha questa opzione slowly start in un cluster per il server. E aumenta gradualmente il carico.

Sì, ottima idea, la proveremo quando ci riusciremo.

Fonte: habr.com

Aggiungi un commento