{"id":96515,"date":"2020-10-12T19:43:02","date_gmt":"2020-10-12T17:43:02","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019"},"modified":"2020-10-12T19:43:02","modified_gmt":"2020-10-12T17:43:02","slug":"odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","title":{"rendered":"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6c445191705a4c96939cd094bc457a53.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nel rapporto, Andrei Borodin parler\u00e0 di come hanno tenuto conto dell'esperienza di scalabilit\u00e0 di PgBouncer durante la progettazione del connection pooler. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odyssey<\/a><\/noindex>, come \u00e8 stato introdotto in produzione. Inoltre, discuteremo quali funzioni del pooler ci piacerebbe vedere nelle nuove versioni: \u00e8 importante per noi non solo soddisfare le nostre esigenze, ma anche sviluppare la comunit\u00e0 degli utenti. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odissea<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Video:<\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"OUx40ABHFZY\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/OUx40ABHFZY\/hqdefault.jpg\" alt=\"Guarda il video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/dd2ea50b72e3d9c4e795aecbf9afdd25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ciao a tutti! Mi chiamo Andrei. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0a2f1880005bec1f61b72fb23b555adc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In Yandex mi occupo dello sviluppo di database open source. Oggi parleremo del connection pooler. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c18e7c937423d2514faa12e820e78e70.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se sai come si chiama il connection pooler in russo, fammelo sapere. Vorrei davvero trovare un buon termine tecnico che si affermi nella letteratura tecnica. <\/p>\n<p><\/p>\n<p>L'argomento \u00e8 piuttosto complesso, perch\u00e9 in molti database il connection pooler \u00e8 integrato e non \u00e8 nemmeno necessario saperlo. Ci sono sicuramente alcune impostazioni ovunque, ma in Postgres non funziona cos\u00ec. Parallelamente, a HighLoad++ 2019, si svolger\u00e0 una presentazione di Nikolay Samokhvalov sulla configurazione delle query in Postgres. E da quello che capisco, sono venute persone che hanno gi\u00e0 configurato le query in modo impeccabile, e queste persone affrontano problemi sistemici pi\u00f9 rari, legati alla rete e all'utilizzo delle risorse. E a volte pu\u00f2 essere piuttosto complicato nel senso che i problemi non sono evidenti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/89c660dd530575e2938e6bf312b83e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In Yandex abbiamo Postgres. In Yandex.Cloud vivono molti servizi di Yandex. E abbiamo diversi petabyte di dati che generano non meno di un milione di richieste al secondo in Postgres. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/288bfa37b9dcd60acd22ba48f0ef8a39.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E forniamo un cluster piuttosto standard a tutti i servizi: \u00e8 il nodo primario principale, due repliche normali (una sincrona e una asincrona), backup e scaling delle query di lettura sulla replica. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c249ca55bb387e25a5560324024cc523.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ogni nodo del cluster \u00e8 un Postgres, su cui oltre a Postgres e ai sistemi di monitoraggio \u00e8 installato anche il connection pooler. Il connection pooler \u00e8 utilizzato per il fencing e per il suo scopo principale. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0e29be55cc048007db21c80bbb08a9d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Qual \u00e8 lo scopo principale del connection pooler? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e2fbbd440c2781573cb35deeef358f20.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In Postgres si adotta un modello basato su processi quando si lavora con il database. Questo significa che una connessione \u00e8 un processo, un backend di Postgres. E in questo backend ci sono molti cache diversi, che \u00e8 piuttosto costoso avere diversi per diverse connessioni. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/587498063b1af8fac4a845961c654bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inoltre, nel codice Postgres c'\u00e8 un array chiamato procArray. Contiene le informazioni principali sulle connessioni di rete. E quasi tutti gli algoritmi che elaborano il procArray hanno una complessit\u00e0 lineare, poich\u00e9 attraversano tutto l'array delle connessioni di rete. Questo \u00e8 un ciclo abbastanza veloce, ma con un numero elevato di connessioni in entrata tutto diventa un po' pi\u00f9 costoso. Quando tutto diventa un po' pi\u00f9 costoso, alla fine si pu\u00f2 pagare un prezzo molto alto per un gran numero di connessioni di rete. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b534a38d0bfae7a65fc4258155a50280.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esistono 3 approcci possibili:<\/p>\n<p><\/p>\n<ul>\n<li>Dalla parte dell'applicazione. <\/li>\n<li>Dalla parte del database. <\/li>\n<li>E in mezzo, cio\u00e8 tutte le possibili combinazioni. <\/li>\n<\/ul>\n<p><\/p>\n<p>Sfortunatamente, il pooler integrato \u00e8 attualmente in fase di sviluppo. Gli amici della PostgreSQL Professional stanno principalmente lavorando su questo. Quando sar\u00e0 disponibile, \u00e8 difficile prevederlo. In effetti, l'architetto ha due soluzioni tra cui scegliere. Questo \u00e8 un pool a livello di applicazione e un proxy pool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/702527a09e9fc86dd39b7fd69dcf1fc9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il pool a livello di applicazione \u00e8 il modo pi\u00f9 semplice. E quasi tutti i driver client vi offrono un modo per rappresentare milioni delle vostre connessioni nel codice come alcune dozzine di connessioni al database. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7b66b9e20d22f472ca5ac39f6b9e0ba4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sorge un problema quando a un certo punto volete scalare il backend, volete distribuirlo su molte macchine virtuali. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f216fd7a8c01c2b07891e2242c48b06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poi vi rendete conto che avete anche diverse zone di disponibilit\u00e0, diversi data center. E l'approccio con il client side pooling porta a numeri elevati. Elevati sono circa 10.000 connessioni. Questo \u00e8 il limite che pu\u00f2 funzionare normalmente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5bc5f284fd8ff568bbe16c3895b7ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Parlando dei proxy poolers, ci sono due poolers che sanno fare molte cose. Non sono solo poolers. Sono poolers + un'ottima funzionalit\u00e0. Questo \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.pgpool.net\/\">Pgpool<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/crunchy-proxy\">Crunchy-Proxy<\/a><\/noindex>. <\/p>\n<p><\/p>\n<p>Ma sfortunatamente, questa funzionalit\u00e0 aggiuntiva non \u00e8 necessaria per tutti. E porta al fatto che i poolers supportano solo il pooling di sessione, cio\u00e8 un client in entrata, un client in uscita nel database. <\/p>\n<p><\/p>\n<p>Per le nostre esigenze, questo non \u00e8 molto adatto, quindi utilizziamo PgBouncer, che implementa il transaction pooling, cio\u00e8 le connessioni del server sono associate alle connessioni dei client solo durante la transazione. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5fedbe14656d2ac2cde8d1878a950e2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E sulla nostra carico \u2013 \u00e8 vero. <strong>Ma ci sono alcuni problemi<\/strong>.<img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/61fd36cadcd9948d624dafa711777307.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I problemi iniziano quando volete diagnosticare una sessione, perch\u00e9 tutte le connessioni in entrata sono locali. Tutte provengono dal loopback e quindi \u00e8 difficile tracciare la sessione. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/36108c4956c410a1b1f286a88bc393d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Certo, puoi utilizzare application_name_add_host. Questo \u00e8 un modo per Bouncer di aggiungere un indirizzo IP a application_name. Ma application_name \u00e8 impostato tramite una connessione aggiuntiva. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b4cec483aa776f48db7ad3966c3b78e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In questo grafico, dove la linea gialla rappresenta le richieste reali e la linea blu rappresenta le richieste che arrivano al database. E questa differenza \u00e8 precisamente l'impostazione di application_name, che \u00e8 necessaria solo per il tracciamento, ma non \u00e8 affatto gratuita. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c02ea73a6f1a2a4cd6af6c621f321ab4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inoltre, in Bouncer non \u00e8 possibile limitare un pool, ovvero il numero di connessioni al database per un determinato utente su un determinato database. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3431a463e04106066e2799aead66f571.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A cosa porta questo? Hai un servizio pesantemente carico, scritto in C++, e accanto a esso un piccolo servizio in Node che non fa nulla di terribile con il database, ma il suo driver impazzisce. Apre 20.000 connessioni e tutto il resto aspetta. Anche il tuo codice \u00e8 a posto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d7fa321714dc017b017945dffcf79bc6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Naturalmente, abbiamo scritto una piccola patch per Bouncer che ha aggiunto questa impostazione, cio\u00e8 la limitazione dei clienti sul pool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d58884fc5ac0f90ff8442f126972157a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Si potrebbe fare questo lato Postgres, cio\u00e8 limitare i ruoli nel database con un numero massimo di connessioni.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d6ff70db72964ed4eae5eaa47309931.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ma in tal caso perdi la possibilit\u00e0 di capire perch\u00e9 non hai connessioni con il server. PgBouncer non inoltra l'errore di connessione, restituisce sempre la stessa informazione. E non puoi capire: forse la tua password \u00e8 cambiata, forse semplicemente il database \u00e8 andato gi\u00f9, forse c'\u00e8 qualcosa che non va. Ma non ci sono diagnosi. Se la sessione non pu\u00f2 essere stabilita, non scopri perch\u00e9 non sia possibile farlo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cb3048344a94f2953bf403485d28e69f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A un certo punto guardi i grafici dell'applicazione e vedi che l'app non funziona.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e67c6680bb9a7f41242af9f9e4920916.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Guardi nel top e vedi che Bouncer \u00e8 a thread singolo. Questo \u00e8 un punto di svolta nella vita del servizio. Realizzi che ti stavi preparando a scalare il database tra un anno e mezzo, mentre devi scalare il pooler. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4c140c4ba6db19cb9939c1148638fb73.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Siamo arrivati alla conclusione che abbiamo bisogno di pi\u00f9 PgBouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d369f572a66c16a8917e13393324a644.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/542629\/\">https:\/\/lwn.net\/Articles\/542629\/<\/a><\/noindex><\/p>\n<p><\/p>\n<p>Abbiamo fatto qualche piccolo patch su Bouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/97755489a25ebfe38efd56ff897bd8fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E abbiamo fatto in modo che possano essere avviati pi\u00f9 Bouncer riutilizzando la porta TCP. E il sistema operativo smista automaticamente le connessioni TCP in entrata tra di loro con round-robin.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/ac30d3f067de2a8cd66ad2325c3a3b58.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questo \u00e8 trasparente per i clienti, cio\u00e8 tutto appare come se avessi un solo Bouncer, ma hai una frammentazione delle connessioni idle tra i Bouncer in esecuzione. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/53825f075db00b026c12013a610be456.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E a un certo punto potresti notare che questi 3 Bouncers consumano ciascuno il proprio core al 100%. Hai bisogno di un numero consistente di Bouncers. Perch\u00e9? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/66c17883a043e157cd7ceab2c2a4e326.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Perch\u00e9 hai TLS. Hai una connessione crittografata. E se esegui un benchmark di Postgres con TLS e senza TLS, scoprirai che il numero di connessioni stabilite diminuisce quasi di due ordini di grandezza con l'attivazione della crittografia, poich\u00e9 il handshake TLS consuma risorse della CPU. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6101121ebe136af16e5eb1a484c65d66.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E nella parte superiore puoi vedere molte funzioni crittografiche che vengono eseguite durante l'ondata di connessioni in arrivo. Poich\u00e9 il nostro primary pu\u00f2 passare tra le zone di disponibilit\u00e0, l'ondata di connessioni in arrivo \u00e8 una situazione piuttosto tipica. Cio\u00e8, per qualche motivo il vecchio primary \u00e8 stato non disponibile, e tutto il carico \u00e8 stato inviato in un altro data center. Arriveranno tutti contemporaneamente a salutare con TLS. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c238ac2f511568590dc275e01c192c00.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E un grande numero di handshake TLS potrebbe non salutare gi\u00e0 con Bouncer, ma strangolarlo. A causa del timeout, l'ondata di connessioni in arrivo potrebbe diventare non attenuabile. Se hai retry nel database senza exponential backoff, non arriveranno nuovamente e nuovamente come un'ondata coerente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f42d0b210174d4d172254603ae6b834a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ecco un esempio di 16 PgBouncer che caricano 16 core al 100%.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d048d3774c09e5b6a3fb3c7bff62084.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Siamo arrivati al PgBouncer a cascata. Questa \u00e8 la configurazione migliore che possiamo ottenere con il nostro carico con Bouncer. I Bouncers esterni servono per il TCP handshake, mentre i Bouncers interni servono per il vero pooling, per non frammentare eccessivamente le connessioni esterne.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3a4ee4ea46d5fe8479a5a7222ee134da.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In questa configurazione \u00e8 possibile un riavvio graduale. \u00c8 possibile riavviare tutti questi 18 Bouncers uno alla volta. Ma mantenere tale configurazione \u00e8 piuttosto complicato. Gli amministratori di sistema, DevOps e le persone che sono veramente responsabili di questo server non saranno molto felici di questo schema. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/5291fe67dbe02036f3ff8e98bdd84d1b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Potrebbe sembrare che possiamo promuovere tutte le nostre modifiche come open source, ma Bouncer non \u00e8 molto ben supportato. Per esempio, la possibilit\u00e0 di avviare pi\u00f9 PgBouncer sulla stessa porta \u00e8 stata impegnata un mese fa. E la pull request con questa funzione \u00e8 stata presentata qualche anno fa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/2059d7f49649d136249103db4aa3ec19.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/libpq-cancel.html\">https:\/\/www.postgresql.org\/docs\/current\/libpq-cancel.html<\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pgbouncer\/pgbouncer\/pull\/79\">https:\/\/github.com\/pgbouncer\/pgbouncer\/pull\/79<\/a><\/noindex><\/p>\n<p><\/p>\n<p>Oppure un altro esempio. In Postgres puoi annullare una query in esecuzione inviando un segreto su un altro collegamento senza necessit\u00e0 di autenticazione aggiuntiva. Ma alcuni client inviano semplicemente un TCP-reset, cio\u00e8 interrompono la connessione di rete. Cosa far\u00e0 quindi Bouncer? Non far\u00e0 nulla. Continuerebbe ad eseguire la query. Se hai ricevuto un numero enorme di connessioni che hanno sovraccaricato il database con piccole query, semplicemente scollegare Bouncer non sar\u00e0 sufficiente; dovrai anche terminare quelle query attive nel database. <\/p>\n<p><\/p>\n<p>Questo \u00e8 stato corretto e il problema non \u00e8 ancora stato integrato nell'upstream di Bouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a9695b6d9e640a5543dc73429eb0050b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E cos\u00ec siamo arrivati al punto in cui abbiamo bisogno del nostro connection pooler, che si svilupper\u00e0, verr\u00e0 patchato, e nel quale sar\u00e0 possibile risolvere rapidamente i problemi, e che, ovviamente, deve essere multithreaded. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e755cd9b06a004f0eced1dc12fd3a6fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Abbiamo impostato il multithreading come obiettivo principale. Dobbiamo gestire bene l'ondata di connessioni TLS in arrivo. <\/p>\n<p><\/p>\n<p>Per questo abbiamo dovuto sviluppare una libreria separata, chiamata Machinarium, progettata per descrivere gli stati delle macchine di una connessione di rete come codice sequenziale. Se guardi il codice sorgente di libpq, vedrai chiamate piuttosto complesse che possono restituire un risultato e dire: \u00abChiamami pi\u00f9 tardi. Attualmente ho IO, ma, quando l'IO sar\u00e0 completato, ho un carico per il processore\u00bb. E questo \u00e8 uno schema a pi\u00f9 livelli. L'interazione di rete \u00e8 solitamente descritta come una macchina a stati. Molte regole del tipo \"Se ho ricevuto in precedenza un intestazione di pacchetto di dimensione N, ora attendo N byte\", \"Se ho inviato un pacchetto SYNC, ora attendo un pacchetto con i metadati del risultato\". Risulta un codice piuttosto difficile e controintuitivo, come se un labirinto venisse trasformato in un disegno lineare. Abbiamo fatto in modo che invece di una macchina a stati, il programmatore descriva il percorso principale di interazione come codice imperativo normale. Solo in questo codice imperativo \u00e8 necessario inserire i punti in cui la sequenza di esecuzione deve essere interrotta in attesa di dati dalla rete, passando il contesto di esecuzione a un'altra coroutine (green thread). Questo approccio \u00e8 simile a quello di registrare il percorso pi\u00f9 atteso nel labirinto e poi aggiungere diramazioni a esso. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a6bfb4b11961c7db3a7c7184674e3bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Di conseguenza, abbiamo un singolo thread che esegue TCP accept e distribuisce le connessioni TCP a pi\u00f9 worker in round-robin. <\/p>\n<p><\/p>\n<p>Inoltre, ogni connessione client funziona sempre su un solo processore. Questo lo rende cache-friendly. <\/p>\n<p><\/p>\n<p>Inoltre, abbiamo migliorato un po' la raccolta di piccoli pacchetti in un grande pacchetto per alleggerire lo stack TCP di sistema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7d740c23baecdd2f993c83cd54a0a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In aggiunta, abbiamo migliorato il pooling transazionale in modo che Odyssey, con la configurazione corretta, possa inviare CANCEL e ROLLBACK in caso di interruzione della connessione di rete, cio\u00e8, se non c'\u00e8 nessuno che attende la richiesta, Odyssey dir\u00e0 al database di non sforzarsi di eseguire quella richiesta che potrebbe consumare risorse preziose.<\/p>\n<p><\/p>\n<p>E, se possibile, manteniamo le connessioni con lo stesso client. Questo evita la reinstallazione di application_name_add_host. Se possibile, non abbiamo reinstallazioni aggiuntive dei parametri necessari per la diagnosi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/afb2fb7fb16d65c9ea73a8978d1eb83c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lavoriamo nell'interesse di Yandex.Cloud. E se state utilizzando PostgreSQL gestito e avete impostato un connection pooler, potete creare una replica logica verso l'esterno, cio\u00e8 allontanarvi da noi, se lo desiderate, tramite replica logica. Bouncer non restituir\u00e0 verso l'esterno il flusso di replica logica. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c53defc92ebd8f3bec57ce64d97b9f72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questo \u00e8 un esempio di configurazione della replica logica. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a37d9d1abf288d17fa646b642e8b62ab.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inoltre, abbiamo il supporto per la replica fisica verso l'esterno. In Cloud, ovviamente, non \u00e8 possibile, poich\u00e9 allora il cluster vi fornirebbe troppe informazioni su di s\u00e9. Ma nelle vostre installazioni, se avete bisogno di replica fisica tramite connection pooler in Odyssey, \u00e8 possibile. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/572934ce5b08115e57ab4b55d2153c6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In Odyssey, ci sono monitoraggi completamente compatibili con PgBouncer. Abbiamo la stessa console che esegue quasi tutti gli stessi comandi. Se manca qualcosa, inviateci una pull request, o almeno un problema su GitHub, e ci occuperemo di implementare i comandi necessari. Ma la funzionalit\u00e0 principale della console PgBouncer \u00e8 gi\u00e0 presente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/451dd798fb3523a7a174ebfe00a14bc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E, naturalmente, abbiamo il forwarding degli errori. Restituiremo l'errore segnalato dal database. Riceverete informazioni sul motivo per cui non riuscite a entrare nel database e non solo che non ci riuscite. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/14b4cb0efa33a2658dfc528349a5382f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questa funzionalit\u00e0 pu\u00f2 essere disattivata nel caso in cui abbiate bisogno di una compatibilit\u00e0 100% con PgBouncer. Possiamo comportarci come Bouncer, giusto per sicurezza. <\/p>\n<p><\/p>\n<p><strong>Sviluppo<\/strong><\/p>\n<p><\/p>\n<p>Qualche parola sul codice sorgente di Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6055d5ec9676c331a83592916a6a292f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/pull\/66\">https:\/\/github.com\/yandex\/odyssey\/pull\/66<\/a><\/noindex><\/p>\n<p><\/p>\n<p>Ad esempio, ci sono i comandi \u00abPause \/ Resume\u00bb. Di solito vengono utilizzati per aggiornare il database. Se hai bisogno di aggiornare Postgres, puoi metterlo in pausa nel connection pooler, eseguire pg_upgrade e poi riprendere. E dal punto di vista del client sembrer\u00e0 che il database si stesse semplicemente bloccando. Questa funzionalit\u00e0 ci \u00e8 stata portata da persone della comunit\u00e0. Non \u00e8 ancora stata fusa, ma presto tutto sar\u00e0. (Gi\u00e0 fusa)<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d2f7c57e0ae3e466ec2a701bbdb8eb3f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/pull\/73\">https:\/\/github.com\/yandex\/odyssey\/pull\/73<\/a><\/noindex> \u2014 gi\u00e0 fusa<\/p>\n<p><\/p>\n<p>Inoltre, una delle nuove funzionalit\u00e0 in PgBouncer \u00e8 il supporto per SCRAM Authentication, che ci \u00e8 stata portata da una persona che non lavora in Yandex.Cloud. Entrambi sono funzionalit\u00e0 complesse e importanti. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f39346a543c88d17728233d05c2dff19.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Perci\u00f2, voglio raccontarvi come \u00e8 fatto Odyssey, magari anche voi volete scrivere un po' di codice. <\/p>\n<p><\/p>\n<p>Hai il codice sorgente di Odyssey, che si basa su due librerie principali. La libreria Kiwi \u00e8 l'implementazione del protocollo di messaggi di Postgres. Cio\u00e8, il proto nativo 3 di Postgres sono i messaggi standard con cui i frontend e i backend possono scambiarsi informazioni. Sono implementati nella libreria Kiwi.<\/p>\n<p><\/p>\n<p>La libreria Machinarium \u00e8 una libreria per l'implementazione dei flussi. Un piccolo frammento di questo Machinarium \u00e8 scritto in assembler. Ma, non spaventarti, sono solo 15 righe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd18f250af50eabd53536b2c0d7f12b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>L'architettura di Odyssey. C'\u00e8 una macchina principale in cui sono eseguite le coroutines. In questa macchina viene implementato l'accettare connessioni TCP in ingresso e distribuirle tra i workers. <\/p>\n<p><\/p>\n<p>All'interno di un worker pu\u00f2 lavorare un elaboratore di diversi client. Inoltre, nel thread principale girano la console e l'elaborazione delle crone-task per rimuovere le connessioni che non sono pi\u00f9 necessarie nel pool.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7072fb20f406f2ee5788542860ccdf50.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Per testare Odyssey viene utilizzato un set standard di test di Postgres. Semplicemente eseguiamo install-check tramite Bouncer e tramite Odyssey, otteniamo un div nullo. Ci sono diversi test relativi al formato delle date che non passano affatto allo stesso modo in Bouncer e in Odyssey.<\/p>\n<p><\/p>\n<p>Inoltre, ci sono molti driver che hanno i propri test. E utilizziamo i loro test per testare Odyssey.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/fb01cc9a0e9724ddcd3cc3d088afb182.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inoltre, a causa della nostra configurazione cascata, dobbiamo testare diverse combinazioni: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey, per essere certi che, se Odyssey si trova in una delle parti della cascata, continui a funzionare come ci aspettiamo. <\/p>\n<p><\/p>\n<p><strong>Grattacapo<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/25855b691180bca083025b9e8b611c09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Utilizziamo Odyssey in produzione. E non sarebbe giusto se dicessi che tutto funziona semplicemente. No, cio\u00e8, s\u00ec, ma non sempre. Ad esempio, in produzione tutto funzionava perfettamente, poi sono arrivati i nostri amici di PostgreSQL Professional e ci hanno detto che avevamo una memory leak. Loro avevano ragione, l'abbiamo corretta. Ma \u00e8 stato davvero un colpo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e638d88397b32b1ca0b74c9c1b905f81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poi abbiamo scoperto che nel connection pooler ci sono connessioni TLS in ingresso e connessioni TLS in uscita. E per le connessioni sono necessari certificati client e certificati server.<\/p>\n<p><\/p>\n<p>I certificati server di Bouncer e Odyssey leggono il loro pcache, ma non \u00e8 necessario rileggere i certificati client dal pcache, perch\u00e9 il nostro Odyssey scalabile finisce per urtare le prestazioni di sistema nella lettura di quel certificato. Questo \u00e8 stato per noi una sorpresa, perch\u00e9 si \u00e8 manifestato ben dopo. All'inizio si era scalato linearmente, ma dopo 20.000 connessioni simultanee in ingresso, il problema si \u00e8 presentato.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6cff094cd59a990e448b82fa0b1572b7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il Pluggable Authentication Method \u00e8 la possibilit\u00e0 di autenticarsi con i mezzi integrati di Linux. In PgBouncer \u00e8 realizzato in modo tale che esiste un thread separato in attesa di una risposta da PAM e un thread principale di PgBouncer che gestisce la connessione attuale e pu\u00f2 chiedere loro di rimanere nel thread PAM. <\/p>\n<p><\/p>\n<p>Non abbiamo deciso di implementare questo per una semplice ragione. Abbiamo molti thread. A cosa ci serve?<\/p>\n<p><\/p>\n<p>In effetti, questo pu\u00f2 creare problemi, poich\u00e9 se hai autenticazione PAM e autenticazione non PAM, una grande ondata di autenticazione PAM pu\u00f2 ritardare significativamente l'autenticazione non PAM. Questa \u00e8 una delle cose che non abbiamo risolto. Ma se vuoi sistemarlo, puoi occuparti di questo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c7bd9e9980ff7298b30a59c130f03dbb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro problema era che avevamo un thread che accettava tutte le connessioni in ingresso. E poi le trasmetteva al worker pool, dove si svolger\u00e0 il TLS handshake.<\/p>\n<p><\/p>\n<p>Di conseguenza, se hai un'ondata coerente di 20.000 connessioni di rete, verranno tutte accettate. E sul lato client, libpq inizier\u00e0 a contare i timeout. Di default sembra che ci sia un'impostazione di 3 secondi. <\/p>\n<p><\/p>\n<p>Se non possono tutte accedere contemporaneamente al database, non possono entrare nel database, perch\u00e9 tutto ci\u00f2 potrebbe essere coperto da un retry non esponenziale. <\/p>\n<p><\/p>\n<p>Siamo giunti al punto di copiare qui lo schema di PgBouncer, in cui abbiamo il throttling del numero di connessioni TCP a cui facciamo accept. <\/p>\n<p><\/p>\n<p>Se vediamo che accettiamo le connessioni, ma alla fine non riescono a completare il handshake, le mettiamo in coda per evitare che consumino risorse della CPU. Questo porta al fatto che il handshake simultaneo potrebbe non avvenire per tutte le connessioni ricevute. Ma almeno qualcuno entrer\u00e0 nel database, anche se il carico \u00e8 abbastanza elevato.<\/p>\n<p><\/p>\n<p><strong>Roadmap<\/strong><\/p>\n<p><\/p>\n<p>Cosa ci piacerebbe vedere in futuro in Odyssey? Cosa siamo pronti a sviluppare noi stessi e cosa ci aspettiamo dalla comunit\u00e0?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4719437d80b33efc3da6572af9a4dedb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>A agosto 2019.<\/strong><\/p>\n<p><\/p>\n<p>Ecco come si presentava la roadmap di Odyssey ad agosto:<\/p>\n<p><\/p>\n<ul>\n<li>Volevamo l'autenticazione SCRAM e PAM.<\/li>\n<li>Volevamo l'inoltro delle query di lettura verso il standby. <\/li>\n<li>Ci piacerebbe un riavvio online. <\/li>\n<li>E la possibilit\u00e0 di mettere in pausa un server. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/455c92f92df826257c2c57dc2b034e22.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Met\u00e0 di questa roadmap \u00e8 stata completata, e non da noi. Ed \u00e8 positivo. Pertanto, discutiamo di ci\u00f2 che resta e aggiungiamo altro. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4a1daafbfe8d65ba0dd3e1ebdae8dd94.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/issues\/12\">Per quanto riguarda l'inoltro delle query in sola lettura al standby<\/a><\/noindex>? \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0440\u0435\u043f\u043b\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0435\u0437 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0440\u0435\u0442\u044c \u0432\u043e\u0437\u0434\u0443\u0445. \u041e\u043d\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f failover \u0438 switchover. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0434\u0430\u0442\u0430-\u0446\u0435\u043d\u0442\u0440\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u0445 \u0437\u0430\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0439. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0435 \u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u044b, \u0442\u0443 \u0436\u0435 \u0441\u0430\u043c\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u0430\u0447\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0873cffd4f1ae15d9ffa6d080671051b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Fondamentalmente, in Postgres, a partire dalla versione 10 c'\u00e8 la possibilit\u00e0 di specificare anche session_attrs durante la connessione. Nella connessione puoi elencare tutti gli host del database e dire perch\u00e9 ti connetti al database: per scrivere o solo per leggere. E il driver sceglier\u00e0 automaticamente il primo host della lista che preferisce, che soddisfa i requisiti di session_attrs. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0693d1327fe5826502a01c21d05d5b4c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ma il problema di questo approccio \u00e8 che non controlla il ritardo di replica. Potresti avere una replica che \u00e8 in ritardo di un tempo inaccettabile per il tuo servizio. Per garantire l'esecuzione funzionale delle query di lettura sulla replica, in sostanza, \u00e8 necessario garantire in Odyssey la possibilit\u00e0 di non lavorare quando la lettura non \u00e8 possibile. <\/p>\n<p><\/p>\n<p>Odyssey dovrebbe occasionalmente interrogare il database per verificare la distanza di replica dal primary. E se questa distanza ha raggiunto un valore limite, non consentire nuove query al database, informare il cliente che deve riavviare le connessioni e, possibilmente, scegliere un altro host per eseguire le query. Questo permetter\u00e0 al database di ripristinare pi\u00f9 rapidamente il ritardo di replica e tornare a rispondere alle query. <\/p>\n<p><\/p>\n<p>\u00c8 difficile fornire una tempistica di implementazione, poich\u00e9 si tratta di open source. Ma spero che non saranno 2,5 anni come per i colleghi di PgBouncer. Vorremmo vedere questa funzionalit\u00e0 in Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4ec3cd2ff7b2298927cccfe8e0ba890a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/issues\/16\">Nella comunit\u00e0, le persone chiedevano riguardo al supporto per le dichiarazioni preparate.<\/a><\/noindex>. Ora puoi creare una prepared statement in due modi. Innanzitutto, puoi eseguire il comando SQL, ovvero \"prepared\". Per capire questo comando SQL, dobbiamo imparare a comprendere SQL dal lato di Bouncer. Sarebbe un eccesso, perch\u00e9 abbiamo bisogno di un parser completo. Non possiamo analizzare ogni comando SQL. <\/p>\n<p><\/p>\n<p>Ma esiste una prepared statement a livello del protocollo di messaggistica su proto3. Ed \u00e8 in questo momento che l'informazione riguardante la creazione della prepared statement viene ricevuta in formato strutturato. E potremmo supportare la comprensione di ci\u00f2 che, su qualche connessione server, il client ha richiesto per creare prepared statements. E anche se la transazione si \u00e8 chiusa, dobbiamo comunque mantenere la coerenza tra server e client. <\/p>\n<p><\/p>\n<p>Ma qui sorge una discrepanza nel dialogo, perch\u00e9 qualcuno parla di dover comprendere quale specifica prepared statement ha creato il client e dividere la connessione server tra tutti i client che hanno creato quella connessione server, cio\u00e8 che hanno creato quella prepared statement. <\/p>\n<p><\/p>\n<p>Andres Freund ha detto che se ti arriva un client che ha gi\u00e0 creato una preparata statement in un'altra connessione server, creala per lui. Ma, sembra, sia un po' sbagliato eseguire le query sul database al posto del client, ma dal punto di vista dello sviluppatore che scrive il protocollo di interazione con il database, sarebbe comodo se gli venisse semplicemente fornita una connessione di rete che ha una tale query preparata. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd56b3ad015195d86a64e52be365b16a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E un'altra funzionalit\u00e0 che dobbiamo implementare. Attualmente abbiamo un monitoraggio compatibile con PgBouncer. Possiamo restituire il tempo medio di esecuzione della query. Ma il tempo medio \u00e8 come la temperatura media in ospedale: qualcuno \u00e8 freddo, qualcun altro \u00e8 caldo \u2013 mediamente tutti sono sani. Non \u00e8 vero. <\/p>\n<p><\/p>\n<p>Dobbiamo implementare il supporto per i percentili, che indicano che ci sono query lente che consumano risorse, rendendo il monitoraggio pi\u00f9 accettabile. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6f285f3eb0d79e7f25d42f0e792b85b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Infine, desidero la versione 1.0 (\u00e8 gi\u00e0 uscita la versione 1.1). Il punto \u00e8 che ora Odyssey si trova nella versione 1.0rc, cio\u00e8 release candidate. E tutte le problematiche che ho elencato sono state risolte proprio con quella versione, eccetto il memory leak. <\/p>\n<p><\/p>\n<p>Cosa significher\u00e0 per noi la versione 1.0? Stiamo lanciando Odyssey sui nostri database. Funziona gi\u00e0 sui nostri database, ma quando raggiunger\u00e0 il milione di richieste al secondo, potremo dire che questa \u00e8 la versione stabile e che pu\u00f2 essere chiamata 1.0. <\/p>\n<p><\/p>\n<p>Nel nostro gruppo, alcune persone hanno chiesto che nella versione 1.0 siano inclusi anche il pause e lo SCRAM. Ma ci\u00f2 significherebbe che dovremmo rilasciare la prossima versione in produzione, perch\u00e9 n\u00e9 SCRAM n\u00e9 la pausa sono ancora stati fusi. Tuttavia, probabilmente questa questione sar\u00e0 risolta abbastanza rapidamente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Roadmap di Odyssey: cosa vogliamo ancora dal connettore di pooling. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/2f50de9f51f653a7396965239bd545e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aspetto le vostre pull request. Vorrei anche sapere quali problemi avete riscontrato con Bouncer. Discutiamone. Forse possiamo implementare alcune funzionalit\u00e0 di cui avete bisogno. <\/p>\n<p><\/p>\n<p>Con questo la mia parte \u00e8 finita, vorrei ascoltarvi. Grazie!<\/p>\n<p><\/p>\n<p>Domande<\/p>\n<p><\/p>\n<p><em>Se imposto il mio application_name, verr\u00e0 correttamente propagato, anche nel transaction pooling in Odyssey?<\/em><\/p>\n<p><\/p>\n<p>In Odyssey o in Bouncer?<\/p>\n<p><\/p>\n<p><em>In Odyssey. In Bouncer viene propagato.<\/em> <\/p>\n<p><\/p>\n<p>Faremo il set. <\/p>\n<p><\/p>\n<p><em>E se la mia connessione reale salta su altre connessioni, verr\u00e0 trasferita?<\/em><\/p>\n<p><\/p>\n<p>Faremo il set di tutti i parametri elencati nella lista. Non posso dire se in questa lista ci sia application_name. Mi sembra di averlo visto. Imposteremo gli stessi parametri. Con una richiesta, il set far\u00e0 tutto ci\u00f2 che \u00e8 stato impostato dal client all'avvio. <\/p>\n<p><\/p>\n<p><em>Grazie, Andrej, per la presentazione! \u00c8 stata una buona presentazione! Sono felice che Odyssey stia evolvendo sempre pi\u00f9 rapidamente. Spero che continui cos\u00ec. Abbiamo gi\u00e0 contattato voi con la richiesta di avere una connessione multi data-source, affinch\u00e9 Odyssey possa connettersi contemporaneamente a diversi database, cio\u00e8 master-slave, e poi automaticamente, dopo un failover, connettersi al nuovo master.<\/em> <\/p>\n<p><\/p>\n<p>S\u00ec, mi sembra di ricordare questa discussione. Attualmente ci sono diversi storage. Ma non ci sono passaggi tra di loro. Dobbiamo interrogare il server per verificare se \u00e8 ancora attivo e capire che \u00e8 avvenuto un failover, chi chiamer\u00e0 pg_recovery. Ho un modo standard per capire che non siamo arrivati al master. E dobbiamo capire in qualche modo dagli errori o come? Cio\u00e8, l'idea \u00e8 interessante, se ne sta discutendo. Scrivete pi\u00f9 commenti. Se avete mani esperte che conoscono C, sarebbe davvero fantastico. <\/p>\n<p><\/p>\n<p>La questione della scalabilit\u00e0 delle repliche ci interessa anche, perch\u00e9 vogliamo rendere l'adozione dei cluster replicati il pi\u00f9 semplice possibile per gli sviluppatori dell'applicazione. Ma qui ci piacerebbe avere pi\u00f9 commenti, cio\u00e8 come farlo e come farlo bene. <\/p>\n<p><\/p>\n<p><em>La domanda riguarda anche le repliche. Risulta che avete un master e diverse repliche. \u00c8 chiaro che le chiamate alla replica avvengono meno frequentemente rispetto al master, poich\u00e9 potrebbero esserci delle differenze. Avete detto che le differenze nei dati potrebbero essere tali da non soddisfare il vostro business e non le consulterete finch\u00e9 non saranno replicate. Inoltre, se non vi accedete per un lungo periodo e poi iniziate a farlo, i dati necessari non saranno immediatamente disponibili. Cio\u00e8, se accediamo continuamente al master, la cache \u00e8 calda, mentre nella replica la cache \u00e8 un po' indietro.<\/em> <\/p>\n<p><\/p>\n<p>S\u00ec, \u00e8 vero. Nel pcache non ci saranno i blocchi di dati che desiderate, nel real cache non ci sar\u00e0 informazione sulle tabelle che volete, nei piani non ci saranno le query parsate, insomma non ci sar\u00e0 nulla. <\/p>\n<p><\/p>\n<p><em>E quando avete un cluster e aggiungete una nuova replica, finch\u00e9 si avvia, la situazione non \u00e8 buona, cio\u00e8 sta accumulando la sua cache.<\/em> <\/p>\n<p><\/p>\n<p>Ho capito l'idea. L'approccio corretto sarebbe iniziare a inviare una piccola percentuale delle query inizialmente alla replica, per scaldare la cache. In breve, abbiamo la condizione che non dobbiamo essere indietro di oltre 10 secondi rispetto al master. E questa condizione deve essere attivata non in un colpo solo, ma gradualmente per alcuni clienti. <\/p>\n<p><\/p>\n<p><em>S\u00ec, aumentare il peso.<\/em><\/p>\n<p><\/p>\n<p>\u00c8 una buona idea. Ma prima dobbiamo implementare questo disattivazione. Dobbiamo prima disattivarci e poi penseremo a come riattivarci. \u00c8 una grande caratteristica per attivarsi gradualmente.<\/p>\n<p><\/p>\n<p><em>In nginx c'\u00e8 questa opzione <code>slowly start<\/code> per il server nel cluster. E aumenta gradualmente il carico.<\/em> <\/p>\n<p><\/p>\n<p>S\u00ec, ottima idea, proveremo quando ci arriveremo.<\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/522734\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u0410\u043d\u0434\u0440\u0435\u0439 \u0411\u043e\u0440\u043e\u0434\u0438\u043d \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442, \u043a\u0430\u043a \u043e\u043d\u0438 \u0443\u0447\u043b\u0438 \u043e\u043f\u044b\u0442 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f PgBouncer \u043f\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0443\u043b\u0435\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 Odyssey, \u043a\u0430\u043a \u0432\u044b\u043a\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u0435\u0433\u043e \u0432 production. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043e\u0431\u0441\u0443\u0434\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0443\u043b\u0435\u0440\u0430 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445: \u043d\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438, \u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u041e\u0434\u0438\u0441\u0441\u0435\u044f. \u0412\u0438\u0434\u0435\u043e: \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0434\u0440\u0435\u0439. \u0412 \u042f\u043d\u0434\u0435\u043a\u0441\u0435 \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":96516,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-96515","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Odyssey roadmap: \u0447\u0442\u043e \u0435\u0449\u0451 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442 \u043f\u0443\u043b\u0435\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. \u0410\u043d\u0434\u0440\u0435\u0439 \u0411\u043e\u0440\u043e\u0434\u0438\u043d (2019) | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-10-12T17:43:02+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-10-12T17:43:02+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Odyssey roadmap: cosa altro vogliamo dal connection pooler. Andrey Borodin (2019) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Odyssey roadmap: \u0447\u0442\u043e \u0435\u0449\u0451 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442 \u043f\u0443\u043b\u0435\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. \u0410\u043d\u0434\u0440\u0435\u0439 \u0411\u043e\u0440\u043e\u0434\u0438\u043d (2019) | ProHoster","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-10-12T17:43:02+00:00","article:modified_time":"2020-10-12T17:43:02+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"96515","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:41:30","updated":"2022-10-01 00:02:14","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/96515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=96515"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/96515\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/96516"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=96515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=96515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=96515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}