Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Nella presentazione, Andrei Borodin parlerà di come hanno considerato l'esperienza di scalabilità di PgBouncer nella progettazione del connection pooler. Odyssey, e come è stato implementato in produzione. Inoltre, discuteremo quali funzionalità vorremmo vedere nelle nuove versioni del pooler: è importante per noi non solo soddisfare le esigenze, ma anche sviluppare la comunità degli utenti. Odyssey.

Video:

Riproduci video

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Ciao a tutti! Mi chiamo Andrei.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

In Yandex mi occupo dello sviluppo di database open source. E oggi discuteremo del tema del connection pooler.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Se sai come si chiama connection pooler in russo, fammelo sapere. Vorrei davvero trovare un buon termine tecnico che si stabilisca nella letteratura tecnica.

L'argomento è piuttosto complesso, perché in molti database il connection pooler è integrato e non è nemmeno necessario saperlo. Certamente ci sono alcune impostazioni ovunque, ma in Postgres non funziona così. E parallelamente (al HighLoad++ 2019) si tiene una relazione di Nikolai Samokhvalov sulla configurazione delle query in Postgres. E da quello che capisco, qui sono venute persone che hanno già configurato perfettamente le query, e queste persone affrontano problemi sistemici più rari legati alla rete e all'utilizzo delle risorse. E in alcuni casi potrebbe essere stata piuttosto difficile, nel senso che i problemi sono poco evidenti.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

In Yandex c'è Postgres. Molti servizi di Yandex vivono nell'Yandex.Cloud. E abbiamo diversi petabyte di dati che generano non meno di un milione di query al secondo in Postgres.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E forniamo un cluster piuttosto standard a tutti i servizi – questa è la principale nodo primaria del nodo, due repliche comuni (sincrona e asincrona), backup, scalabilità delle query di lettura sulla replica.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Ogni nodo del cluster è un Postgres, su cui oltre a Postgres e ai sistemi di monitoraggio è stato installato anche il connection pooler. Il connection pooler è utilizzato per il fencing e per il suo scopo principale.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Qual è lo scopo principale del connection pooler?

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

In Postgres si adotta un modello di processo per la gestione del database. Ciò significa che una connessione corrisponde a un processo, un backend di Postgres. In questo backend ci sono molteplici cache diverse, e crearne di differenti per ciascuna connessione è piuttosto costoso.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Inoltre, nel codice di Postgres esiste un array chiamato procArray. Esso contiene dati fondamentali sulle connessioni di rete. Quasi tutti gli algoritmi che elaborano procArray hanno una complessità lineare, poiché attraversano l'intero array delle connessioni di rete. Questo è un ciclo abbastanza veloce, ma con un elevato numero di connessioni in ingresso, i costi aumentano leggermente. Quando i costi aumentano, si potrebbe finire per pagare un prezzo molto elevato per un numero considerevole di connessioni di rete.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Esistono 3 approcci possibili:

  • Lato applicazione.
  • Lato database.
  • E tra i due, cioè varie combinazioni.

Purtroppo, il pooler integrato è attualmente in fase di sviluppo. I colleghi della PostgreSQL Professional se ne stanno occupando principalmente. È difficile prevedere quando sarà disponibile. E in effetti, l'architetto ha davanti due soluzioni. Si tratta del pooling lato applicazione e del proxy pool.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Il pooling lato applicazione è il modo più semplice. Quasi tutti i driver client vi offrono un modo per rappresentare milioni delle vostre connessioni nel codice come alcune decine di connessioni al database.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Si presenta il problema che, a un certo punto, si desidera scalare il backend, si vuole distribuirlo su molte macchine virtuali.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Poi vi rendete conto che avete anche diverse zone di disponibilità, diversi data center. E l'approccio con il pooling client-side porta a numeri elevati. Elevati sono circa 10.000 connessioni. Questo è il limite per ciò che può funzionare normalmente.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Parlando di proxy pooler, ci sono due pooler che sanno fare molte cose. Non sono solo pooler. Sono pooler + altra funzionalità interessante. Questi sono Pgpool e Crunchy-Proxy.

Tuttavia, sfortunatamente, questa funzionalità aggiuntiva non è necessaria per tutti. Questo porta a una situazione in cui i pooler supportano solo il pooling delle sessioni, ossia un cliente in entrata e un cliente in uscita nel database.

Per i nostri scopi, non è molto adatto, quindi utilizziamo PgBouncer, che implementa il transaction pooling, ossia le connessioni server sono associate alle connessioni client solo per la durata della transazione.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E sulla nostra carico – è vero. Ma ci sono alcuni problemi.Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

I problemi iniziano quando si desidera diagnosticare una sessione, perché tutte le connessioni in entrata sono locali. Sono tutte provenienti da loopback e diventare difficile tracciare la sessione.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Certo, puoi utilizzare application_name_add_host. Questo è un modo per Bouncer di aggiungere l'indirizzo IP a application_name. Ma application_name viene impostato con una connessione aggiuntiva.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Inoltre, in Bouncer non è possibile limitare un pool, cioè il numero di connessioni al database per un determinato utente o un determinato database.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

A cosa porta questo? Avete un servizio carico, scritto in C++, e vicino c'è un piccolo servizio su Node che non fa niente di grave con il database, ma il suo driver è sballato. Apre 20.000 connessioni, mentre tutto il resto aspetta. Anche il vostro codice è a posto.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Certo, abbiamo scritto una piccola patch per Bouncer, che ha aggiunto questa impostazione, cioè il limite dei clienti sul pool.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Sarebbe possibile fare questo lato Postgres, cioè limitare il numero di connessioni per le ruoli nel database.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Ma in tal caso si perde la possibilità di capire perché non ci sono connessioni con il server. PgBouncer non restituisce un errore di connessione, riporta sempre la stessa informazione. E non puoi capire: forse la password è cambiata, forse il database è semplicemente caduto, forse c'è qualcosa che non va. Ma non c'è alcuna diagnosi. Se non si può stabilire una sessione, non si scopre perché non è possibile farlo.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

A un certo punto, guardate i grafici dell'applicazione e vedete che l'applicazione non funziona.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Guarda in cima e vedi che Bouncer è monoprodotto. Questo è un punto di svolta nella vita del servizio. Capisci che ti stavi preparando a scalare il database tra un anno e mezzo, ma ora devi scalare il pooler.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

Abbiamo applicato qualche patch a Bouncer.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E abbiamo fatto in modo che possano essere avviati più Bouncer riutilizzando la porta TCP. Il sistema operativo gestisce automaticamente le connessioni TCP in entrata tra di loro con un round-robin.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Questo è trasparente per i clienti, cioè tutto appare come se avessi un solo Bouncer, ma hai una frammentazione delle connessioni idle tra i Bouncer attivi.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E a un certo punto potresti notare che questi 3 Bouncer utilizzano ciascuno il proprio core al 100%. Hai bisogno di un numero considerevole di Bouncer. Perché?

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Nel pannello, puoi vedere molte funzioni crittografiche che vengono eseguite durante le ondate di connessioni in entrata. Poiché il nostro primary può passare tra le aree di disponibilità, le ondate di connessioni in entrata sono una situazione piuttosto comune. Cioè, per qualche motivo, il vecchio primary non era disponibile e tutto il carico è stato inviato in un altro data center. Tutti arriveranno contemporaneamente per salutare con TLS.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E un gran numero di handshake TLS potrebbe non salutare più il Bouncer, ma strozzarlo. A causa del timeout, l'ondata di connessioni in entrata può diventare persistente. Se hai retry nel database senza exponential backoff, non arriveranno continuamente come un'ondata coerente.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Siamo arrivati al PgBouncer a cascata. Questa è la migliore configurazione che possiamo raggiungere con il nostro carico su Bouncer. I Bouncer esterni servono per il TCP handshake, mentre i Bouncer interni servono per il pooling reale, così da non frammentare eccessivamente le connessioni esterne.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

In questa configurazione è possibile un riavvio fluido. Puoi riavviare tutti questi 18 Bouncer uno alla volta. Tuttavia, mantenere questa configurazione è piuttosto complesso. Gli amministratori di sistema, i DevOps e le persone che sono realmente responsabili di questo server potrebbero non apprezzare questa soluzione.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Potrebbe sembrare che possiamo promuovere tutte le nostre modifiche come open source, ma il supporto per Bouncer non è molto buono. Ad esempio, la possibilità di avviare più PgBouncer sulla stessa porta è stata implementata un mese fa. E la pull request per questa funzione risale a diversi anni fa.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

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

Un altro esempio. In Postgres puoi annullare una query in esecuzione inviando un segreto su una connessione diversa senza ulteriori autenticazioni. Ma alcuni client inviano semplicemente un TCP-reset, cioè interrompono la connessione di rete. Cosa farà Bouncer in questo caso? Non farà nulla. Continuerà a eseguire la query. Se hai ricevuto un numero enorme di connessioni che con piccole query hanno sovraccaricato il database, quindi semplicemente staccare la connessione da Bouncer non basterà; sarà necessario anche concludere quelle query che stanno girando nel database.

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

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E così siamo giunti alla conclusione che abbiamo bisogno di un nostro connection pooler, che si sviluppi, venga patchato, nel quale sia possibile risolvere rapidamente i problemi e che, ovviamente, debba essere multithreading.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Abbiamo fissato la multithreading come obiettivo principale. Dobbiamo gestire bene l'ondata di connessioni TLS in ingresso.

Per questo, abbiamo dovuto sviluppare una libreria separata chiamata Machinarium, destinata a descrivere gli stati delle macchine di una connessione di rete come un codice sequenziale. Se guardi nel codice sorgente di libpq, vedrai delle chiamate piuttosto complesse che possono restituirti un risultato e dirti: "Chiamami più tardi. Al momento sto eseguendo IO, ma quando l'IO sarà completato sarò sotto carico per il processore". E questo è uno schema multilivello. L'interazione di rete è solitamente descritta come una macchina a stati. Con molte regole del tipo "Se in precedenza ho ricevuto un'intestazione di pacchetto di dimensione N, allora ora attendo N byte", "Se ho inviato un pacchetto SYNC, allora ora attendo un pacchetto con i metadati del risultato". Di conseguenza, si ottiene un codice piuttosto difficile e controintuitivo, come se un labirinto fosse trasformato in un elenco lineare. Abbiamo fatto in modo che invece di una macchina a stati, il programmatore descrivesse il percorso principale di interazione sotto forma di codice imperativo normale. Semplicemente, 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 ad un'altra coroutina (green thread). Questo approccio è simile a quello in cui segniamo sequenzialmente il percorso più previsto nel labirinto e poi aggiungiamo diramazioni.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Alla fine, abbiamo un flusso che gestisce il TCP accept e utilizza un bilanciamento round-robin per trasferire molteplici connessioni TPC ai workers.

Ogni connessione client, infatti, funziona sempre su un singolo processore, il che la rende cache-friendly.

Inoltre, abbiamo migliorato il processo di unione dei piccoli pacchetti in un unico pacchetto per alleggerire lo stack TCP di sistema.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Abbiamo anche migliorato il pooling delle transazioni in modo tale che, con la configurazione appropriata, Odyssey possa inviare CANCEL e ROLLBACK in caso di interruzione della connessione di rete, cioè se non c'è nessuno in attesa della richiesta, Odyssey dirà al database di non cercare di eseguire quella richiesta che potrebbe consumare risorse preziose.

E, quando possibile, manteniamo le connessioni associate allo stesso client. Questo evita di dover reinstallare application_name_add_host. Se fattibile, non ci sono ulteriori reinstallazioni dei parametri necessari per la diagnosi.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Lavoriamo per conto di Yandex.Cloud. Se utilizzate managed PostgreSQL e avete impostato un connection pooler, potete creare una replica logica verso l'esterno, ossia potete distaccarvi da noi se lo desiderate, attraverso la replica logica. Il Bouncer non restituirà il flusso della replica logica verso l'esterno.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Questo è un esempio di configurazione della replica logica.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Inoltre, supportiamo la replica fisica verso l'esterno. Nel Cloud, ciò è ovviamente impossibile, perché in tal caso il cluster fornirebbe troppe informazioni su di sé. Tuttavia, nelle vostre installazioni, se avete bisogno di replica fisica tramite connection pooler in Odyssey, è possibile.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

In Odyssey, è disponibile un monitoraggio completamente compatibile con PgBouncer. Abbiamo una console simile che esegue quasi tutti gli stessi comandi. Se manca qualcosa, inviate un pull request o, almeno, un issue su GitHub; ci impegneremo a completare i comandi necessari. Ma la funzionalità principale della console di PgBouncer è già presente.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E, ovviamente, abbiamo l'error forwarding. Restituiremo l'errore segnalato dal database. Riceverete informazioni sul motivo per cui non riuscite a connettervi al database, e non semplicemente che non ci riuscite.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Questa opzione è disattivata nel caso in cui necessiti di una compatibilità al 100% con PgBouncer. Possiamo comportarci esattamente come Bouncer, giusto per sicurezza.

Sviluppo

Qualche parola sul codice sorgente di Odyssey.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

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

Ad esempio, ci sono comandi come "Pausa / Riprendi". Questi vengono solitamente utilizzati per aggiornare il database. Se hai bisogno di aggiornare Postgres, puoi mettere in pausa il pool di connessioni, eseguire pg_upgrade e poi riprendere. Per il cliente sembrerà semplicemente che il database fosse in stallo. Questa funzionalità ci è stata fornita dalla comunità. Non è ancora stata integrata, ma sarà presto. (Già integrata)

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

https://github.com/yandex/odyssey/pull/73 — già integrata

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

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Pertanto, vorrei raccontarti di cosa è fatto Odyssey, chissà che anche tu voglia scrivere un po' di codice.

Hai una base di origine Odyssey che si basa su due librerie principali. La libreria Kiwi è un'implementazione del protocollo di messaggistica di Postgres. In altre parole, il proto 3 nativo di Postgres sono i messaggi standard che i frontend e i backend possono scambiarsi. Sono implementati nella libreria Kiwi.

La libreria Machinarium è un'implementazione dei flussi. Un piccolo frammento di questo Machinarium è scritto in assembler. Ma non preoccuparti, sono solo 15 righe.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Architettura di Odyssey. C'è una macchina principale in cui sono in esecuzione le coroutine. In questa macchina viene gestito l'accettamento delle connessioni TCP in entrata e la distribuzione tra i workers.

All'interno di un worker può operare un gestore per più client. Inoltre, nel thread principale girano la console e l'elaborazione dei compiti crone per rimuovere le connessioni che non sono più necessarie nel pool.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Per testare Odyssey si utilizza un set di test standard di Postgres. Basta eseguire install-check tramite Bouncer e attraverso Odyssey, si ottiene un div nullo. Ci sono diversi test relativi alla formattazione delle date che non passano affatto nello stesso modo in Bouncer e in Odyssey.

Inoltre, ci sono molti driver che hanno i propri test. E utilizziamo i loro test per testare Odyssey.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Inoltre, a causa della nostra configurazione a cascata, dobbiamo testare diverse combinazioni: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey, per assicurarci che, se Odyssey si trova in una delle parti della cascata, funzioni ancora come ci aspettiamo.

Rastrelli

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Utilizziamo Odyssey in produzione. E non sarebbe corretto dire che tutto funziona semplicemente. No, cioè, sì, ma non sempre. Ad esempio, in produzione tutto funzionava, poi sono arrivati i nostri amici di PostgreSQL Professional e ci hanno detto che avevamo una perdita di memoria. Era vero, l'abbiamo risolta. Ma è stata una cosa semplice.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Poi abbiamo scoperto che nel connection pooler ci sono connessioni TLS in entrata e connessioni TLS in uscita. E nelle connessioni sono necessari certificati client e certificati server.

I certificati server Bouncer e Odyssey leggono la loro pcache, ma non è necessario rileggere i certificati client dalla pcache, perché il nostro Odyssey scalabile alla fine si scontra con la prestazione di sistema nella lettura di questo certificato. È stata una sorpresa per noi, perché il problema non si è manifestato subito. Inizialmente, si è scalato linearmente, ma dopo 20.000 connessioni simultanee in entrata, questo problema si è presentato.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Il metodo di autenticazione pluggable è la possibilità di autenticarsi utilizzando strumenti integrati di Linux. In PgBouncer è implementato in modo tale che c'è un thread separato in attesa di risposta da PAM e c'è il thread principale di PgBouncer, che gestisce la connessione attuale e può chiedere loro di attendere nel thread PAM.

Non abbiamo deciso di implementarlo per un semplice motivo. Abbiamo molti thread. Perché ne abbiamo bisogno?

Di conseguenza, questo può creare problemi, poiché se hai l'autenticazione PAM e non PAM, un'ampia ondata di autenticazione PAM può ritardare sostanzialmente l'autenticazione non PAM. Questa è una delle cose che non abbiamo corretto. Ma se desideri sistemarlo, puoi occuparti di questo.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Un altro problema che abbiamo riscontrato è che abbiamo un flusso che accetta tutte le connessioni in ingresso. Successivamente, queste vengono trasferite a un pool di worker, dove avverrà il handshake TLS.

Di conseguenza, se hai un’onda coerente di 20.000 connessioni di rete, tutte saranno accettate. E dal lato client, libpq inizierà a conteggiare i timeout. Di default, sembra che ci sia impostato un valore di 3 secondi.

Se non possono accedere al database simultaneamente, non possono entrare nel database, perché tutto ciò potrebbe non essere coperto da un retry non esponenziale.

Siamo arrivati al punto di copiare qui lo schema di PgBouncer, considerando che abbiamo il throttling del numero di connessioni TCP che accettiamo.

Se vediamo che accettiamo connessioni, ma non riescono a completare il handshake in tempo, le mettiamo in coda in modo che non consumino risorse della CPU. Questo porta al fatto che il handshake simultaneo non può avvenire per tutte le connessioni che sono arrivate. Ma almeno qualcuno potrà accedere al database, anche se il carico è piuttosto elevato.

Roadmap

Cosa ci piacerebbe vedere in futuro in Odyssey? Cosa siamo pronti a sviluppare da soli e cosa ci aspettiamo dalla comunità?

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Ad agosto 2019.

Ecco come appariva il roadmap di Odyssey ad agosto:

  • Volevamo l'autenticazione SCRAM e PAM.
  • Volevamo inoltrare le query di lettura a standby.
  • Ci piacerebbe avere un riavvio online.
  • E la possibilità di fare pause sul server.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Metà di questo roadmap è stata realizzata, peraltro non da noi. Ed è una buona notizia. Quindi parliamo di ciò che resta e aggiungiamo altro.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Per quanto riguarda l'inoltro delle query di sola lettura a standby,? У нас есть реплики, которые без выполнения запросов будут просто греть воздух. Они нам необходимы для обеспечения failover и switchover. В случае проблем в одном из дата-центре хотелось бы их занять какой-то полезной работой. Потому что те же самые центральные процессоры, ту же самую память мы не можем сконфигурировать по-другому, потому что иначе не будет работать репликация.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

In effetti, in Postgres, a partire dalla versione 10, c'è la possibilità di specificare anche session_attrs nella connessione. Nella connessione puoi elencare tutti gli host del database e indicare cosa desideri fare nel database: scrivere o solo leggere. E il driver sceglierà automaticamente il primo host della lista che soddisfa i requisiti di session_attrs.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Ma il problema di questo approccio è che non controlla il ritardo della replica. Potresti avere una replica che è in ritardo rispetto al tuo servizio per un tempo inaccettabile. Per rendere possibile l'esecuzione completa delle query di lettura sulla replica, in sostanza, dobbiamo supportare in Odyssey la possibilità di non funzionare quando non è possibile leggere.

Odyssey deve controllare periodicamente il database per verificare la distanza di replica dal primary. Se questa distanza supera il limite stabilito, non consentire nuove richieste al database, informando il cliente che deve riavviare le connessioni e possibilmente scegliere un altro host per eseguire le richieste. Questo permetterà al database di ripristinare più rapidamente il ritardo di replica e tornare a rispondere alle richieste.

Difficile indicare un tempo di realizzazione, in quanto si tratta di un progetto open source. Speriamo che non ci vogliano 2,5 anni come per i colleghi di PgBouncer. Questa funzione sarebbe davvero utile in Odyssey.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Nella comunità, le persone hanno chiesto informazioni sul supporto per prepared statement.Ora puoi creare prepared statement in due modi. In primo luogo, puoi eseguire l'istruzione SQL denominata 'prepared'. Per comprendere questa istruzione SQL, dobbiamo imparare a gestire SQL dal lato di Bouncer. Questo sarebbe un eccesso, poiché avremmo bisogno di un parser completo. Non possiamo analizzare ogni istruzione SQL.

Tuttavia, esiste un prepared statement a livello del protocollo di messaggi su proto3. Ed è proprio qui che l'informazione riguardante la creazione del prepared statement viene inviata in forma strutturata. Potremmo così mantenere la comprensione che, su una connessione server, il cliente ha richiesto di creare prepared statements. Anche se la transazione è terminata, dobbiamo comunque mantenere la coerenza tra il server e il cliente.

Ma qui sorge un disaccordo nel dialogo, perché qualcuno afferma che è necessario comprendere quale specifico prepared statement ha creato il cliente e separare la connessione server tra tutti i clienti che hanno creato tale connessione server, cioè quelli che hanno generato quel prepared statement.

Andres Freund ha detto che se arriva un cliente che ha già creato tale prepared statement in un'altra connessione server, allora è opportuno crearlo per lui. Tuttavia, sembra un po' inappropriato eseguire richieste nel database al posto del cliente, ma dal punto di vista di uno sviluppatore che scrive un protocollo di interazione con il database, sarebbe comodo se gli venisse semplicemente fornita una connessione di rete in cui è presente quella query preparata.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

E un'altra funzione che dobbiamo implementare. Attualmente abbiamo un monitoraggio compatibile con PgBouncer. Possiamo restituire il tempo medio di esecuzione delle query. Ma il tempo medio è come la media della temperatura in ospedale: qualcuno è freddo, qualcun altro è caldo — in media tutti stanno bene. Questo non è vero.

Dobbiamo implementare il supporto per i percentili, che indicherebbero che ci sono query lente che consumano risorse, rendendo il monitoraggio più utile.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

La cosa più importante è che vogliamo la versione 1.0 (è già stata rilasciata la versione 1.1). Il problema è che attualmente Odyssey è in versione 1.0rc, ovvero release candidate. E tutti i problemi che ho elencato sono stati risolti esattamente con quella versione, tranne il memory leak.

Cosa significherebbe per noi la versione 1.0? Stiamo rilasciando Odyssey sulle nostre basi. Attualmente funziona già sulle nostre basi, ma quando raggiungerà il punto di 1.000.000 di richieste al secondo, potremo dire che è una versione di rilascio e che è una versione che può essere chiamata 1.0.

Nella comunità, diverse persone hanno richiesto che nella versione 1.0 ci siano anche la pausa e SCRAM. Ma questo significherebbe dover rilasciare già la prossima versione in produzione, poiché né SCRAM né la pausa sono stati ancora uniti. Tuttavia, probabilmente questo problema sarà risolto abbastanza rapidamente.

Roadmap di Odyssey: cosa desideriamo ancora dal connection pooler. Andrei Borodin (2019)

Aspetto i vostri pull request. Vorrei anche sapere quali problemi avete con Bouncer. Discutiamone. Potremmo implementare alcune funzioni di cui avete bisogno.

Con questo ho concluso la mia parte, ora vorrei ascoltarvi. Grazie!

Domande

Se imposto application_name, verrà passato correttamente, incluso nel transaction pooling in Odyssey?

In Odyssey o in Bouncer?

In Odyssey. Viene passato in Bouncer.

Faremo il set.

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

Faremo un set di tutti i parametri elencati. Non posso dire se application_name sia presente in questa lista. Mi sembra di averlo visto. Installeremo tutti gli stessi parametri. Con una sola richiesta, verrà impostato tutto ciò che era stato configurato dal cliente al momento dell'avvio.

Grazie, Andrea, per il rapporto! Un'ottima relazione! Sono felice che Odyssey stia evolvendo sempre più rapidamente ogni minuto. Spero che continui così. Ci siamo già rivolti a voi chiedendo di avere una connessione multi data-source, in modo che Odyssey possa connettersi simultaneamente a diversi database, cioè master-slave, e poi riconnettersi automaticamente a un nuovo master dopo un failover.

Sì, ricordo vagamente questa discussione. Attualmente ci sono diversi storage. Ma non c'è switch tra di essi. Dobbiamo interrogare il server dalla nostra parte per verificare che sia ancora attivo e capire se è avvenuto un failover, chi chiamerà pg_recovery. Ho un metodo standard per capire che non ci troviamo sul master. Dobbiamo avere un modo per capire dagli errori, o come? In altre parole, l'idea è interessante, è in discussione. Scrivi più commenti. Se hai persone che conoscono il C, sarebbe fantastico.

La questione della scalabilità delle repliche ci interessa anche, perché vogliamo rendere l'adozione dei cluster replicati il più semplice possibile per gli sviluppatori dell'applicazione. Ma qui vorremmo più commenti, cioè come implementare correttamente, come ottenere buoni risultati.

La domanda riguarda anche le repliche. Quindi, avete un master e diverse repliche. È chiaro che ci si connette meno frequentemente alle repliche rispetto al master, poiché potrebbero esserci differenze. Avete detto che le differenze nei dati potrebbero non soddisfare le vostre esigenze aziendali e non vi connetterete a esse finché non si saranno replicate completamente. Nel frattempo, se non vi collegate a lungo, e poi iniziate a farlo, i dati necessari non saranno immediatamente disponibili. Cioè, se ci colleghiamo costantemente al master, la cache sarà attiva, mentre la replica avrà una cache leggermente indietro.

Sì, è vero. Nella pcache non ci saranno i blocchi di dati che desiderate, nella cache reale non ci sarà informazione sulle tabelle che desiderate, nei piani non ci saranno query analizzate, non ci sarà veramente niente.

E quando avete un cluster e aggiungete una nuova replica, finché essa si avvia, è in uno stato critico, cioè sta accumulando la sua cache.

Ho compreso l'idea. L'approccio corretto sarebbe avviare inizialmente una piccola percentuale di richieste su una replica, per riscaldare la cache. In altre parole, abbiamo una condizione, che non dobbiamo essere indietro più di 10 secondi rispetto al master. E questa condizione deve essere attivata non in un'unica ondata, ma gradualmente per alcuni clienti.

Sì, aumentare il peso.

È una buona idea. Ma prima dobbiamo implementare questa disattivazione. Prima dobbiamo disattivarci, poi penseremo a come riattivarci. È una funzionalità ottima per accendersi gradualmente.

In nginx c'è un'opzione del genere iniziare lentamente nel cluster per il server. E lui aumenta gradualmente il carico.

Sì, ottima idea, proveremo quando arriveremo a questo.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster