{"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\/pl\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","title":{"rendered":"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6c445191705a4c96939cd094bc457a53.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W raporcie Andriej Borodin opowie, jak uwzgl\u0119dnili do\u015bwiadczenie skalowania PgBouncer podczas projektowania puli po\u0142\u0105cze\u0144 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odyssey<\/a><\/noindex>, jak wdra\u017cali go w produkcji. Ponadto om\u00f3wimy, jakie funkcje puli chcieliby\u015bmy zobaczy\u0107 w nowych wersjach: wa\u017cne jest dla nas nie tylko zaspokojenie naszych potrzeb, ale tak\u017ce rozwijanie spo\u0142eczno\u015bci u\u017cytkownik\u00f3w <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odysseja<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Wideo:<\/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=\"Odtwarzaj wideo\" 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: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/dd2ea50b72e3d9c4e795aecbf9afdd25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cze\u015b\u0107 wszystkim! Nazywam si\u0119 Andriej. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0a2f1880005bec1f61b72fb23b555adc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W Yandex zajmuj\u0119 si\u0119 rozwojem open source baz danych. I dzi\u015b naszym tematem jest pula po\u0142\u0105cze\u0144. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c18e7c937423d2514faa12e820e78e70.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Je\u015bli wiecie, jak nazwa\u0107 pul\u0119 po\u0142\u0105cze\u0144 po rosyjsku, to mi powiedzcie. Bardzo chc\u0119 znale\u017a\u0107 dobry termin techniczny, kt\u00f3ry powinien si\u0119 ugruntowa\u0107 w literaturze technicznej. <\/p>\n<p><\/p>\n<p>Temat jest do\u015b\u0107 skomplikowany, poniewa\u017c w wielu bazach danych pula po\u0142\u0105cze\u0144 jest wbudowana i nawet nie trzeba o niej wiedzie\u0107. Oczywi\u015bcie w ka\u017cdym z nich s\u0105 jakie\u015b ustawienia, ale w Postgresie nie da si\u0119 tak po prostu. R\u00f3wnocze\u015bnie (na HighLoad++ 2019) odbywa si\u0119 wyk\u0142ad Niko\u0142aja Samochwa\u0142owa o konfiguracji zapyta\u0144 w Postgresie. Rozumiem, \u017ce przyszli tu ludzie, kt\u00f3rzy ju\u017c idealnie skonfigurowali zapytania, i to s\u0105 ludzie, kt\u00f3rzy napotykaj\u0105 bardziej rzadkie problemy systemowe zwi\u0105zane z sieci\u0105, wykorzystaniem zasob\u00f3w. I miejscami mo\u017ce to by\u0107 do\u015b\u0107 skomplikowane, poniewa\u017c problemy nie s\u0105 oczywiste.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/89c660dd530575e2938e6bf312b83e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W Yandex mamy Postgres. W Yandex.Cloud mieszka wiele us\u0142ug Yandexu. I mamy kilka petabajt\u00f3w danych, kt\u00f3re generuj\u0105 nie mniej ni\u017c milion zapyta\u0144 na sekund\u0119 w Postgresie. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/288bfa37b9dcd60acd22ba48f0ef8a39.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I zapewniamy do\u015b\u0107 standardowy klaster dla wszystkich us\u0142ug \u2013 to g\u0142\u00f3wny w\u0119ze\u0142 primary, zwykle dwie repliki (synchroniczna i asynchroniczna), kopie zapasowe, skalowanie zapyta\u0144 odczytowych na replikach. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c249ca55bb387e25a5560324024cc523.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ka\u017cdy w\u0119ze\u0142 klastra to Postgres, w kt\u00f3rym opr\u00f3cz Postgresa i monitorowania systemu jeszcze zainstalowany jest pooler po\u0142\u0105cze\u0144. Pooler po\u0142\u0105cze\u0144 jest u\u017cywany do fencing i w swoim podstawowym przeznaczeniu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0e29be55cc048007db21c80bbb08a9d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Czym jest podstawowe przeznaczenie poolera po\u0142\u0105cze\u0144? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e2fbbd440c2781573cb35deeef358f20.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W Postgres przyj\u0119to model procesowy podczas pracy z baz\u0105 danych. Oznacza to, \u017ce jedno po\u0142\u0105czenie to jeden proces, jeden backend Postgresa. A w tym backendzie jest wiele r\u00f3\u017cnych cache\u2019y, kt\u00f3re s\u0105 do\u015b\u0107 kosztowne, gdy s\u0105 zrobione r\u00f3\u017cnie dla r\u00f3\u017cnych po\u0142\u0105cze\u0144. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/587498063b1af8fac4a845961c654bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ponadto w kodzie Postgres znajduje si\u0119 tablica o nazwie procArray. Zawiera ona podstawowe informacje o po\u0142\u0105czeniach sieciowych. A niemal wszystkie algorytmy przetwarzania procArray maj\u0105 liniow\u0105 z\u0142o\u017cono\u015b\u0107, przeszukuj\u0105 ca\u0142\u0105 tablic\u0119 po\u0142\u0105cze\u0144 sieciowych. To do\u015b\u0107 szybka p\u0119tla, ale przy du\u017cej liczbie przychodz\u0105cych po\u0142\u0105cze\u0144 sieciowych staje si\u0119 to nieco dro\u017csze. A gdy wszystko staje si\u0119 troch\u0119 dro\u017csze, w rezultacie mo\u017cna zap\u0142aci\u0107 bardzo wysok\u0105 cen\u0119 za du\u017c\u0105 liczb\u0119 po\u0142\u0105cze\u0144 sieciowych. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b534a38d0bfae7a65fc4258155a50280.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Istniej\u0105 3 mo\u017cliwe podej\u015bcia:<\/p>\n<p><\/p>\n<ul>\n<li>Po stronie aplikacji. <\/li>\n<li>Po stronie bazy danych. <\/li>\n<li>I pomi\u0119dzy nimi, tzn. wszelkie kombinacje. <\/li>\n<\/ul>\n<p><\/p>\n<p>Niestety, wbudowany pooler jest obecnie w fazie rozwoju. Koledzy z firmy PostgreSQL Professional g\u0142\u00f3wnie si\u0119 tym zajmuj\u0105. Kiedy si\u0119 pojawi, ci\u0119\u017cko przewidzie\u0107. W rzeczywisto\u015bci architekt ma do wyboru dwa rozwi\u0105zania: pool po stronie aplikacji oraz proxy pool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/702527a09e9fc86dd39b7fd69dcf1fc9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pool po stronie aplikacji to najprostszy spos\u00f3b. A niemal wszystkie sterowniki klienta oferuj\u0105 spos\u00f3b na przedstawienie milion\u00f3w po\u0142\u0105cze\u0144 w kodzie jako kilkudziesi\u0119ciu po\u0142\u0105cze\u0144 w bazie danych. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7b66b9e20d22f472ca5ac39f6b9e0ba4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pojawia si\u0119 problem, gdy w pewnym momencie chcesz skalowa\u0107 backend, chcesz wdro\u017cy\u0107 go na wielu maszynach wirtualnych. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f216fd7a8c01c2b07891e2242c48b06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Potem zdajesz sobie spraw\u0119, \u017ce masz kilka stref dost\u0119pno\u015bci, kilka centr\u00f3w danych. Podej\u015bcie z klienta side pooling prowadzi do du\u017cych liczb. Du\u017ce to mniej wi\u0119cej 10 000 po\u0142\u0105cze\u0144. To jest maksimum, kt\u00f3re mo\u017ce dzia\u0142a\u0107 w miar\u0119 normalnie. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5bc5f284fd8ff568bbe16c3895b7ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Je\u015bli m\u00f3wimy o proxy poolerach, to s\u0105 dwa poolery, kt\u00f3re maj\u0105 wiele do zaoferowania. To nie tylko poolery. To poolery + dodatkowa \u015bwietna funkcjonalno\u015b\u0107. S\u0105 to <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>Ale niestety, ta dodatkowa funkcjonalno\u015b\u0107 nie wszystkim jest potrzebna. Prowadzi to do tego, \u017ce poolery obs\u0142uguj\u0105 tylko pooling sesji, tzn. jeden przychodz\u0105cy klient, jeden wychodz\u0105cy klient do bazy danych. <\/p>\n<p><\/p>\n<p>Dla naszych potrzeb to nie jest zbyt dobre, dlatego u\u017cywamy PgBouncer, kt\u00f3ry realizuje pooling transakcji, tzn. po\u0142\u0105czenia serwerowe s\u0105 dopasowywane do po\u0142\u0105cze\u0144 klienckich tylko na czas transakcji. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5fedbe14656d2ac2cde8d1878a950e2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I przy naszym obci\u0105\u017ceniu \u2013 to prawda. <strong>Ale pojawia si\u0119 kilka problem\u00f3w.<\/strong>.<img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/61fd36cadcd9948d624dafa711777307.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Problemy zaczynaj\u0105 si\u0119, gdy chcesz zdiagnozowa\u0107 sesj\u0119, poniewa\u017c wszystkie przychodz\u0105ce po\u0142\u0105czenia s\u0105 lokalne. Wszystkie pochodz\u0105 z loopback i w jaki\u015b spos\u00f3b \u015bledzenie sesji staje si\u0119 trudne. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/36108c4956c410a1b1f286a88bc393d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oczywi\u015bcie, mo\u017cesz u\u017cy\u0107 application_name_add_host. To spos\u00f3b po stronie Bouncera, aby doda\u0107 adres IP do application_name. Jednak application_name jest ustawiane dodatkowym po\u0142\u0105czeniem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b4cec483aa776f48db7ad3966c3b78e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na tym wykresie \u017c\u00f3\u0142ta linia reprezentuje rzeczywiste zapytania, a niebieska \u2013 zapytania, kt\u00f3re trafiaj\u0105 do bazy. A ta r\u00f3\u017cnica to w\u0142a\u015bnie ustawienie application_name, kt\u00f3re jest potrzebne tylko do \u015bledzenia, ale wcale nie jest darmowe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c02ea73a6f1a2a4cd6af6c621f321ab4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ponadto w Bouncerze nie mo\u017cna ograniczy\u0107 jednego poola, tzn. liczby po\u0142\u0105cze\u0144 z baz\u0105 danych dla konkretnego u\u017cytkownika, w konkretnej bazie. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3431a463e04106066e2799aead66f571.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Do czego to prowadzi? Masz obci\u0105\u017con\u0105 us\u0142ug\u0119 napisan\u0105 w C++, a gdzie\u015b blisko jest ma\u0142a us\u0142uga na nodzie, kt\u00f3ra nie robi nic szkodliwego z baz\u0105, ale jej sterownik szaleje. Otwiera 20 000 po\u0142\u0105cze\u0144, a wszystko inne musi poczeka\u0107. Tw\u00f3j kod jest nawet poprawny. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d7fa321714dc017b017945dffcf79bc6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oczywi\u015bcie napisali\u015bmy ma\u0142y patch do Bouncera, kt\u00f3ry doda\u0142 to ustawienie, tzn. ograniczenie klient\u00f3w w poolu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d58884fc5ac0f90ff8442f126972157a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mo\u017cna by to zrobi\u0107 po stronie Postgresa, tzn. ograniczy\u0107 role w bazie danych do liczby po\u0142\u0105cze\u0144.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d6ff70db72964ed4eae5eaa47309931.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ale wtedy tracisz mo\u017cliwo\u015b\u0107 zrozumienia, dlaczego nie masz po\u0142\u0105cze\u0144 z serwerem. PgBouncer nie przekazuje b\u0142\u0119du po\u0142\u0105czenia, zawsze zwraca t\u0119 sam\u0105 informacj\u0119. I nie mo\u017cesz zrozumie\u0107: mo\u017ce has\u0142o si\u0119 zmieni\u0142o, mo\u017ce baza po prostu le\u017cy, mo\u017ce co\u015b jest nie tak. Ale brak jakiejkolwiek diagnostyki. Je\u015bli sesja nie mo\u017ce by\u0107 nawi\u0105zana, nie dowiesz si\u0119, dlaczego to si\u0119 nie udaje. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cb3048344a94f2953bf403485d28e69f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W pewnym momencie patrzysz na wykresy aplikacji i widzisz, \u017ce aplikacja nie dzia\u0142a.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e67c6680bb9a7f41242af9f9e4920916.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Patrzysz w top i widzisz, \u017ce Bouncer jest jednow\u0105tkowy. To prze\u0142omowy moment w \u017cyciu us\u0142ugi. Rozumiesz, \u017ce przygotowywa\u0142e\u015b si\u0119 do skalowania bazy danych za p\u00f3\u0142tora roku, a musisz skalowa\u0107 poolera. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4c140c4ba6db19cb9939c1148638fb73.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Doszli\u015bmy do tego, \u017ce potrzebujemy wi\u0119cej PgBouncer\u00f3w. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej 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>Troch\u0119 zapatchowali\u015bmy Bouncera. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/97755489a25ebfe38efd56ff897bd8fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I zrobili\u015bmy tak, \u017ce mo\u017cna uruchomi\u0107 kilka Bouncer\u00f3w z ponownym wykorzystaniem portu TCP. A system operacyjny automatycznie rozk\u0142ada przychodz\u0105ce po\u0142\u0105czenia TCP mi\u0119dzy nimi w spos\u00f3b round-robin.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/ac30d3f067de2a8cd66ad2325c3a3b58.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To jest przejrzyste dla klient\u00f3w, tzn. wszystko wygl\u0105da tak, jakby\u015b mia\u0142 jednego Bouncera, ale masz fragmentacj\u0119 idle-po\u0142\u0105cze\u0144 mi\u0119dzy uruchomionymi Bouncerami. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/53825f075db00b026c12013a610be456.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I w pewnym momencie mo\u017cesz zauwa\u017cy\u0107, \u017ce te 3 Bouncery wykorzystuj\u0105 ka\u017cde swoje rdze\u0144 w 100 %. Potrzebujesz sporo Bouncer\u00f3w. Dlaczego? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/66c17883a043e157cd7ceab2c2a4e326.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poniewa\u017c masz TLS. Masz zaszyfrowane po\u0142\u0105czenie. A je\u015bli benchmarkujesz Postgres z TLS i bez TLS, odkryjesz, \u017ce liczba nawi\u0105zanych po\u0142\u0105cze\u0144 spada prawie o dwa rz\u0119dy przy w\u0142\u0105czeniu szyfrowania, poniewa\u017c handshake TLS zu\u017cywa zasoby procesora. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6101121ebe136af16e5eb1a484c65d66.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na g\u00f3rze mo\u017cesz zobaczy\u0107 do\u015b\u0107 du\u017co funkcji kryptograficznych, kt\u00f3re s\u0105 wykonywane podczas fali przychodz\u0105cych po\u0142\u0105cze\u0144. Poniewa\u017c nasz primary mo\u017ce si\u0119 prze\u0142\u0105cza\u0107 mi\u0119dzy strefami dost\u0119pno\u015bci, fala przychodz\u0105cych po\u0142\u0105cze\u0144 to do\u015b\u0107 typowa sytuacja. To znaczy, z jakiego\u015b powodu stary primary by\u0142 niedost\u0119pny, ca\u0142a obci\u0105\u017cenie zosta\u0142o wys\u0142ane do innego centrum danych. Wszystkie one przyb\u0119d\u0105 jednocze\u015bnie, aby przywita\u0107 si\u0119 z TLS. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c238ac2f511568590dc275e01c192c00.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A du\u017ca liczba handshake TLS mo\u017ce nie przywita\u0107 si\u0119 z Bouncerem, a zatyka\u0107 mu gard\u0142o. Z powodu timeoutu fala przychodz\u0105cych po\u0142\u0105cze\u0144 mo\u017ce sta\u0107 si\u0119 nie wygasaj\u0105c\u0105. Je\u015bli masz retry w bazie bez exponential backoff, nie b\u0119d\u0105 one przychodzi\u0107 z powrotem w sp\u00f3jnym strumieniu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f42d0b210174d4d172254603ae6b834a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oto przyk\u0142ad 16 PgBouncer\u00f3w, kt\u00f3re obci\u0105\u017caj\u0105 16 rdzeni w 100 %<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d048d3774c09e5b6a3fb3c7bff62084.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Doszli\u015bmy do kaskadowego PgBouncer. To najlepsza konfiguracja, jak\u0105 mo\u017cna osi\u0105gn\u0105\u0107 przy naszym obci\u0105\u017ceniu z Bouncerem. Zewn\u0119trzne Bouncery s\u0142u\u017c\u0105 do handshake TCP, a wewn\u0119trzne Bouncery do rzeczywistego pooling, aby nie fragmentowa\u0107 zbytnio zewn\u0119trznych po\u0142\u0105cze\u0144.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3a4ee4ea46d5fe8479a5a7222ee134da.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W takiej konfiguracji mo\u017cliwy jest p\u0142ynny restart. Mo\u017cna restartowa\u0107 wszystkie te 18 Bouncer\u00f3w po jednym. Ale utrzymanie takiej konfiguracji jest do\u015b\u0107 trudne. Administratorzy system\u00f3w, DevOps i ludzie, kt\u00f3rzy naprawd\u0119 odpowiadaj\u0105 za ten serwer, nie b\u0119d\u0105 zbyt zadowoleni z tego schematu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/5291fe67dbe02036f3ff8e98bdd84d1b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wydaje si\u0119, \u017ce mo\u017cna wszystkie nasze poprawki wprowadza\u0107 do open source, ale Bouncer nie jest zbyt dobrze wspierany. Na przyk\u0142ad mo\u017cliwo\u015b\u0107 uruchomienia kilku PgBouncer\u00f3w na tym samym porcie zosta\u0142a skomitowana miesi\u0105c temu. A pull request z t\u0105 funkcjonalno\u015bci\u0105 by\u0142 kilka lat temu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej 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>Albo inny przyk\u0142ad. W Postgres mo\u017cesz anulowa\u0107 bie\u017c\u0105ce zapytanie, wysy\u0142aj\u0105c sekretny kod przez inne po\u0142\u0105czenie bez dodatkowej autoryzacji. Jednak niekt\u00f3rzy klienci po prostu wysy\u0142aj\u0105 TCP-reset, tzn. przerywaj\u0105 po\u0142\u0105czenie sieciowe. Co wtedy zrobi Bouncer? Nic nie zrobi. Nadal b\u0119dzie wykonywa\u0142 zapytanie. Je\u015bli masz ogromn\u0105 liczb\u0119 po\u0142\u0105cze\u0144, kt\u00f3re ma\u0142ymi zapytaniami obci\u0105\u017caj\u0105 baz\u0119, to samo od\u0142\u0105czenie od Bouncera nie wystarczy, trzeba te\u017c zako\u0144czy\u0107 te zapytania, kt\u00f3re s\u0105 wykonywane w bazie. <\/p>\n<p><\/p>\n<p>To zosta\u0142o za\u0142atane, a problem nadal nie zosta\u0142 w\u0142\u0105czony do upstream Bouncera. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a9695b6d9e640a5543dc73429eb0050b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I tak doszli\u015bmy do wniosku, \u017ce potrzebujemy w\u0142asnego connection poolera, kt\u00f3ry b\u0119dzie si\u0119 rozwija\u0142, patchowa\u0142, w kt\u00f3rym b\u0119dzie mo\u017cna szybko naprawia\u0107 problemy i kt\u00f3ry, oczywi\u015bcie, musi by\u0107 wielow\u0105tkowy. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e755cd9b06a004f0eced1dc12fd3a6fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wielow\u0105tkowo\u015b\u0107 postawili\u015bmy jako g\u0142\u00f3wne zadanie. Musimy dobrze radzi\u0107 sobie z fal\u0105 nadchodz\u0105cych po\u0142\u0105cze\u0144 TLS. <\/p>\n<p><\/p>\n<p>W tym celu musieli\u015bmy opracowa\u0107 oddzieln\u0105 bibliotek\u0119 o nazwie Machinarium, kt\u00f3ra s\u0142u\u017cy do opisywania stan\u00f3w maszynowych po\u0142\u0105czenia sieciowego jako sekwencyjnego kodu. Je\u015bli spojrzysz w kod \u017ar\u00f3d\u0142owy libpq, zobaczysz do\u015b\u0107 skomplikowane wywo\u0142ania, kt\u00f3re mog\u0105 zwr\u00f3ci\u0107 wynik i powiedzie\u0107: \u201eWywo\u0142aj mnie troch\u0119 p\u00f3\u017aniej. Teraz mam IO, ale kiedy IO si\u0119 zako\u0144czy, b\u0119d\u0119 mia\u0142 obci\u0105\u017cenie procesora\u201d. I to jest schemat wielowarstwowy. Komunikacj\u0119 sieciow\u0105 zazwyczaj opisuje si\u0119 jako maszyn\u0119 stan\u00f3w. Zestawem regu\u0142 typu \u201eje\u015bli wcze\u015bniej otrzyma\u0142em nag\u0142\u00f3wek pakietu o rozmiarze N, to teraz czekam na N bajt\u00f3w\u201d, \u201eje\u015bli wysy\u0142a\u0142em pakiet SYNC, to teraz czekam na pakiet z metadanymi wyniku\u201d. Okazuje si\u0119, \u017ce to do\u015b\u0107 trudny i nieintuicyjny kod, jakby labirynt przekszta\u0142cono w jednoodcinkowe rozwini\u0119cie. Zrobili\u015bmy tak, \u017ce zamiast maszyny stan\u00f3w programista opisuje g\u0142\u00f3wn\u0105 \u015bcie\u017ck\u0119 komunikacji jako zwyk\u0142y kod imperatywny. Po prostu w tym kodzie imperatywnym trzeba wstawi\u0107 miejsca, w kt\u00f3rych sekwencj\u0119 wykonywania nale\u017cy przerwa\u0107, czekaj\u0105c na dane z sieci, przekazuj\u0105c kontekst wykonania innej korutynie (green thread). To podej\u015bcie jest podobne do tego, \u017ce najpierw zapisujemy najoczywistsz\u0105 \u015bcie\u017ck\u0119 w labiryncie, a potem dodajemy do niej odga\u0142\u0119zienia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a6bfb4b11961c7db3a7c7184674e3bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W efekcie mamy jeden w\u0105tek, kt\u00f3ry wykonuje akceptacj\u0119 TCP i przekazuje po\u0142\u0105czenia TPC pomi\u0119dzy wieloma pracownikami w systemie round-robin. <\/p>\n<p><\/p>\n<p>Ka\u017cde po\u0142\u0105czenie z klientem dzia\u0142a zawsze na jednym procesorze, co czyni je przyjaznym dla pami\u0119ci cache. <\/p>\n<p><\/p>\n<p>Dodatkowo, opracowali\u015bmy drobne poprawki w zbieraniu ma\u0142ych pakiet\u00f3w w jeden du\u017cy, aby odci\u0105\u017cy\u0107 systemowy stos TCP.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7d740c23baecdd2f993c83cd54a0a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ponadto, poprawili\u015bmy pulowanie transakcji, w ten spos\u00f3b, \u017ce przy odpowiedniej konfiguracji, Odyssey mo\u017ce wys\u0142a\u0107 CANCEL i ROLLBACK w przypadku utraty po\u0142\u0105czenia sieciowego, tj. je\u015bli \u017caden proces nie oczekuje na zapytanie, Odyssey poinformuje baz\u0119 danych, aby nie pr\u00f3bowa\u0142a wykona\u0107 zapytania, kt\u00f3re mog\u0142oby zu\u017cywa\u0107 cenne zasoby.<\/p>\n<p><\/p>\n<p>W miar\u0119 mo\u017cliwo\u015bci staramy si\u0119 utrzymywa\u0107 po\u0142\u0105czenia z tym samym klientem, co pozwala unikn\u0105\u0107 ponownej konfiguracji application_name_add_host. Je\u015bli to mo\u017cliwe, nie ma dodatkowej konieczno\u015bci zmiany parametr\u00f3w, kt\u00f3re s\u0105 potrzebne do diagnozowania. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/afb2fb7fb16d65c9ea73a8978d1eb83c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dzia\u0142amy w interesach Yandex.Cloud. Je\u015bli korzystasz z managed PostgreSQL i masz zainstalowany connection pooler, mo\u017cesz utworzy\u0107 replikacj\u0119 logiczn\u0105 na zewn\u0105trz, co oznacza, \u017ce mo\u017cesz odej\u015b\u0107 od nas, je\u015bli zechcesz, za pomoc\u0105 replikacji logicznej. Bouncer nie przeka\u017ce strumienia replikacji logicznej na zewn\u0105trz. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c53defc92ebd8f3bec57ce64d97b9f72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To przyk\u0142ad konfiguracji replikacji logicznej. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a37d9d1abf288d17fa646b642e8b62ab.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ponadto, mamy wsparcie dla replikacji fizycznej na zewn\u0105trz. W chmurze jest to oczywi\u015bcie niemo\u017cliwe, poniewa\u017c klaster przeka\u017ce zbyt wiele informacji o sobie. Jednak w twoich instalacjach, je\u015bli potrzebujesz fizycznej replikacji przez connection pooler w Odyssey, jest to mo\u017cliwe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/572934ce5b08115e57ab4b55d2153c6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W Odyssey mamy w pe\u0142ni kompatybilne monitorowanie z PgBouncer. Mamy tak\u0105 sam\u0105 konsol\u0119, kt\u00f3ra wykonuje prawie wszystkie te same polecenia. Je\u015bli czego\u015b brakuje, prze\u015blij pull request lub przynajmniej zg\u0142o\u015b problem na GitHubie, a my dodamy potrzebne komendy. Jednak g\u0142\u00f3wna funkcjonalno\u015b\u0107 konsoli PgBouncer jest ju\u017c w pe\u0142ni dost\u0119pna. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/451dd798fb3523a7a174ebfe00a14bc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oczywi\u015bcie, mamy r\u00f3wnie\u017c przekazywanie b\u0142\u0119d\u00f3w. Zwr\u00f3cimy ten b\u0142\u0105d, kt\u00f3ry zg\u0142osi\u0142a baza. Otrzymasz informacj\u0119, dlaczego nie mo\u017cesz po\u0142\u0105czy\u0107 si\u0119 z baz\u0105, a nie tylko, \u017ce si\u0119 nie \u0142\u0105czysz. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/14b4cb0efa33a2658dfc528349a5382f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ta funkcjonalno\u015b\u0107 mo\u017ce by\u0107 wy\u0142\u0105czona, je\u015bli potrzebujesz 100% zgodno\u015bci z PgBouncer. Mo\u017cemy zachowywa\u0107 si\u0119 tak samo jak Bouncer, na wszelki wypadek. <\/p>\n<p><\/p>\n<p><strong>Rozw\u00f3j<\/strong><\/p>\n<p><\/p>\n<p>Kilka s\u0142\u00f3w o kodzie \u017ar\u00f3d\u0142owym Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej 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 przyk\u0142ad, s\u0105 komendy \u201ePause \/ Resume\u201d. Zwykle s\u0105 one u\u017cywane do aktualizacji bazy danych. Je\u015bli musisz zaktualizowa\u0107 Postgresa, mo\u017cesz wstrzyma\u0107 go w po\u0142\u0105czeniu pooler, wykona\u0107 pg_upgrade, a nast\u0119pnie wznowi\u0107. I po stronie klienta b\u0119dzie to wygl\u0105da\u0107 tak, jakby baza po prostu spowolni\u0142a. T\u0119 funkcjonalno\u015b\u0107 dostarczyli nam ludzie ze spo\u0142eczno\u015bci. Nie zosta\u0142a jeszcze scalona, ale wkr\u00f3tce wszystko b\u0119dzie. (Ju\u017c scalono)<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej 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 ju\u017c scalono<\/p>\n<p><\/p>\n<p>Ponadto jedn\u0105 z nowych funkcji w PgBouncer jest wsparcie dla uwierzytelniania SCRAM, kt\u00f3re r\u00f3wnie\u017c przyni\u00f3s\u0142 nam kto\u015b, kto nie pracuje w Yandex.Cloud. Oba s\u0105 skomplikowan\u0105 funkcjonalno\u015bci\u0105 i wa\u017cne. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f39346a543c88d17728233d05c2dff19.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dlatego chcia\u0142bym opowiedzie\u0107, z czego zrobiony jest Odyssey, mo\u017ce tak\u017ce chcecie chwil\u0119 napisa\u0107 kod. <\/p>\n<p><\/p>\n<p>Macie baz\u0119 \u017ar\u00f3d\u0142ow\u0105 Odyssey, kt\u00f3ra opiera si\u0119 na dw\u00f3ch g\u0142\u00f3wnych bibliotekach. Biblioteka Kiwi to realizacja protoko\u0142u komunikacyjnego Postgresa. Tzn. natywny proto 3 w Postgresie to standardowe wiadomo\u015bci, kt\u00f3re frontend i backend mog\u0105 wymienia\u0107. Zosta\u0142y one zaimplementowane w bibliotece Kiwi.<\/p>\n<p><\/p>\n<p>Biblioteka Machinarium to biblioteka realizacji w\u0105tk\u00f3w. Ma\u0142y fragment tego Machinarium zosta\u0142 napisany w assemblerze. Ale nie martwcie si\u0119, jest tam tylko 15 wierszy. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd18f250af50eabd53536b2c0d7f12b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Architektura Odyssey. Jest g\u0142\u00f3wna maszyna, w kt\u00f3rej uruchomione s\u0105 coroutines. W tej maszynie realizowane s\u0105 akceptacje przychodz\u0105cych po\u0142\u0105cze\u0144 TCP i ich rozdzielanie na worker\u00f3w. <\/p>\n<p><\/p>\n<p>Wewn\u0105trz jednego workera mo\u017ce pracowa\u0107 handler kilku klient\u00f3w. A tak\u017ce w g\u0142\u00f3wnym w\u0105tku dzia\u0142aj\u0105 konsola i przetwarzanie zada\u0144 crone do usuwania po\u0142\u0105cze\u0144, kt\u00f3re ju\u017c nie s\u0105 potrzebne w pool.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7072fb20f406f2ee5788542860ccdf50.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Do testowania Odyssey u\u017cywa si\u0119 standardowego zestawu test\u00f3w Postgresa. Po prostu uruchamiamy install-check przez Bouncera i przez Odyssey, uzyskuj\u0105c zerowy div. Kilka test\u00f3w zwi\u0105zanych z formatowaniem dat nie przechodzi w og\u00f3le w Bouncerze i Odyssey identycznie.<\/p>\n<p><\/p>\n<p>Ponadto istnieje wiele sterownik\u00f3w, kt\u00f3re maj\u0105 w\u0142asne testy. I u\u017cywamy ich test\u00f3w do testowania Odyssey.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/fb01cc9a0e9724ddcd3cc3d088afb182.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dodatkowo, z powodu naszej kaskadowej konfiguracji, musimy testowa\u0107 r\u00f3\u017cne kombinacje: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey, aby by\u0107 pewnymi, \u017ce je\u015bli Odyssey znajdzie si\u0119 w kt\u00f3rejkolwiek z cz\u0119\u015bci w kaskadzie, r\u00f3wnie\u017c b\u0119dzie dzia\u0142a\u0142 tak, jak oczekujemy. <\/p>\n<p><\/p>\n<p><strong>Grapple<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/25855b691180bca083025b9e8b611c09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U\u017cywamy Odyssey w produkcji. Nie by\u0142oby uczciwie powiedzie\u0107, \u017ce wszystko po prostu dzia\u0142a. Tak, to prawda, ale nie zawsze. Na przyk\u0142ad w produkcji wszystko dzia\u0142a\u0142o, a\u017c nasi przyjaciele z PostgreSQL Professional powiedzieli, \u017ce mamy wyciek pami\u0119ci. Rzeczywi\u015bcie tak by\u0142o, naprawili\u015bmy to. Ale to by\u0142o dla nas zaskoczeniem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e638d88397b32b1ca0b74c9c1b905f81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Potem odkryli\u015bmy, \u017ce w connection pooler s\u0105 przychodz\u0105ce i wychodz\u0105ce po\u0142\u0105czenia TLS. I w tych po\u0142\u0105czeniach potrzebne s\u0105 certyfikaty klienta i certyfikaty serwera.<\/p>\n<p><\/p>\n<p>Certyfikaty serwera Bouncer i Odyssey odczytuj\u0105 swoje pcache, ale certyfikaty klienta nie musz\u0105 by\u0107 odczytywane z pcache, poniewa\u017c nasz skalowalny Odyssey ostatecznie napotyka na wydajno\u015b\u0107 systemu zwi\u0105zane z odczytem tych certyfikat\u00f3w. To by\u0142o dla nas zaskoczeniem, poniewa\u017c napotka\u0142 ten problem dopiero po pewnym czasie. Najpierw skalowa\u0142 si\u0119 liniowo, a po 20 000 jednoczesnych po\u0142\u0105cze\u0144 przychodz\u0105cych ten problem si\u0119 ujawni\u0142.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6cff094cd59a990e448b82fa0b1572b7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metoda uwierzytelniania Pluggable Authentication Method to mo\u017cliwo\u015b\u0107 uwierzytelnienia przy u\u017cyciu wbudowanych \u015brodk\u00f3w linuksowych. W PgBouncer zrealizowano to w taki spos\u00f3b, \u017ce jest osobny w\u0105tek na oczekiwanie na odpowied\u017a od PAM oraz g\u0142\u00f3wny w\u0105tek PgBouncer, kt\u00f3ry obs\u0142uguje bie\u017c\u0105ce po\u0142\u0105czenie i mo\u017ce poprosi\u0107 je o pozostanie w w\u0105tku PAM. <\/p>\n<p><\/p>\n<p>Nie zdecydowali\u015bmy si\u0119 na to z jednego prostego powodu. Mamy przecie\u017c wiele w\u0105tk\u00f3w. Po co nam to potrzebne?<\/p>\n<p><\/p>\n<p>W efekcie mo\u017ce to powodowa\u0107 problemy, poniewa\u017c je\u017celi masz uwierzytelnianie PAM i nie-PAM, to du\u017ca fala uwierzytelnie\u0144 PAM mo\u017ce znacznie op\u00f3\u017ania\u0107 uwierzytelnianie nie-PAM. To jedna z rzeczy, kt\u00f3rych nie naprawili\u015bmy. Ale je\u015bli chcesz to naprawi\u0107, mo\u017cesz si\u0119 tym zaj\u0105\u0107. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c7bd9e9980ff7298b30a59c130f03dbb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kolejnym problemem by\u0142o to, \u017ce mamy jeden w\u0105tek, kt\u00f3ry akceptuje wszystkie przychodz\u0105ce po\u0142\u0105czenia. A nast\u0119pnie przekazuje je do puli roboczej, gdzie odbywa si\u0119 zestawienie TLS.<\/p>\n<p><\/p>\n<p>W efekcie, je\u015bli masz sp\u00f3jn\u0105 fal\u0119 20 000 po\u0142\u0105cze\u0144 sieciowych, wszystkie zostan\u0105 zaakceptowane. A po stronie klienta libpq rozpocznie odliczanie limit\u00f3w czasowych. Domy\u015blnie wydaje si\u0119, \u017ce jest tam ustawione 3 sekundy. <\/p>\n<p><\/p>\n<p>Je\u015bli nie mog\u0105 jednocze\u015bnie wej\u015b\u0107 do bazy, to nie mog\u0105 wej\u015b\u0107 do bazy, poniewa\u017c wszystko to mo\u017ce by\u0107 pokryte nieeksponencjalnym ponownym pr\u00f3b\u0105. <\/p>\n<p><\/p>\n<p>Doszli\u015bmy do tego, \u017ce skopiowali\u015bmy tutaj schemat z PgBouncer, w kt\u00f3rym mamy throttling liczby po\u0142\u0105cze\u0144 TCP, kt\u00f3re akceptujemy. <\/p>\n<p><\/p>\n<p>Je\u015bli zauwa\u017cymy, \u017ce akceptujemy po\u0142\u0105czenia, a one ostatecznie nie zd\u0105\u017caj\u0105 si\u0119 zestawi\u0107, umieszczamy je w kolejce, aby nie zu\u017cywa\u0142y zasob\u00f3w procesora centralnego. To prowadzi do sytuacji, \u017ce jednoczesne zestawienie mo\u017ce by\u0107 realizowane nie dla wszystkich po\u0142\u0105cze\u0144, kt\u00f3re przyby\u0142y. Ale przynajmniej kto\u015b wejdzie do bazy, nawet je\u015bli obci\u0105\u017cenie jest do\u015b\u0107 du\u017ce.<\/p>\n<p><\/p>\n<p><strong>map\u0119<\/strong><\/p>\n<p><\/p>\n<p>Czego chcieliby\u015bmy zobaczy\u0107 w przysz\u0142o\u015bci w Odyssey? Co jeste\u015bmy gotowi opracowa\u0107 sami, a czego oczekujemy od spo\u0142eczno\u015bci?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4719437d80b33efc3da6572af9a4dedb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Na sierpie\u0144 2019 roku.<\/strong><\/p>\n<p><\/p>\n<p>Tak wygl\u0105da\u0142 roadmap Odyssey w sierpniu:<\/p>\n<p><\/p>\n<ul>\n<li>Chcieli\u015bmy uwierzytelniania SCRAM i PAM.<\/li>\n<li>Chcieli\u015bmy przesy\u0142a\u0107 zapytania tylko do odczytu na standby. <\/li>\n<li>Chcieliby\u015bmy mo\u017cliwo\u015bci restartu online. <\/li>\n<li>I mo\u017cliwo\u015b\u0107 wstrzymania serwera. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/455c92f92df826257c2c57dc2b034e22.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Po\u0142owa tego roadmapu zosta\u0142a zrealizowana, i to nie przez nas. I to jest dobre. Dlatego porozmawiajmy o tym, co pozosta\u0142o i dodajmy wi\u0119cej. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej 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\">Je\u015bli chodzi o przesy\u0142anie zapyta\u0144 tylko do odczytu do 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: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0873cffd4f1ae15d9ffa6d080671051b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W zasadzie w Postgres, pocz\u0105wszy od wersji 10, istnieje mo\u017cliwo\u015b\u0107 wskazania session_attrs podczas \u0142\u0105czenia. Mo\u017cecie w po\u0142\u0105czeniu wymieni\u0107 wszystkie hosty baz danych i okre\u015bli\u0107, dlaczego idziecie do bazy danych: aby zapisa\u0107 lub tylko przeczyta\u0107. I sterownik sam wybierze pierwszy z listy host, kt\u00f3ry bardziej mu odpowiada i spe\u0142nia wymagania session_attrs. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0693d1327fe5826502a01c21d05d5b4c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jednak problem z tym podej\u015bciem polega na tym, \u017ce nie kontroluje ono op\u00f3\u017anienia replikacji. Mo\u017cecie mie\u0107 jak\u0105\u015b replik\u0119, kt\u00f3ra jest sp\u00f3\u017aniona o czas niedopuszczalny dla waszej us\u0142ugi. Aby umo\u017cliwi\u0107 pe\u0142nofunkcyjne wykonanie zapyta\u0144 do odczytu na replicie, w zasadzie musimy wspiera\u0107 w Odyssey mo\u017cliwo\u015b\u0107 niepracy, gdy nie mo\u017cna czyta\u0107. <\/p>\n<p><\/p>\n<p>Odyssey powinien czasami wchodzi\u0107 do bazy i pyta\u0107 o odleg\u0142o\u015b\u0107 replikacji od primary. I je\u015bli osi\u0105gnie ona maksymaln\u0105 warto\u015b\u0107, nowe zapytania do bazy nie powinny by\u0107 akceptowane, a klientowi nale\u017cy powiedzie\u0107, \u017ce musi ponownie zainicjowa\u0107 po\u0142\u0105czenia i ewentualnie wybra\u0107 inny host do wykonania zapyta\u0144. To pozwoli bazie szybciej przywr\u00f3ci\u0107 op\u00f3\u017anienie replikacji i ponownie wr\u00f3ci\u0107 do odpowiedzi na zapytania. <\/p>\n<p><\/p>\n<p>Trudno jest okre\u015bli\u0107 terminy realizacji, poniewa\u017c to open source. Ale mam nadziej\u0119, \u017ce nie zajmie to 2,5 roku, jak u koleg\u00f3w z PgBouncer. Chcia\u0142bym zobaczy\u0107 t\u0119 funkcj\u0119 w Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej 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\">W spo\u0142eczno\u015bci ludzie pytali o wsparcie dla prepared statement.<\/a><\/noindex>Obecnie mo\u017cesz utworzy\u0107 prepared statement na dwa sposoby. Po pierwsze, mo\u017cesz wykona\u0107 polecenie SQL, a mianowicie \u201eprepared\u201d. Aby zrozumie\u0107 to polecenie SQL, musimy nauczy\u0107 si\u0119 rozumie\u0107 SQL po stronie Bouncer. By\u0142oby to overkill, poniewa\u017c potrzebujemy kompletny parser. Nie mo\u017cemy analizowa\u0107 ka\u017cdego polecenia SQL. <\/p>\n<p><\/p>\n<p>Jednak istnieje prepared statement na poziomie protoko\u0142u wiadomo\u015bci w proto3. I to jest to miejsce, w kt\u00f3rym informacja o tym, \u017ce tworzony jest prepared statement, przychodzi w ustrukturyzowanej formie. Mogliby\u015bmy wspiera\u0107 zrozumienie, \u017ce na jakim\u015b po\u0142\u0105czeniu serwera klient poprosi\u0142 o utworzenie prepared statements. I nawet je\u015bli transakcja si\u0119 zako\u0144czy\u0142a, nadal musimy zachowa\u0107 sp\u00f3jno\u015b\u0107 serwera i klienta. <\/p>\n<p><\/p>\n<p>Ale tutaj pojawia si\u0119 rozbie\u017cno\u015b\u0107 w dialogu, poniewa\u017c kto\u015b m\u00f3wi o potrzebie zrozumienia, kt\u00f3re dok\u0142adnie prepared statements utworzy\u0142 klient i rozdzielenia po\u0142\u0105czenia serwera mi\u0119dzy wszystkimi klientami, kt\u00f3rzy utworzyli to po\u0142\u0105czenie serwera, tzn. kt\u00f3rzy stworzyli taki prepared statement. <\/p>\n<p><\/p>\n<p>Andres Freund powiedzia\u0142, \u017ce je\u015bli pojawi si\u0119 klient, kt\u00f3ry ju\u017c tworzy\u0142 taki prepared statement w innym po\u0142\u0105czeniu serwera, to stw\u00f3rz go za niego. Ale wydaje si\u0119, \u017ce nieco niew\u0142a\u015bciwie jest wykonywa\u0107 zapytania w bazie zamiast klienta, ale z punktu widzenia programisty, kt\u00f3ry pisze protok\u00f3\u0142 interakcji z baz\u0105, by\u0142oby wygodne, gdyby po prostu dano mu po\u0142\u0105czenie sieciowe, w kt\u00f3rym znajduje si\u0119 takie przygotowane zapytanie. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd56b3ad015195d86a64e52be365b16a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I jeszcze jedna funkcja, kt\u00f3r\u0105 musimy zaimplementowa\u0107. Obecnie mamy monitorowanie kompatybilne z PgBouncer. Mo\u017cemy zwr\u00f3ci\u0107 \u015bredni czas wykonania zapytania. Ale \u015bredni czas to \u015brednia temperatura w szpitalu: kto\u015b zimny, kto\u015b ciep\u0142y \u2013 \u015brednio wszyscy s\u0105 zdrowi. To nieprawda. <\/p>\n<p><\/p>\n<p>Musimy zaimplementowa\u0107 wsparcie dla percentyli, kt\u00f3re wskazywa\u0142yby, \u017ce istniej\u0105 wolne zapytania, kt\u00f3re zu\u017cywaj\u0105 zasoby, i uczyni\u0142yby monitorowanie bardziej akceptowalnym. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6f285f3eb0d79e7f25d42f0e792b85b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Najwa\u017cniejsze \u2013 chcemy wersj\u0119 1.0 (Ju\u017c wydano wersj\u0119 1.1). Faktem jest, \u017ce obecnie Odyssey znajduje si\u0119 w wersji 1.0rc, tzn. release candidate. I wszystkie problemy, kt\u00f3re wymieni\u0142em, zosta\u0142y naprawione w tej wersji, z wyj\u0105tkiem wycieku pami\u0119ci. <\/p>\n<p><\/p>\n<p>Co dla nas oznacza wersja 1.0? Wdra\u017camy Odyssey na nasze bazy. Ju\u017c teraz dzia\u0142a na naszych bazach, ale kiedy osi\u0105gnie punkt 1 000 000 zapyta\u0144 na sekund\u0119, b\u0119dziemy mogli powiedzie\u0107, \u017ce to jest wersja produkcyjna, a ta wersja to 1.0. <\/p>\n<p><\/p>\n<p>Niekt\u00f3rzy w spo\u0142eczno\u015bci poprosili o dodanie pauzy i SCRAM w wersji 1.0. Ale to oznacza, \u017ce b\u0119dziemy musieli wdro\u017cy\u0107 ju\u017c nast\u0119pn\u0105 wersj\u0119 w produkcji, poniewa\u017c ani SCRAM, ani pauza nie zosta\u0142y jeszcze po\u0142\u0105czone. Ale najprawdopodobniej ten problem zostanie do\u015b\u0107 szybko rozwi\u0105zany. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Odyssey roadmap: czego jeszcze oczekujemy od \u0142\u0105cznika po\u0142\u0105cze\u0144. Andriej Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/2f50de9f51f653a7396965239bd545e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Czekam na wasze zg\u0142oszenia pull request. I chcia\u0142bym r\u00f3wnie\u017c us\u0142ysze\u0107, jakie macie problemy z Bouncer. Porozmawiajmy o tym. Mo\u017ce uda nam si\u0119 zrealizowa\u0107 jakie\u015b funkcje, kt\u00f3re s\u0105 dla was potrzebne. <\/p>\n<p><\/p>\n<p>Na tym ko\u0144cz\u0119 swoj\u0105 cz\u0119\u015b\u0107, chcia\u0142bym us\u0142ysze\u0107 was. Dzi\u0119kuj\u0119!<\/p>\n<p><\/p>\n<p>Pytania<\/p>\n<p><\/p>\n<p><em>Je\u015bli ustawi\u0119 application_name, b\u0119dzie poprawnie przekazywane, w tym do transaction pooling w Odyssey?<\/em><\/p>\n<p><\/p>\n<p>W Odyssey czy w Bouncer?<\/p>\n<p><\/p>\n<p><em>W Odyssey. W Bouncer jest przekazywane.<\/em> <\/p>\n<p><\/p>\n<p>Zestaw zrobimy. <\/p>\n<p><\/p>\n<p><em>A je\u015bli moje rzeczywiste po\u0142\u0105czenie b\u0119dzie skaka\u0107 pomi\u0119dzy innymi po\u0142\u0105czeniami, to b\u0119dzie przekazywane?<\/em><\/p>\n<p><\/p>\n<p>Zrobimy zestaw wszystkich parametr\u00f3w wymienionych na li\u015bcie. Nie mog\u0119 powiedzie\u0107, czy w tej li\u015bcie znajduje si\u0119 application_name. Wydaje mi si\u0119, \u017ce go tam widzia\u0142em. Ustawimy wszystkie te same parametry. Jednym zapytaniem przekazuje wszystko to, co zosta\u0142o ustawione przez klienta przy uruchamianiu. <\/p>\n<p><\/p>\n<p><em>Dzi\u0119kuj\u0119, Andrieju, za referat! Dobry referat! Ciesz\u0119 si\u0119, \u017ce Odyssey rozwija si\u0119 coraz szybciej z ka\u017cd\u0105 chwil\u0105. \u017bycz\u0119 dalszych sukces\u00f3w. Ju\u017c zwracali\u015bmy si\u0119 do was z pro\u015bb\u0105 o posiadanie multi data-source po\u0142\u0105czenia, aby Odyssey mog\u0142o \u0142\u0105czy\u0107 si\u0119 jednocze\u015bnie z r\u00f3\u017cnymi bazami danych, tzn. master slave, a potem automatycznie po failover \u0142\u0105czy\u0107 si\u0119 z nowym masterem.<\/em> <\/p>\n<p><\/p>\n<p>Tak, zdaje si\u0119, \u017ce przypominam sobie t\u0119 dyskusj\u0119. Obecnie istnieje kilka magazyn\u00f3w. Ale nie ma prze\u0142\u0105czania mi\u0119dzy nimi. Musimy z naszej strony pyta\u0107 serwer, czy jeszcze \u017cyje i zrozumie\u0107, \u017ce nast\u0105pi\u0142 failover, kto wywo\u0142a pg_recovery. Mam standardowy spos\u00f3b, \u017ceby sprawdzi\u0107, \u017ce nie dotarli\u015bmy do mastera. I musimy jako\u015b zrozumie\u0107 z b\u0142\u0119d\u00f3w, czy nie? To znaczy, pomys\u0142 jest interesuj\u0105cy, jest omawiany. Piszecie wi\u0119cej komentarzy. Je\u015bli macie pracownik\u00f3w, kt\u00f3rzy znaj\u0105 C, to wspaniale. <\/p>\n<p><\/p>\n<p>Kwestia skalowania replikami r\u00f3wnie\u017c nas interesuje, poniewa\u017c chcemy, aby przyj\u0119cie replikowanych klastr\u00f3w by\u0142o jak najprostsze dla programist\u00f3w aplikacji. Chcieliby\u015bmy jednak us\u0142ysze\u0107 wi\u0119cej komentarzy, tzn. jak dok\u0142adnie to zrobi\u0107 oraz jak to zrobi\u0107 dobrze. <\/p>\n<p><\/p>\n<p><em>Kwestia dotycz\u0105ca replik. Macie wi\u0119c jeden master i kilka replik. Oczywi\u015bcie, \u017ce do replik zagl\u0105da si\u0119 rzadziej ni\u017c do mastera, poniewa\u017c mog\u0105 wyst\u0119powa\u0107 r\u00f3\u017cnice. M\u00f3wili\u015bcie, \u017ce r\u00f3\u017cnice w danych mog\u0105 by\u0107 takie, \u017ce mog\u0105 nie odpowiada\u0107 waszym potrzebom biznesowym i nie b\u0119dziecie do nich zagl\u0105da\u0107, dop\u00f3ki nie zostan\u0105 zreplikowane. Je\u015bli za\u015b d\u0142ugo ich nie odwiedzali\u015bcie, a potem zaczniecie, to te dane, kt\u00f3re s\u0105 potrzebne, nie b\u0119d\u0105 natychmiast dost\u0119pne. To znaczy, \u017ce je\u015bli non stop korzystamy z mastera, to tam cache jest nagrzany, a w replice cache jest nieco op\u00f3\u017aniony.<\/em> <\/p>\n<p><\/p>\n<p>Tak, to prawda. W pcache nie b\u0119d\u0105 znajdowa\u0142y si\u0119 bloki danych, kt\u00f3rych chcecie, w real cache nie b\u0119dzie informacji o tabelach, kt\u00f3rych chcecie, w planach nie b\u0119dzie sparsowanych zapyta\u0144, w og\u00f3le nic nie b\u0119dzie. <\/p>\n<p><\/p>\n<p><em>A kiedy macie jaki\u015b klaster i dodajecie do niego now\u0105 replik\u0119, to p\u00f3ki si\u0119 uruchamia, wszystko jest w niej \u017ale, tzn. nawi\u0105zuje swoj\u0105 pami\u0119\u0107 podr\u0119czn\u0105.<\/em> <\/p>\n<p><\/p>\n<p>Zrozumia\u0142em ide\u0119. Prawid\u0142owym podej\u015bciem by\u0142oby najpierw uruchomi\u0107 ma\u0142y procent zapyta\u0144 na replik\u0119, kt\u00f3re by nagrzewa\u0142y pami\u0119\u0107 podr\u0119czn\u0105. M\u00f3wi\u0105c wprost, mamy warunek, \u017ce nie mo\u017cemy by\u0107 bardziej ni\u017c 10 sekund do ty\u0142u za masterem. I ten warunek wprowadza\u0107 nie jednorazowo, a p\u0142ynnie dla niekt\u00f3rych klient\u00f3w. <\/p>\n<p><\/p>\n<p><em>Tak, zwi\u0119ksza\u0107 ci\u0119\u017car.<\/em><\/p>\n<p><\/p>\n<p>To dobry pomys\u0142. Ale najpierw musimy wdro\u017cy\u0107 t\u0119 mo\u017cliwo\u015b\u0107 wy\u0142\u0105czenia. Najpierw musimy si\u0119 wy\u0142\u0105czy\u0107, a potem pomy\u015blimy, jak si\u0119 w\u0142\u0105czy\u0107. To \u015bwietna funkcja, aby p\u0142ynnie si\u0119 w\u0142\u0105cza\u0107.<\/p>\n<p><\/p>\n<p><em>W nginx jest taka opcja <code>powolne uruchamianie<\/code> w klastrze dla serwera. I stopniowo zwi\u0119ksza obci\u0105\u017cenie.<\/em> <\/p>\n<p><\/p>\n<p>Tak, \u015bwietny pomys\u0142, wypr\u00f3bujemy, kiedy dojdziemy do tego.<\/p>\n<p>\u0179r\u00f3d\u0142o: <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\/pl\/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=\"pl_PL\" \/>\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\/pl\/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: co jeszcze chcemy od puli po\u0142\u0105cze\u0144. Andrey Borodin (2019) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pl\/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":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/96515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=96515"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/96515\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/96516"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=96515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=96515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=96515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}