{"id":31124,"date":"2019-10-31T21:39:36","date_gmt":"2019-10-31T18:39:36","guid":{"rendered":"https:\/\/prohoster.info\/blog\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie\/"},"modified":"2019-10-31T21:39:36","modified_gmt":"2019-10-31T18:39:36","slug":"stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","title":{"rendered":"Gra\u0111evni blokovi distribuiranih aplikacija. Drugo pribli\u017eavanje","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Najava<\/strong><\/p>\n<p><\/p>\n<p><em>Kolege, sredinom ljeta planiram objaviti jo\u0161 jedan niz \u010dlanaka o dizajniranju sustava masovne usluge: \u201cEksperiment VTrade\u201d \u2014 poku\u0161aj pisanja okvira za trgova\u010dke sustave. U nizu \u0107e se razmatrati teorija i praksa izgradnje burze, aukcije i trgovine. Na kraju \u010dlanka predla\u017eem da glasate za teme koje vas najvi\u0161e zanimaju.<br \/>\n<\/em><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gra\u0111evni blokovi distribuiranih aplikacija. Drugo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/358996733e805327b587176f4f992aea.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovo je zavr\u0161ni \u010dlanak niza o distribuiranim reaktivnim aplikacijama na Erlangu\/Elixiru. U <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">prvom \u010dlanku<\/a><\/noindex> mo\u017ee se prona\u0107i teorijska osnova reaktivne arhitekture. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446108\/\">Drugi \u010dlanak<\/a><\/noindex> ilustrira osnovne uzorke i mehanizme izgradnje sli\u010dnih sustava.<\/p>\n<p><\/p>\n<p>Danas \u0107emo razmotriti pitanja razvoja kodne baze i projekata u cjelini. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"organizaciya-servisov\">Organizacija servisa<\/h2>\n<p><\/p>\n<p>U stvarnom \u017eivotu, prilikom razvoja servisa \u010desto je potrebno spojiti nekoliko uzoraka interakcije u jednom kontroleru. Na primjer, servis users, koji rje\u0161ava zadatke upravljanja profilima korisnika projekta, trebao bi odgovarati na zahtjeve req-resp i obavje\u0161tavati o a\u017euriranjima profila putem pub-sub. Ovaj slu\u010daj je prili\u010dno jednostavan: iza messaginga stoji jedan kontroler koji implementira logiku servisa i objavljuje a\u017euriranja.<\/p>\n<p><\/p>\n<p>Situacija se komplikuje kada trebamo realizirati otporan distribuirani servis. Zamislite da su se zahtjevi za users promijenili: <\/p>\n<p><\/p>\n<ol>\n<li>sada servis treba obraditi zahtjeve na 5 \u010dvorova klastera, <\/li>\n<li>imati mogu\u0107nost izvr\u0161avanja pozadinskih zadataka obrade, <\/li>\n<li>kao i imati mogu\u0107nost dinami\u010dkog upravljanja popisima pretplate na a\u017euriranja profila.<\/li>\n<\/ol>\n<p><\/p>\n<p><em>Napomena:<\/em> Pitanje konzistentnog pohranjivanja i replike podataka ne razmatramo. Pretpostavljamo da su ta pitanja ranije rije\u0161ena i da sustav ve\u0107 ima pouzdan i skalabilan sloj pohrane, a procesori imaju mehanizme interakcije s njim.<\/p>\n<p><\/p>\n<p>Formalni opis servisa users postao je slo\u017eeniji. S programerskog stajali\u0161ta, zahvaljuju\u0107i kori\u0161tenju messaginga, promjene su minimalne. Da bismo zadovoljili prvi zahtjev, trebamo postaviti balansiranje na to\u010dki izmjene req-resp. <\/p>\n<p><\/p>\n<p>Zahtev za obradu pozadinskih zadataka \u010desto se javlja. U korisnicima, to mogu biti provere dokumenata korisnika, obrada u\u010ditanih multimedijalnih sadr\u017eaja ili sinhronizacija podataka sa dru\u0161tvenim mre\u017eama. Ove zadatke treba nekako raspodeliti unutar klastera i kontrolisati tok izvr\u0161enja. Stoga imamo dve opcije re\u0161enja: ili koristiti \u0161ablon raspodele zadataka iz prethodnog \u010dlanka, ili, ako to ne odgovara, napisati prilago\u0111eni planer zadataka koji \u0107e upravljati grupom obrtnika na na\u010din koji nam je potreban. <\/p>\n<p><\/p>\n<p>3. ta\u010dka zahteva pro\u0161irenje pub-sub \u0161ablona. Nakon kreiranja ta\u010dke razmene pub-sub, moramo dodatno pokrenuti kontroler te ta\u010dke u okviru na\u0161eg servisa. Na taj na\u010din kao da iznosimo logiku obrade pretplate i otplate iz sloja poruka u implementaciju korisnika.<\/p>\n<p><\/p>\n<p>Na kraju, dekompozicija zadatka pokazala je da, da bismo ispunili zahteve, treba da pokrenemo 5 instanci servisa na razli\u010ditim \u010dvorovima i stvorimo dodatnu entitet - kontroler pub-sub, odgovoran za pretplatu.<br \/>\nZa pokretanje 5 obrtnika nije potrebno menjati kod servisa. Jedina dodatna akcija je konfiguracija pravila balansiranja na ta\u010dki razmene, o \u010demu \u0107emo govoriti malo kasnije.<br \/>\nPojavila se dodatna slo\u017eenost: kontroler pub-sub i prilago\u0111eni planer zadataka treba da rade u jednom jedinom primeru. Ponovo, servis za razmenu poruka, kao fundamentalni, treba da obezbedi mehanizam izbora lidera.<\/p>\n<p><\/p>\n<h3 id=\"vybor-lidera\">Izbor lidera<\/h3>\n<p><\/p>\n<p>U distribuiranim sistemima, izbor lidera je procedura imenovanja jedinog procesa koji je odgovoran za planiranje distribuirane obrade nekog optere\u0107enja. <\/p>\n<p><\/p>\n<p>U sistemima koji nisu skloni centralizaciji, koriste se univerzalni algoritmi i algoritmi zasnovani na konsenzusu, kao \u0161to su paxos ili raft.<br \/>\nBudu\u0107i da je razmena poruka \u2013 broker i centralna ta\u010dka, ona zna o svim kontrolerima servisa \u2013 kandidatima za lidere. Razmena poruka mo\u017ee imenovati lidera bez glasanja.<\/p>\n<p><\/p>\n<p>Svi servisi nakon pokretanja i povezivanja sa ta\u010dkom razmene dobijaju sistemsku poruku <code>#'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}<\/code>. U slu\u010daju da <code>LeaderPid<\/code> se podudara sa <code>pid<\/code> trenutnog procesa, on se imenuje liderom, a lista <code>Servers<\/code> sadr\u017ei sve \u010dvorove i njihove parametre.<br \/>\nKada se novi \u010dvor klastera pojavi i radni \u010dvor isklju\u010di, svi kontroleri servisa primaju <code>#'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts}<\/code> i <code>#'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts}<\/code> odgovaraju\u0107e.<\/p>\n<p><\/p>\n<p>Tako svi komponenti znaju o svim promjenama, a u klasteru je u svakoj trenutku zajam\u010den jedan lider.<\/p>\n<p><\/p>\n<h2 id=\"posredniki\">Posrednici<\/h2>\n<p><\/p>\n<p>Za realizaciju slo\u017eenih distribuiranih procesa obrade, kao i u zadacima optimizacije postoje\u0107e arhitekture, prikladno je koristiti posrednike.<br \/>\nKako bismo izbjegli promjenu koda servisa i rije\u0161ili, na primjer, zadatke dodatne obrade, usmjeravanja ili logiranja poruka, ispred servisa mo\u017eemo uklju\u010diti proxy obrtnika koji \u0107e izvr\u0161iti sav dodatni posao.<\/p>\n<p><\/p>\n<p>Klasi\u010dni primjer optimizacije pub-sub je distribuirana aplikacija s poslovnim jezgrima koja generiraju doga\u0111aje a\u017euriranja, kao \u0161to je promjena cijene na tr\u017ei\u0161tu, i sloj pristupa - N servera koji pru\u017eaju websocket API za web klijente.<br \/>\nAko se stvari rje\u0161avaju direktno, usluga klijenta izgleda ovako:<\/p>\n<p><\/p>\n<ul>\n<li>klijent uspostavlja veze s platformom. Na strani servera, koja terminira promet, pokre\u0107e se proces koji opslu\u017euje tu vezu.<\/li>\n<li>unutar opslu\u017enog procesa doga\u0111a se autorizacija i pretplata na a\u017euriranja. Proces poziva metodu subscribe za teme.<\/li>\n<li>nakon generiranja doga\u0111aja u jezgri, on se isporu\u010duje procesima koji opslu\u017euju veze.<\/li>\n<\/ul>\n<p><\/p>\n<p>Zamislimo da imamo 50000 pretplatnika na temu \u201cnews\u201d. Pretplatnici su ravnomjerno raspore\u0111eni po 5 servera. Kao rezultat, svako a\u017euriranje koje stigne na to\u010dku razmjene bit \u0107e replicirano 50000 puta: 10000 puta na svakom serveru, prema broju pretplatnika na njemu. Nije ba\u0161 u\u010dinkovita shema, zar ne?<br \/>\nKako bismo pobolj\u0161ali situaciju, uvest \u0107emo proxy s istim imenom kao to\u010dka razmjene. Registar globalnih imena trebao bi mo\u0107i vra\u0107ati najbli\u017ei proces po imenu, \u0161to je va\u017eno.<\/p>\n<p><\/p>\n<p>Pokrenut \u0107emo ovaj proxy na serverima sloja pristupa, i svi na\u0161i procesi koji opslu\u017euju websocket API \u0107e se pretplatiti na njega, a ne na izvorno pub-sub to\u010dku razmjene u jezgri. Proxy se pretpla\u0107uje na jezgru samo u slu\u010daju jedinstvene pretplate i replicira primljenu poruku svim svojim pretplatnicima.<br \/>\nKao rezultat, izme\u0111u jezgre i pristupnih servera bit \u0107e proslije\u0111eno 5 poruka, umjesto 50000.<\/p>\n<p><\/p>\n<h2 id=\"marshrutizaciya-i-balansirovka\">Usmjeravanje i balansiranje<\/h2>\n<p><\/p>\n<h3 id=\"req-resp\">Req-Resp<\/h3>\n<p><\/p>\n<p>U trenutnoj implementaciji messaging sustava postoji 7 strategija raspodjele zahtjeva:<\/p>\n<p><\/p>\n<ul>\n<li><code>default<\/code>. Upit se \u0161alje svim kontrolerima.<\/li>\n<li><code>round-robin<\/code>. Odr\u017eiv je obilazak i cikli\u010dna raspodjela upita izme\u0111u kontrolera.<\/li>\n<li><code>consensus<\/code>. Kontroleri koji opslu\u017euju servis dijele se na vo\u0111u i vo\u0111ene. Upiti se \u0161alju samo vo\u0111i.<\/li>\n<li><code>consensus &amp; round-robin<\/code>. U grupi postoji vo\u0111a, ali se upiti raspore\u0111uju izme\u0111u svih \u010dlanova.<\/li>\n<li><code>sticky<\/code>. Izra\u010dunava se hash funkcija i pridru\u017euje odre\u0111enom obra\u0111iva\u010du. Sljede\u0107i upiti s tom potpisom dolaze do istog obra\u0111iva\u010da.<\/li>\n<li><code>sticky-fun<\/code>. Prilikom inicijalizacije to\u010dke razmjene dodatno se prenosi funkcija za izra\u010dun hash-a za <code>sticky<\/code> balansiranje.<\/li>\n<li><code>fun<\/code>. Sli\u010dan je sticky-fun, ali je mogu\u0107e dodatno preusmjeriti, odbiti ili prethodno obraditi. <\/li>\n<\/ul>\n<p><\/p>\n<p>Strategija raspodjele postavlja se prilikom inicijalizacije to\u010dke razmjene.<\/p>\n<p><\/p>\n<p>Osim balansiranja, messaging omogu\u0107ava ozna\u010davanje entiteta. Razmotrite vrste oznaka u sustavu:<\/p>\n<p><\/p>\n<ul>\n<li>Oznaka za povezivanje. Omogu\u0107ava razumijevanje kako su doga\u0111aji stigli preko povezivanja. Koristi se kada se proces kontrolera povezuje na jednu to\u010dku razmjene, ali s razli\u010ditim klju\u010devima usmjeravanja. <\/li>\n<li>Oznaka servisa. Omogu\u0107ava grupiranje obra\u0111iva\u010da za jedan servis i pro\u0161iruje mogu\u0107nosti usmjeravanja i balansiranja. Za req-resp obrazac usmjeravanje je linearno. \u0160aljemo upit na to\u010dku razmjene, a zatim ga ona proslje\u0111uje servisu. No, ako trebamo podijeliti obra\u0111iva\u010de u logi\u010dke grupe, to se ostvaruje pomo\u0107u oznaka. Kada se ozna\u010di oznaka, upit \u0107e biti poslan konkretnoj grupi kontrolera.<\/li>\n<li>Oznaka upita. Omogu\u0107ava razlikovanje odgovora. Budu\u0107i da je na\u0161 sustav asinkroni, za obradu odgovora servisa potrebno je imati mogu\u0107nost navesti RequestTag prilikom slanja upita. Prema toj oznaci mo\u0107i \u0107emo razumjeti na koji je upit stigao odgovor.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pub-sub\">Pub-sub<\/h3>\n<p><\/p>\n<p>Za pub-sub je sve malo jednostavnije. Imamo to\u010dku razmjene na koju se objavljuju poruke. To\u010dka razmjene raspore\u0111uje poruke izme\u0111u pretplatnika koji su se pretplatili na potrebne klju\u010deve usmjeravanja (mo\u017ee se re\u0107i da je to analogno temama).<\/p>\n<p><\/p>\n<h2 id=\"masshtabiruemost-i-otkazoustoychivost\">Skalabilnost i otpornost na gre\u0161ke<\/h2>\n<p><\/p>\n<p>Skalabilnost sustava u cjelini ovisi o stupnju skalabilnosti slojeva i komponenti sustava:<\/p>\n<p><\/p>\n<ul>\n<li>Usluge se skaliraju dodavanjem dodatnih \u010dvorova sa procesorima te usluge u klaster. Tijekom eksperimentalnog rada mo\u017ee se odabrati optimalna politika uravnote\u017eenja.<\/li>\n<li>Sama usluga messaging u okviru zasebnog klastera obi\u010dno se skalira ili premje\u0161tanjem posebno optere\u0107enih to\u010daka razmjene na zasebne \u010dvorove klastera, ili dodavanjem proxy procesa u posebno optere\u0107ena podru\u010dja klastera.<\/li>\n<li>Skalabilnost cijelog sustava kao karakteristika ovisi o fleksibilnosti arhitekture i mogu\u0107nosti spajanja pojedinih klastera u cjelovitu logi\u010dku cjelinu.<\/li>\n<\/ul>\n<p><\/p>\n<p>Jednostavnost i brzina skaliranja \u010desto utje\u010du na uspje\u0161nost projekta. Messaging u trenutnom obliku raste zajedno s aplikacijom. \u010cak i ako nemamo dovoljno klastera od 50-60 strojeva, mo\u017eemo pribje\u0107i federaciji. Na\u017ealost, tema federacije izlazi iz okvira ovog \u010dlanka.<\/p>\n<p><\/p>\n<h2 id=\"rezervirovanie\">Sigurnosna kopija<\/h2>\n<p><\/p>\n<p>Pri analizi uravnote\u017eenja optere\u0107enja ve\u0107 smo raspravljali o rezervaciji kontrolera usluga. Me\u0111utim, messaging tako\u0111er mora biti rezerviran. U slu\u010daju pada \u010dvora ili stroja, messaging se mora automatski oporaviti u najkra\u0107em mogu\u0107em roku.<\/p>\n<p><\/p>\n<p>U svojim projektima koristim dodatne \u010dvorove koji preuzimaju optere\u0107enje u slu\u010daju pada. U Erlangu postoji standardna implementacija distribuiranog na\u010dina rada za OTP aplikacije. Distribuirani na\u010din rada zapravo provodi oporavak u slu\u010daju kvara pokretanjem pao aplikacije na drugom prethodno pokrenutom \u010dvoru. Proces je transparentan, nakon kvara aplikacija se automatski prebacuje na failover \u010dvor. O ovom funkcionalnosti mo\u017eete pro\u010ditati vi\u0161e. <noindex><a rel=\"nofollow\" href=\"http:\/\/erlang.org\/doc\/design_principles\/distributed_applications.html\">ovdje<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2 id=\"proizvoditelnost\">Performanse<\/h2>\n<p><\/p>\n<p>Poku\u0161ajmo barem pribli\u017eno usporediti performanse rabbitmq i na\u0161e prilago\u0111ene messaging usluge.<br \/>\nProna\u0161ao sam <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.openstack.org\/developer\/performance-docs\/test_results\/mq\/rabbitmq\/cmsm\/index.html\">slu\u017ebene rezultate<\/a><\/noindex> testiranja rabbitmq od tima openstack.<\/p>\n<p><\/p>\n<p>U to\u010dki 6.14.1.2.1.2.2. originalnog dokumenta predstavljeni su rezultati RPC CAST:<br \/>\n<img decoding=\"async\" alt=\"Gra\u0111evni blokovi distribuiranih aplikacija. Drugo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/95f615d241d70a4523fe3c400179b8e6.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Preliminarno, nikakve dodatne postavke u kernel OS-a ili erlang VM ne\u0107emo unositi. Uvjeti za testiranje:<\/p>\n<p><\/p>\n<ul>\n<li>erl opts: +A1 +sbtu.<\/li>\n<li>Test u okviru jednog \u010dvora erlang pokre\u0107e se na prijenosnom ra\u010dunalu sa starim i7 mobilnim procesorom.<\/li>\n<li>Klaster testovi se provode na serverima sa 10G mre\u017eom.<\/li>\n<li>Kod radi u docker kontejnerima. Mre\u017ea je u NAT re\u017eimu.<\/li>\n<\/ul>\n<p><\/p>\n<p>Kod testa:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">req_resp_bench(_) -&gt;\n  W = perftest:comprehensive(10000,\n    fun() -&gt;\n      messaging:request(?EXCHANGE, default, ping, self()),\n      receive\n        #'$msg'{message = pong} -&gt; ok\n      after 5000 -&gt;\n        throw(timeout)\n      end\n    end\n  ),\n  true = lists:any(fun(E) -&gt; E &gt;= 30000 end, W),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p><em>Scenarij 1:<\/em> Test se pokre\u0107e na prijenosnom ra\u010dunalu s starijim i7 mobilnim procesorom. Test, messaging i servis rade na jednoj instanci unutar jednog docker kontejnera:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Sekvencijalno 10000 ciklusa u ~0 sekundi (26987 ciklusa\/s)\nSekvencijalno 20000 ciklusa u ~1 sekundi (26915 ciklusa\/s)\nSekvencijalno 100000 ciklusa u ~4 sekundi (26957 ciklusa\/s)\nParalelno 2 100000 ciklusa u ~2 sekundi (44240 ciklusa\/s)\nParalelno 4 100000 ciklusa u ~2 sekundi (53459 ciklusa\/s)\nParalelno 10 100000 ciklusa u ~2 sekundi (52283 ciklusa\/s)\nParalelno 100 100000 ciklusa u ~3 sekundi (49317 ciklusa\/s)<\/code><\/pre>\n<p><\/p>\n<p><em>Scenarij 2<\/em>: 3 \u010dvora pokrenuta na razli\u010ditim strojevima pod dockerom (NAT).<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Sekvencijalno 10000 ciklusa u ~1 sekundi (8684 ciklusa\/s)\nSekvencijalno 20000 ciklusa u ~2 sekundi (8424 ciklusa\/s)\nSekvencijalno 100000 ciklusa u ~12 sekundi (8655 ciklusa\/s)\nParalelno 2 100000 ciklusa u ~7 sekundi (15160 ciklusa\/s)\nParalelno 4 100000 ciklusa u ~5 sekundi (19133 ciklusa\/s)\nParalelno 10 100000 ciklusa u ~4 sekundi (24399 ciklusa\/s)\nParalelno 100 100000 ciklusa u ~3 sekundi (34517 ciklusa\/s)<\/code><\/pre>\n<p><\/p>\n<p>U svim slu\u010dajevima, iskori\u0161tenje CPU-a nije prelazilo 250%<\/p>\n<p><\/p>\n<h2 id=\"itogi\">Zaklju\u010dci<\/h2>\n<p><\/p>\n<p>Nadam se da ovaj ciklus ne izgleda kao ispumpavanje svesti i da \u0107e moje iskustvo stvarno koristiti i istra\u017eiva\u010dima distribuiranih sistema i prakti\u010darima koji su na samom po\u010detku izgradnje distribuiranih arhitektura za svoje poslovne sisteme i s interesovanjem gledaju na Erlang\/Elixir, ali se pitaju da li da...<\/p>\n<p><\/p>\n<p>Fotografija <noindex><a rel=\"nofollow\" href=\"https:\/\/unsplash.com\/photos\/Q4bmoSPJM18\">@chuttersnap<\/a><\/noindex><\/p>\n<p class=\"for_users_only_msg\">Samo registrirani korisnici mogu sudjelovati u anketi. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Prijavite se<\/a><\/noindex>, molimo.<\/p>\n<h2 class=\"default-block__polling-title\">Koje teme bih trebao detaljno obraditi u okviru ciklusa \"Eksperiment VTrade\"?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Teorija: Tr\u017ei\u0161ta, nalogi i vrijeme njihovog trajanja: DAY, GTD, GTC, IOC, FOK, MOO, MOC, LOO, LOC<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Knjiga naloga. Teorija i praksa implementacije knjige s grupama<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Vizualizacija trgovanja: Tikovi, barovi, rezolucije. Kako pohranjivati i kako povezivati<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Backoffice. Planiranje i razvoj. Kontrola zaposlenika i istraga incidenata<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    API. Istra\u017eujemo koje su su\u010delja potrebna i kako ih implementirati<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Pohrana informacija: PostgreSQL, Timescale, Tarantool u trgova\u010dkim sustavima<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Reaktivnost u trgova\u010dkim sustavima<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Drugo. Napisat \u0107u u komentarima<\/p>\n<\/li>\n<\/ul>\n<p>    Glasovalo je 6 korisnika. 4 korisnika se suzdr\u017ealo.<br \/>\n<br \/>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446344\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c. \u0412 \u0446\u0438\u043a\u043b\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d\u0430 \u0442\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0431\u0438\u0440\u0436\u0438, \u0430\u0443\u043a\u0446\u0438\u043e\u043d\u0430 \u0438 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u0430. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u0442\u044c \u0437\u0430 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0432\u0430\u043c \u0442\u0435\u043c\u044b. \u042d\u0442\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0446\u0438\u043a\u043b\u0430 \u043f\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":23092,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-31124","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=\"description\" content=\"\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445.\" \/>\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\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie\" \/>\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\udd47\u0421\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0412\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie\" \/>\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=\"2019-10-31T18:39:36+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:39:36+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\udd47Gra\u0111evni blokovi distribuiranih aplikacija. Drugo pribli\u017eavanje | ProHoster","description":"Najava Dru\u0161tvo, sredinom ljeta planiram izdati jo\u0161 jedan ciklus \u010dlanaka o dizajnu sustava za masovno uslu\u017eivanje: \"Eksperiment VTrade\" - poku\u0161aj pisanja frameworka za trgovanje.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","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\udd47\u0421\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0412\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster","og:description":"\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445.","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","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":"2019-10-31T18:39:36+00:00","article:modified_time":"2019-10-31T18:39:36+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"31124","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":"2026-01-21 04:39:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:22:34","updated":"2026-01-21 04:39:19","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\/31124","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=31124"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/31124\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/23092"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=31124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=31124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=31124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}