{"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\/hr\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","title":{"rendered":"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6c445191705a4c96939cd094bc457a53.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U svom izlaganju, Andrej Borodin \u0107e objasniti kako su uzeli u obzir iskustvo skaliranja PgBouncer pri projektiranju connection poolera. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odyssey<\/a><\/noindex>, te kako su ga uveli u proizvodnu upotrebu. Tako\u0111er, raspraviti \u0107emo koje bi funkcije connection poolera voljeli vidjeti u novim verzijama: va\u017eno nam je ne samo zadovoljiti vlastite potrebe, ve\u0107 i razvijati zajednicu korisnika. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odiseja<\/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=\"Pogledajte 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=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/dd2ea50b72e3d9c4e795aecbf9afdd25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pozdrav svima! Moje ime je Andrej. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0a2f1880005bec1f61b72fb23b555adc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U Yandexu se bavim razvojem open source baza podataka. I danas imamo temu o connection pooleru. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c18e7c937423d2514faa12e820e78e70.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ako znate kako se connection pooler zove na hrvatskom, javite mi. Stvarno \u017eelim prona\u0107i dobar tehni\u010dki termin koji bi trebao postati ustaljen u tehni\u010dkoj literaturi. <\/p>\n<p><\/p>\n<p>Tema je prili\u010dno slo\u017eena, jer u mnogim bazama podataka je connection pooler ugra\u0111en i zapravo nije potrebno ni znati za njega. Naravno, postoje neka pode\u0161avanja, ali to u Postgresu ne prolazi tako jednostavno. Paralelno (na HighLoad++ 2019) ide izlaganje Nikolaja Samohvalova o pode\u0161avanju upita u Postgresu. Razumijem da su ovdje ljudi koji su ve\u0107 savr\u0161eno postavili upite, i to su ljudi koji se suo\u010davaju s rje\u0111im sistemskim problemima, povezanim s mre\u017eom i iskori\u0161tavanjem resursa. Ponekad to mo\u017ee biti prili\u010dno slo\u017eeno, jer problemi nisu o\u010diti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/89c660dd530575e2938e6bf312b83e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U Yandexu imamo Postgres. U Yandex.Cloudu \u017eive mnogi servisi Yandexa. I imamo nekoliko petabajta podataka koji generiraju ne manje od milijun upita u sekundi u Postgresu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/288bfa37b9dcd60acd22ba48f0ef8a39.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pru\u017ea se dovoljno tipi\u010dan klaster svim uslugama \u2013 to je osnovna primarna \u010dvorna jedinica, obi\u010dno dvije replikacije (sinhrona i asinhrona), rezervne kopije, skaliranje \u010ditaju\u0107ih upita na replikama. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c249ca55bb387e25a5560324024cc523.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Svaki \u010dvor klastera je Postgres na kojem, osim Postgresa i sustava za pra\u0107enje, jo\u0161 je instaliran connection pooler. Connection pooler se koristi za fencing i po svojstvu namjene. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0e29be55cc048007db21c80bbb08a9d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0160to je osnovna namjena connection poolera? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e2fbbd440c2781573cb35deeef358f20.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U Postgresu je usvojena procesna paradigma pri radu s bazom podataka. To zna\u010di da je jedna veza jedan proces, jedan backend Postgresa. I u tom backendu ima mnogo razli\u010ditih cache-ova koji je prili\u010dno skupo praviti razli\u010ditima za razne veze. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/587498063b1af8fac4a845961c654bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Osim toga, u Postgres kodu postoji niz koji se zove procArray. Sadr\u017ei osnovne podatke o mre\u017enim vezama. Gotovo svi algoritmi za obradu procArray imaju linearni slo\u017eenost, prolaze kroz cijeli niz mre\u017enih veza. To je prili\u010dno brza petlja, ali kada je u pitanju ve\u0107i broj ulaznih mre\u017enih veza, sve postaje malo skuplje. A kada sve postane malo skuplje, na kraju mo\u017eete platiti vrlo visoku cijenu za veliki broj mre\u017enih veza. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b534a38d0bfae7a65fc4258155a50280.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Postoje 3 mogu\u0107a pristupa:<\/p>\n<p><\/p>\n<ul>\n<li>Na strani aplikacije. <\/li>\n<li>Na strani baze podataka. <\/li>\n<li>I izme\u0111u, tj. razne kombinacije. <\/li>\n<\/ul>\n<p><\/p>\n<p>Na\u017ealost, ugra\u0111eni pooler je trenutno u fazi razvoja. Prijatelji iz tvrtke PostgreSQL Professional se uglavnom time bave. Kada \u0107e biti dostupan, te\u0161ko je predvidjeti. I zapravo, arhitekt ima dvije opcije. To su application-side pool i proxy pool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/702527a09e9fc86dd39b7fd69dcf1fc9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Application-side pool je najjednostavniji na\u010din. Gotovo svi klijentski drajveri pru\u017eaju mogu\u0107nost: milijune va\u0161ih veza u kodu predstaviti kao nekoliko desetaka veza u bazi podataka. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7b66b9e20d22f472ca5ac39f6b9e0ba4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pojavljuje se problem kada u odre\u0111enom trenutku \u017eelite skalirati backend, \u017eelite ga rasporediti na vi\u0161e virtualnih ma\u0161ina. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f216fd7a8c01c2b07891e2242c48b06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tada shvatite da imate nekoliko dostupnih zona, nekoliko data centara. A pristup s client side pooling vodi do velikih brojeva. Velikih \u2013 oko 10 000 veza. To je kraj koji mo\u017ee normalno raditi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5bc5f284fd8ff568bbe16c3895b7ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kada govorimo o proxy poolerima, postoje dva poolera koja znaju mnogo. Oni nisu samo pooleri. Oni su pooleri + dodatna sjajna funkcionalnost. To su <noindex><a rel=\"nofollow\" href=\"https:\/\/www.pgpool.net\/\">Pgpool<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/crunchy-proxy\">Crunchy-Proxy<\/a><\/noindex>. <\/p>\n<p><\/p>\n<p>Ali, na\u017ealost, ta dodatna funkcionalnost nije svima potrebna. I dovodi do toga da pooleri podr\u017eavaju samo sesijski pooling, tj. jedan ulazni klijent, jedan izlazni klijent u bazi podataka. <\/p>\n<p><\/p>\n<p>Za na\u0161e potrebe to nije ba\u0161 dobro, stoga koristimo PgBouncer, koji implementira transaction pooling, tj. serverske veze se uskla\u0111uju s klijentskim vezama samo tijekom trajanja transakcije. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5fedbe14656d2ac2cde8d1878a950e2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I pod na\u0161im optere\u0107enjem \u2013 to je istina. <strong>Ali postoje neki problemi.<\/strong>.<img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/61fd36cadcd9948d624dafa711777307.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Problemi po\u010dinju kada \u017eelite dijagnosticirati sesiju, jer su sve ulazne veze lokalne. Sve dolaze s loopback-a i nekako je te\u0161ko pratiti sesiju. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/36108c4956c410a1b1f286a88bc393d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Naravno, mo\u017eete koristiti application_name_add_host. To je na\u010din na strani Bouncer-a za dodavanje IP adrese u application_name. Ali application_name se postavlja dodatnom vezom. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b4cec483aa776f48db7ad3966c3b78e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na ovom grafikonu, gdje je \u017euta linija stvarni zahtjevi, a plava linija su zahtjevi koji ulaze u bazu. I ta razlika predstavlja postavljanje application_name koje je potrebno samo za pra\u0107enje, ali nije potpuno besplatno. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c02ea73a6f1a2a4cd6af6c621f321ab4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Osim toga, u Bouncer-u nije mogu\u0107e ograni\u010diti jedan pool, tj. broj veza s bazom podataka za odre\u0111enog korisnika ili odre\u0111enu bazu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3431a463e04106066e2799aead66f571.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>K \u010demu to vodi? Imate optere\u0107enu uslugu napisanju u C++ i negdje u blizini malu uslugu na nodu koja ne radi ni\u0161ta stra\u0161no s bazom, ali njezin drajver poludi. Otvara 20.000 veza, a sve ostalo \u010deka. \u010cak imate i normalan kod. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d7fa321714dc017b017945dffcf79bc6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Naravno, napisali smo mali patch za Bouncer koji je dodao ovu postavku, tj. ograni\u010denje klijenata na pool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d58884fc5ac0f90ff8442f126972157a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To se moglo napraviti na strani Postgresa, tj. uloge u bazi podataka ograni\u010diti brojem veza.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d6ff70db72964ed4eae5eaa47309931.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ali tada gubite mogu\u0107nost da shvatite za\u0161to nemate veze sa serverom. PgBouncer ne prolazi gre\u0161ku veze, uvijek vra\u0107a istu informaciju. I ne mo\u017eete shvatiti: mo\u017eda vam se promijenila lozinka, mo\u017eda je baza jednostavno pala, mo\u017eda ne\u0161to nije u redu. Ali nema dijagnostike. Ako se sesija ne mo\u017ee uspostaviti, ne\u0107ete saznati za\u0161to to ne mo\u017eete u\u010diniti. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cb3048344a94f2953bf403485d28e69f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U jednom trenutku gledate grafikone aplikacije i vidite da aplikacija ne radi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e67c6680bb9a7f41242af9f9e4920916.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Gledate u top i vidite da je Bouncer jednopotni. To je prekretnica u \u017eivotu usluge. Shva\u0107ate da ste se pripremali za skaliranje baze podataka za godinu i pol, a sada morate skalirati pooler. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4c140c4ba6db19cb9939c1148638fb73.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Do\u0161li smo do toga da nam treba vi\u0161e PgBouncer-a. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. 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>Malo smo ispravili Bouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/97755489a25ebfe38efd56ff897bd8fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I napravili smo tako da mo\u017ee biti podignuto vi\u0161e Bouncer-a s ponovnom upotrebom TCP porta. A ve\u0107 operacijski sustav automatski prebacuje dolazne TCP veze izme\u0111u njih na round-robin na\u010din.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/ac30d3f067de2a8cd66ad2325c3a3b58.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To je transparentno za klijente, tj. sve izgleda kao da imate jedan Bouncer, ali imate fragmentaciju idle veza izme\u0111u pokrenutih Bouncer-a. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/53825f075db00b026c12013a610be456.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U nekom trenutku mo\u017eete primijetiti da ova tri Bouncer-a koriste 100 % svojih jezgri. Trebat \u0107e vam prili\u010dno puno Bouncer-a. Za\u0161to? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/66c17883a043e157cd7ceab2c2a4e326.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Zato \u0161to imate TLS. Imate \u0161ifriranu vezu. Ako benchmarkirate Postgres s TLS-om i bez njega, otkrit \u0107ete da broj uspostavljenih veza pada skoro za dva reda veli\u010dine kada se uklju\u010di \u0161ifriranje, jer TLS handshake tro\u0161i resurse CPU-a. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6101121ebe136af16e5eb1a484c65d66.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na vrhu mo\u017eete vidjeti prili\u010dno mnogo kriptografskih funkcija koje se izvode tijekom vala dolaznih veza. Budu\u0107i da na\u0161 primary mo\u017ee prelaziti izme\u0111u dostupnosnih zona, val dolaznih veza je prili\u010dno uobi\u010dajena situacija. To jest, iz nekog razloga stari primary je bio nedostupan, a sav teret je preba\u010den u drugi podatkovni centar. Oni \u0107e svi odjednom do\u0107i da se pozdrave s TLS-om. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c238ac2f511568590dc275e01c192c00.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Veliki broj TLS handshake-a mo\u017eda se vi\u0161e ne pozdravlja s Bouncer-om, ve\u0107 mu mo\u017ee zagu\u0161iti kapacitet. Zbog vremenskog ograni\u010denja val dolaznih veza mo\u017ee postati neiscrpan. Ako imate retry prema bazi bez eksponencijalnog backoff-a, oni ne\u0107e ponovo dolaziti kao koherentni val. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f42d0b210174d4d172254603ae6b834a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Evo primjer 16 PgBouncer-a koji optere\u0107uju 16 jezgri na 100 %.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d048d3774c09e5b6a3fb3c7bff62084.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Do\u0161li smo do kaskadnog PgBouncer-a. Ovo je najbolja konfiguracija koju mo\u017eemo posti\u0107i pod na\u0161im optere\u0107enjem s Bouncer-om. Vanjski Bouncers slu\u017ee za TCP handshake, dok unutarnji Bouncers slu\u017ee za stvarno pooliranje, kako ne bi previ\u0161e fragmentirali vanjske veze.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3a4ee4ea46d5fe8479a5a7222ee134da.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U takvoj konfiguraciji mogu\u0107 je glatki restart. Mo\u017eete restartati svih 18 Bouncer-a jedan po jedan. No, odr\u017eavanje takve konfiguracije prili\u010dno je te\u0161ko. Sustavni administratori, DevOps i ljudi koji su zaista odgovorni za ovaj server ne\u0107e biti previ\u0161e zadovoljni takvom shemom. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/5291fe67dbe02036f3ff8e98bdd84d1b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u010cinilo bi se da sve na\u0161e nadogradnje mo\u017eemo promovirati u open source, ali Bouncer se ne podr\u017eava dobro. Na primjer, mogu\u0107nost pokretanja nekoliko PgBouncer-a na jednoj portu je odobrena prije mjesec dana. A pull request sa tom funkcijom bio je nekoliko godina ranije. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. 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>Ili jo\u0161 jedan primjer. U Postgresu mo\u017eete prekinuti izvr\u0161avanje upita tako da po\u0161aljete tajnu na drugu vezu bez dodatne autentifikacije. No neki klijenti jednostavno \u0161alju TCP-reset, tj. prekidaju mre\u017enu vezu. \u0160to \u0107e Bouncer u\u010diniti u tom slu\u010daju? Ni\u0161ta. Nastavit \u0107e izvr\u0161avati upit. Ako imate ogroman broj veza koje malim upitima optere\u0107uju bazu, samo prekinuti vezu s Bouncerom ne\u0107e biti dovoljno; potrebno je tako\u0111er zavr\u0161iti one upite koji se izvr\u0161avaju u bazi. <\/p>\n<p><\/p>\n<p>To je ispravljeno i ovaj problem jo\u0161 nije integriran u upstream Bouncera. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a9695b6d9e640a5543dc73429eb0050b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I tako smo do\u0161li do zaklju\u010dka da nam treba vlastiti connection pooler koji \u0107e se razvijati, ispravljati, u kojem \u0107e se mo\u0107i brzo rje\u0161avati problemi i koji, naravno, treba biti vi\u0161edretven. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e755cd9b06a004f0eced1dc12fd3a6fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi\u0161edretvenost smo postavili kao glavni cilj. Moramo dobro podnositi val dolaznih TLS veza. <\/p>\n<p><\/p>\n<p>Za to smo morali razviti posebnu biblioteku koja se zove Machinarium, a koja je namijenjena opisivanju stanja ma\u0161ine mre\u017ene povezanosti kao sekvencijalnog koda. Ako pogledate izvorni kod libpq, vidjet \u0107ete prili\u010dno slo\u017eene pozive koji vam mogu vratiti rezultat i re\u0107i: 'Pozovi me malo kasnije. Trenutno imam IO, ali kada IO zavr\u0161i, imat \u0107u optere\u0107enje za procesor'. I to je vi\u0161eslojna shema. Mre\u017ena interakcija obi\u010dno se opisuje kao ma\u0161ina stanja. Mnogim pravilima tipa 'Ako sam ranije primio zaglavlje paketa veli\u010dine N, sada \u010dekam N bajtova', 'Ako sam slao paket SYNC, sada \u010dekam paket s metapodacima rezultata'. Ispostavlja se prili\u010dno te\u0161ki kontraintuitivni kod, kao da se labirint pretvorio u linearni raspored. U\u010dinili smo da umjesto ma\u0161ine stanja programer opisuje glavni put interakcije kao obi\u010dan imperativni kod. Samo \u0161to u ovom imperativnom kodu treba umetnuti mjesta gdje se slijed izvr\u0161avanja mora prekinuti \u010dekanjem podataka s mre\u017ee, predaju\u0107i kontekst izvr\u0161avanja drugoj korutini (zelenoj niti). Ovaj pristup je sli\u010dan onome \u0161to najizgledniji put u labirintu zapisujemo uzastopno, a zatim mu dodajemo ogranke. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a6bfb4b11961c7db3a7c7184674e3bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na kraju imamo jednu nit koja radi TCP accept i round-robin&#8217;om prenosi vi\u0161e workers TPC-veza. <\/p>\n<p><\/p>\n<p>Svaka klijentska veza uvek radi na jednom procesoru. To omogu\u0107ava da bude friendly prema cache-u. <\/p>\n<p><\/p>\n<p>Osim toga, malo smo doradili sakupljanje malih paketa u jedan veliki paket radi olak\u0161avanja sistemskog TCP stacka.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7d740c23baecdd2f993c83cd54a0a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tako\u0111e, pobolj\u0161ali smo transakcijsko povla\u010denje tako da Odyssey uz postavljenu konfiguraciju mo\u017ee poslati CANCEL i ROLLBACK u slu\u010daju prekida mre\u017ene veze, tj. ako niko ne \u010deka na zahtev, Odyssey \u0107e re\u0107i bazi da ne poku\u0161ava da izvr\u0161i taj zahtev koji mo\u017ee tro\u0161iti dragocene resurse.<\/p>\n<p><\/p>\n<p>Po mogu\u0107stvu, zadr\u017eavamo veze za istog klijenta. To omogu\u0107ava da se ne ponovo postavlja application_name_add_host. Ako je to mogu\u0107e, nemamo dodatno ponavljanje parametara koji su potrebni za dijagnostiku. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/afb2fb7fb16d65c9ea73a8978d1eb83c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Radimo u interesu Yandex. Oblaka. Ako koristite managed PostgreSQL i imate postavljen connection pooler, mo\u017eete kreirati logi\u010dku replikaciju napolje, tj. oti\u0107i od nas, ako \u017eelite, pomo\u0107u logi\u010dke replikacije. Bouncer ne\u0107e proslediti tok logi\u010dke replikacije napolje. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c53defc92ebd8f3bec57ce64d97b9f72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovo je primer pode\u0161avanja logi\u010dke replikacije. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a37d9d1abf288d17fa646b642e8b62ab.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tako\u0111e, imamo podr\u0161ku za fizi\u010dku replikaciju napolje. U Oblaku je to, naravno, nemogu\u0107e, jer bi va\u0161 klaster preneo previ\u0161e informacija o sebi. Ali u va\u0161im instalacijama, ako vam je potrebna fizi\u010dka replikacija kroz connection pooler u Odyssey, to je mogu\u0107e. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/572934ce5b08115e57ab4b55d2153c6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U Odyssey imamo potpuno kompatibilno pra\u0107enje sa PgBouncer. Imamo istu konzolu koja izvr\u0161ava gotovo sve iste komande. Ako ne\u0161to nedostaje, po\u0161aljite pull request ili bar issue na GitHub, doda\u0107emo neophodne komande. No, osnovna funkcionalnost konzole PgBouncer ve\u0107 postoji kod nas. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/451dd798fb3523a7a174ebfe00a14bc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I, naravno, imamo prosle\u0111ivanje gre\u0161aka. Vra\u0107amo onu gre\u0161ku koju je prijavila baza. Dobija\u0107ete informacije za\u0161to ne mo\u017eete da se pove\u017eete na bazu, a ne samo da ne mo\u017eete da se pove\u017eete. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/14b4cb0efa33a2658dfc528349a5382f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ova mogu\u0107nost se isklju\u010duje u slu\u010daju da vam je potrebna 100%-na kompatibilnost sa PgBouncer. Mo\u017eemo se pona\u0161ati kao Bouncer, samo u slu\u010daju. <\/p>\n<p><\/p>\n<p><strong>Razvoj<\/strong><\/p>\n<p><\/p>\n<p>Nekoliko re\u010di o izvorom kodu Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. 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>Na primjer, postoje komande \u201ePause \/ Resume\u201c. Obi\u010dno se koriste za a\u017euriranje baze podataka. Ako trebate a\u017eurirati Postgres, mo\u017eete ga staviti na pauzu u connection pooler-u, izvr\u0161iti pg_upgrade, a zatim nastaviti. Iz perspektive klijenta, to \u0107e izgledati kao da je baza jednostavno usporila. Ovu funkcionalnost su nam donijeli ljudi iz zajednice. Jo\u0161 nije spojeno, ali uskoro \u0107e sve biti. (Ve\u0107 je spojeno)<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. 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 ve\u0107 je spojeno<\/p>\n<p><\/p>\n<p>Osim toga, jedna od novih funkcija u PgBounceru je podr\u0161ka za SCRAM Authentication, koju nam je tako\u0111er donio osoba koja ne radi u Yandex.Cloud-u. I jedno i drugo \u2013 vrlo su kompleksne funkcionalnosti i va\u017ene. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f39346a543c88d17728233d05c2dff19.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Stoga \u017eelim re\u0107i iz \u010dega je sastavljen Odyssey, mo\u017eda biste i vi \u017eeljeli malo pisati kod. <\/p>\n<p><\/p>\n<p>Imate izvorni Odyssey koji se oslanja na dvije glavne biblioteke. Biblioteka Kiwi \u2013 to je implementacija Postgres protokola poruka. To jest, nativni proto 3 u Postgres-u su standardne poruke s kojima se frontend-i i backend-i mogu razmjenjivati. One su implementirane u biblioteci Kiwi.<\/p>\n<p><\/p>\n<p>Biblioteka Machinarium \u2013 to je biblioteka za implementaciju tokova. Mali dio ovog Machinarium-a napisan je u asembleru. Ali, ne bojte se, tu je samo 15 redaka. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd18f250af50eabd53536b2c0d7f12b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Arhitektura Odyssey. Tu je glavna ma\u0161ina u kojoj su pokrenute coroutines. U toj ma\u0161ini je implementirano prihva\u0107anje dolaznih TCP veza i raspodjela po worker-ima. <\/p>\n<p><\/p>\n<p>Unutar jednog workera mo\u017ee raditi upravitelj vi\u0161e klijenata. Tako\u0111er, u glavnoj niti vrte se konzola i obrada crone-zadataka za uklanjanje veza koje vi\u0161e nisu potrebne u pool-u.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7072fb20f406f2ee5788542860ccdf50.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Za testiranje Odyssey-a koristi se standardni set testova Postgres-a. Jednostavno pokre\u0107emo install-check kroz Bouncer i kroz Odyssey, dobijamo nulti div. Tu je nekoliko testova vezanih za formatiranje datuma koji se ne prolaze potpuno identi\u010dno u Bouncer-u i u Odyssey-u.<\/p>\n<p><\/p>\n<p>Osim toga, postoji mnogo drajvera koji imaju svoje testiranje. Njihove teste koristimo za testiranje Odyssey-a.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/fb01cc9a0e9724ddcd3cc3d088afb182.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tako\u0111er, zbog na\u0161e kaskadne konfiguracije moramo testirati razli\u010dite kombinacije: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey kako bismo bili sigurni da, ako se Odyssey na\u0111e u nekom dijelu kaskade, on tako\u0111er nastavlja raditi onako kako o\u010dekujemo. <\/p>\n<p><\/p>\n<p><strong>Grablje<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/25855b691180bca083025b9e8b611c09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Koristimo Odyssey u produkciji. Ne bi bilo po\u0161teno re\u0107i da sve jednostavno radi. Da, u nekim slu\u010dajevima, ali ne uvijek. Na primjer, u produkciji je sve jednostavno radilo, a onda su nam na\u0161i prijatelji iz PostgreSQL Professional rekli da imamo curenje memorije. Doista su to otkrili, ispravili smo to. No, bilo je to jednostavno. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e638d88397b32b1ca0b74c9c1b905f81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tada smo otkrili da u connection pooleru postoje ulazne TLS veze i izlazne TLS veze. Za te veze su potrebni klijentni certifikati i serverski certifikati.<\/p>\n<p><\/p>\n<p>Serverski certifikati Bouncer i Odyssey ponovo pro\u010ditavaju iz svog pcache-a, ali klijentni certifikati ne trebaju biti ponovo pro\u010ditani iz pcache-a, jer na\u0161 skalabilni Odyssey u kona\u010dnici nailazi na sistemske performanse pri \u010ditanju tog certifikata. To nam je bilo iznena\u0111enje, jer se to nije dogodilo odmah. U po\u010detku se linearno skalirao, a nakon 20 000 istovremenih ulaznih veza problem se po\u010deo manifestirati.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6cff094cd59a990e448b82fa0b1572b7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pluggable Authentication Method je mogu\u0107nost autentifikacije ugra\u0111enim linuxovim sredstvima. U PgBouncer-u to je implementirano tako da postoji poseban tok koji \u010deka na odgovor od PAM-a i postoji glavni tok PgBouncer-a koji opslu\u017euje trenutnu vezu i mo\u017ee zatra\u017eiti da se zadr\u017ei u PAM toku. <\/p>\n<p><\/p>\n<p>To nismo implementirali zbog jedne jednostavne stvari. Imamo mnogo tokova. Za\u0161to bi nam to bilo potrebno?<\/p>\n<p><\/p>\n<p>Na kraju, to mo\u017ee stvoriti probleme jer, ako imate PAM autentifikaciju i ne-PAM autentifikaciju, velika valna PAM autentifikacija mo\u017ee zna\u010dajno usporiti ne-PAM autentifikaciju. To je jedna od onih stvari koju nismo ispravili. No, ako \u017eelite to ispraviti, mo\u017eete se time pozabaviti. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c7bd9e9980ff7298b30a59c130f03dbb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jo\u0161 jedan problem bio je to \u0161to imamo jedan tok koji prihva\u0107a sve ulazne veze. I zatim ih proslje\u0111uje na worker pool, gdje \u0107e se odvijati TLS handshake.<\/p>\n<p><\/p>\n<p>Na kraju, ako imate koherentnu valnu od 20 000 mre\u017enih veza, sve \u0107e biti prihva\u0107ene. I na strani klijenta libpq po\u010det \u0107e odbrojavanje vremenskih ograni\u010denja. \u010cini se da je osnovno vremensko ograni\u010denje 3 sekunde. <\/p>\n<p><\/p>\n<p>Ako svi ne mogu istovremeno u\u0107i u bazu, ne mogu u\u0107i u bazu, jer sve to mo\u017ee biti pokriveno neeksponencijalnim ponovnim poku\u0161ajem. <\/p>\n<p><\/p>\n<p>Do\u0161li smo do toga da smo ovdje kopirali shemu iz PgBouncer-a s time da imamo ograni\u010denje broja TCP veza koje prihva\u0107amo. <\/p>\n<p><\/p>\n<p>Ako vidimo da prihva\u0107amo veze, a one na kraju ne mogu uspostaviti handshake, stavljamo ih u red kako ne bi tro\u0161ile resurse sredi\u0161njeg procesora. To dovodi do toga da se istovremeni handshake ne mo\u017ee odvijati za sve veze koje su do\u0161le. No, barem \u0107e netko u\u0107i u bazu, \u010dak i ako je optere\u0107enje prili\u010dno sna\u017eno.<\/p>\n<p><\/p>\n<p><strong>Putokaz<\/strong><\/p>\n<p><\/p>\n<p>\u0160to bismo \u017eeljeli vidjeti u budu\u0107nosti u Odyssey? \u0160to smo spremni sami razvijati i \u0161to \u010dekamo od zajednice?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4719437d80b33efc3da6572af9a4dedb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Za kolovoz 2019. godine.<\/strong><\/p>\n<p><\/p>\n<p>Ovako je izgledao putokaz Odyssey u kolovozu:<\/p>\n<p><\/p>\n<ul>\n<li>\u017deljeli smo SCRAM i PAM autentifikaciju.<\/li>\n<li>\u017deljeli smo preusmjeravanje upita za \u010ditanje na standby. <\/li>\n<li>\u017deljeli bismo online-restart. <\/li>\n<li>I mogu\u0107nost stavljanja poslu\u017eitelja na pauzu. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/455c92f92df826257c2c57dc2b034e22.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Polovica ovog putokaza je ostvarena, i to ne od nas. I to je dobro. Stoga, razgovarajmo o onome \u0161to je ostalo i dodajmo jo\u0161. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. 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\">\u0160to se ti\u010de preusmjeravanja upita za \u010ditanje na 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=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0873cffd4f1ae15d9ffa6d080671051b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U principu, u Postgresu, po\u010dev\u0161i od verzije 10, postoji mogu\u0107nost da pri povezivanju navedete i session_attrs. U vezi mo\u017eete navesti sve hostove baza podataka i re\u0107i za\u0161to idete u bazu podataka: za zapisivanje ili samo za \u010ditanje. I drajver \u0107e sam odabrati prvi host na listi koji mu vi\u0161e odgovara, a koji ispunjava zahtjeve session_attrs. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0693d1327fe5826502a01c21d05d5b4c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ali problem ovog pristupa je u tome \u0161to ne kontrolira ka\u0161njenje replikacije. Mo\u017ee postojati neka replika koja kasni na neprihvatljivo vrijeme za va\u0161u uslugu. Da bismo omogu\u0107ili potpuno funkcionalno izvr\u0161avanje upita za \u010ditanje na replici, u osnovi, trebamo podr\u017eati u Odyssey mogu\u0107nost da ne radi kada nije mogu\u0107e \u010ditati. <\/p>\n<p><\/p>\n<p>Odyssey bi trebao s vremena na vrijeme i\u0107i u bazu i pitati o replikacijskom razmaku od primarnog. I ako dostigne ograni\u010denje, nove upite u bazu ne smije propustiti, re\u0107i klijentu da treba ponovo inicirati veze i, mo\u017eda, odabrati drugi host za izvr\u0161avanje upita. To \u0107e omogu\u0107iti da se baza br\u017ee oporavi od replikacijskog ka\u0161njenja i ponovo se vrati na odgovaranje na upite. <\/p>\n<p><\/p>\n<p>Te\u0161ko je odrediti vremenske okvire realizacije, jer je to open source. No, nadam se da ne\u0107e trajati 2,5 godine kao kod kolega iz PgBouncer. Ovu funkciju bismo \u017eeljeli vidjeti u Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. 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\">U zajednici su ljudi pitali o podr\u0161ci za pripremljene izjave.<\/a><\/noindex>. Sada mo\u017eete stvoriti pripremljenu izjavu na dva na\u010dina. Prvo, mo\u017eete izvr\u0161iti SQL naredbu, konkretno \u201epripremljenu\u201c. Da bismo razumeli ovu SQL naredbu, moramo nau\u010diti kako razumevati SQL s strane Bouncera. To bi bilo pretjerano, jer nam je potreban cjelokupni parser. Ne mo\u017eemo parsirati svaku SQL naredbu. <\/p>\n<p><\/p>\n<p>No, postoji pripremljena izjava na nivou protokola poruka na proto3. I to je trenutak kada informacije o tome da se stvara pripremljena izjava dolaze u strukturiranom obliku. Mogli bismo podr\u017eati razumevanje da je na nekoj server konekciji klijent zatra\u017eio stvaranje pripremljenih izjava. \u010cak i ako je transakcija zatvorena, i dalje moramo odr\u017eavati povezanost servera i klijenta. <\/p>\n<p><\/p>\n<p>Me\u0111utim, ovde dolazi do nesuglasja u dijalogu, jer neko govori o tome da je potrebno razumeti koju je to\u010dno pripremljenu izjavu klijent stvorio i razdvojiti server konekciju me\u0111u svim klijentima koji su stvorili ovu server konekciju, tj. koji su stvorili takvu pripremljenu izjavu. <\/p>\n<p><\/p>\n<p>Andres Freund je rekao da, ako vam do\u0111e klijent koji je ve\u0107 stvorio takvu pripremljenu izjavu na drugoj server konekciji, treba da je stvorite umesto njega. No, \u010dini se da je pomalo pogre\u0161no izvr\u0161avati upite u bazi umesto klijenta, ali s gledi\u0161ta programera koji pi\u0161e protokol interakcije sa bazom, bilo bi zgodno kada bi mu jednostavno dali mre\u017enu konekciju u kojoj postoji takav pripremljeni upit. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd56b3ad015195d86a64e52be365b16a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I jo\u0161 jedna funkcionalnost koju trebamo implementirati. Trenutno imamo monitoring kompatibilan s PgBouncerom. Mo\u017eemo vratiti prose\u010dno vreme izvr\u0161avanja upita. Ali prose\u010dno vreme je prosek: neko je hladan, neko je topao - u proseku su svi zdravi. To nije istina. <\/p>\n<p><\/p>\n<p>Treba da implementiramo podr\u0161ku za percentile koji bi ukazivali na to da postoje spori upiti koji tro\u0161e resurse, a \u0161to bi monitoring u\u010dinilo prihvatljivijim. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6f285f3eb0d79e7f25d42f0e792b85b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Najva\u017enije \u2013 potrebna nam je verzija 1.0 (Verzija 1.1 je ve\u0107 objavljena). \u010cinjenica je da je trenutno Odyssey u verziji 1.0rc, tj. release candidate. Svi problemi koje sam naveo su re\u0161eni upravo s tom verzijom, osim curenja memorije. <\/p>\n<p><\/p>\n<p>\u0160to za nas zna\u010di verzija 1.0? Izbacujemo Odyssey na na\u0161e baze. Ve\u0107 sada radi na na\u0161im bazama, ali kada postigne razinu od 1.000.000 zahtjeva u sekundi, mo\u017eemo re\u0107i da je to verzija za izdavanje i da mo\u017ee biti nazvana 1.0. <\/p>\n<p><\/p>\n<p>U zajednici je nekoliko ljudi zatra\u017eilo da verzija 1.0 uklju\u010duje i pauzu i SCRAM. No to bi zna\u010dilo da bismo morali odmah izbaciti sljede\u0107u verziju u produkciju, jer ni SCRAM ni pauza jo\u0161 nisu spojeni. Ali, vjerojatno \u0107e se to pitanje rije\u0161iti dovoljno brzo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: \u0161to jo\u0161 \u017eelimo od pooler-a poveznica. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/2f50de9f51f653a7396965239bd545e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u010cekam va\u0161e pull requestove. Tako\u0111er bih volio \u010duti koje probleme imate s Bouncer-om. O tome mo\u017eemo razgovarati. Mo\u017eda bismo mogli implementirati neke funkcije koje su vam potrebne. <\/p>\n<p><\/p>\n<p>Moja je uloga zavr\u0161ila, volio bih \u010duti vas. Hvala!<\/p>\n<p><\/p>\n<p>Pitanja<\/p>\n<p><\/p>\n<p><em>Ako postavim application_name, ho\u0107e li se ispravno proslijediti, uklju\u010duju\u0107i u transaction pooling u Odyssey?<\/em><\/p>\n<p><\/p>\n<p>U Odyssey ili u Bouncer-u?<\/p>\n<p><\/p>\n<p><em>U Odyssey. U Bouncer-u se proslijedi.<\/em> <\/p>\n<p><\/p>\n<p>Postavit \u0107emo set. <\/p>\n<p><\/p>\n<p><em>I ako \u0107e moja stvarna veza skakati na druge veze, ho\u0107e li se ona proslijediti?<\/em><\/p>\n<p><\/p>\n<p>U\u010dinit \u0107emo set svih parametara navedenih na popisu. Ne mogu re\u0107i je li application_name na tom popisu. \u010cini se da sam ga vidio. Postavit \u0107emo sve iste parametre. Jednim zahtjevom set \u0107e napraviti sve \u0161to je klijent postavio prilikom pokretanja. <\/p>\n<p><\/p>\n<p><em>Hvala, Andrej, na izlaganju! Dobro izlaganje! Drago mi je \u0161to se Odyssey s svakom minutom razvija sve br\u017ee. \u017delim da tako nastavite. Ve\u0107 smo se obratili s molbom da imamo multi data-source povezivanje kako bi Odyssey mogao istovremeno povezivati s razli\u010ditim bazama podataka, tj. master slave, a zatim se automatski nakon failover-a povezivati s novim masterom.<\/em> <\/p>\n<p><\/p>\n<p>Da, \u010dini se da se sje\u0107am te rasprave. Trenutno postoji nekoliko spremi\u0161ta. No nema prebacivanja izme\u0111u njih. Moramo na na\u0161oj strani provjeriti server da li je jo\u0161 uvijek \u017eiv i shvatiti da je do\u0161lo do failover-a, tko \u0107e pozvati pg_recovery. Imam standardni na\u010din razumjeti da nismo do\u0161li na master. I moramo razumjeti na neki na\u010din iz gre\u0161aka ili kako? Ideja je zanimljiva, raspravlja se. Pi\u0161ite vi\u0161e komentara. Ako imate radne ruke koje znaju C, to bi bilo sjajno. <\/p>\n<p><\/p>\n<p>Pitanje skaliranja replikama nas tako\u0111er zanima jer \u017eelimo u\u010diniti usvajanje replikiranih klastera maksimalno jednostavnim za programere aplikacija. Me\u0111utim, ovdje bismo voljeli vi\u0161e komentara, tj. kako to\u010dno u\u010diniti, kako to dobro u\u010diniti. <\/p>\n<p><\/p>\n<p><em>Pitanje je tako\u0111er o replikama. Ispada da imate majstora i nekoliko replikacija. Jasno je da se u replice povezuje rje\u0111e nego u majstora, jer mogu postojati razlike. Rekli ste da razlike u podacima mogu biti takve da ne\u0107e zadovoljiti va\u0161e poslovanje i ne\u0107ete se povezivati dok se ne replikiraju. U tom slu\u010daju, ako dugo niste odlazili tamo, a zatim po\u010dnete, podaci koji su potrebni ne\u0107e odmah biti dostupni. To jest, ako se stalno povezujemo s majstorom, tada je ke\u0161 zagrijan, a u replici je ke\u0161 malo zaostao.<\/em> <\/p>\n<p><\/p>\n<p>Da, to je istina. U pcache ne\u0107e biti blokova podataka koje \u017eelite, u real cache ne\u0107e biti informacija o tablicama koje \u017eelite, u planovima ne\u0107e biti analiziranih upita, jednostavno ne\u0107e biti ni\u010dega. <\/p>\n<p><\/p>\n<p><em>I kada imate neki klaster i dodate novu repliku, dok se ona pokre\u0107e, u njoj je sve lo\u0161e, tj. ona pove\u0107ava svoj ke\u0161.<\/em> <\/p>\n<p><\/p>\n<p>Shvatio sam ideju. Ispravan pristup bi bio pokrenuti mali postotak upita prvo na replici, koji bi zagrijali ke\u0161. Drugim rije\u010dima, imamo uvjet da ne smijemo zaostajati vi\u0161e od 10 sekundi za majstora. I to uklju\u010diti ne jednom, nego postepeno za neke klijente. <\/p>\n<p><\/p>\n<p><em>Da, pove\u0107ati te\u017einu.<\/em><\/p>\n<p><\/p>\n<p>To je dobra ideja. Ali prvo treba implementirati ovo isklju\u010divanje. Prvo se treba isklju\u010diti, a onda \u0107emo razmi\u0161ljati kako se uklju\u010diti. To je odli\u010dna funkcija za postepeno uklju\u010divanje.<\/p>\n<p><\/p>\n<p><em>U nginx-u postoji takva opcija <code>polako zapo\u010deti<\/code> u klasteru za server. I polako pove\u0107ava optere\u0107enje.<\/em> <\/p>\n<p><\/p>\n<p>Da, odli\u010dna ideja, poku\u0161at \u0107emo kada do\u0111emo do toga.<\/p>\n<p>Izvor: <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.4 - 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\/hr\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\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\/hr\/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: \u0161to jo\u0161 \u017eelimo od connection poolera. Andrej Borodin (2019) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/hr\/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":"hr_HR","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\/hr\/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\/hr\/wp-json\/wp\/v2\/posts\/96515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=96515"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/96515\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/96516"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=96515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=96515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=96515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}