{"id":30908,"date":"2019-10-31T21:38:07","date_gmt":"2019-10-31T18:38:07","guid":{"rendered":"https:\/\/prohoster.info\/blog\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\/"},"modified":"2019-10-31T21:38:07","modified_gmt":"2019-10-31T18:38:07","slug":"stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","title":{"rendered":"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/7ef485e452075775ce317b557671274c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U pro\u0161loj <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">\u010dlanku<\/a><\/noindex> Obradili smo teoretske osnove reaktivne arhitekture. Do\u0161lo je vrijeme da razgovaramo o tokovima podataka, na\u010dinima implementacije reaktivnih Erlang\/Elixir sustava i obrascima razmjene poruka u njima:<\/p>\n<p><\/p>\n<ul>\n<li>Zahtjev-odgovor<\/li>\n<li>Zahtjev-Chunkski odgovor<\/li>\n<li>Odgovor s zahtjevom<\/li>\n<li>Objavi-podijeli<\/li>\n<li>Inverted Publish-subscribe<\/li>\n<li>Distribucija zadataka<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"soa-msa-i-obmen-soobscheniyami\">SOA, MSA i razmjena poruka<\/h2>\n<p><\/p>\n<p>SOA, MSA \u2013 sistemske arhitekture koje definiraju pravila za izgradnju sustava, dok messaging pru\u017ea primitive za njihovu implementaciju.<\/p>\n<p><\/p>\n<p>Ne \u017eelim promicati odre\u0111enu arhitekturu izgradnje sustava. Zala\u017eem se za primjenu maksimalno u\u010dinkovitih i korisnih praksi za konkretan projekt i poslovanje. Koju god paradigmu odabrali, najbolje je kreirati sistemske blokove s pogledom na Unix-way: komponente s minimalnom povezanosti, odgovorne za pojedina\u010dne entitete. API metode obavljaju maksimalno jednostavne radnje s entitetima.<\/p>\n<p><\/p>\n<p>Messaging \u2012 kao \u0161to naziv sugerira \u2012 je posrednik poruka. Njegov primarni cilj je primati i slati poruke. On je zadu\u017een za su\u010delja slanja informacija, formiranje logi\u010dkih kanala za prijenos informacija unutar sustava, usmjeravanje i ravnote\u017eu optere\u0107enja, kao i obradu gre\u0161aka na sistemskoj razini.<br \/>\nRazvijeni messaging ne poku\u0161ava konkurirati rabbitmq-u niti ga zamijeniti. Njegove osnovne karakteristike su:<\/p>\n<p><\/p>\n<ul>\n<li>Distribuiranost.<br \/>\nTo\u010dke razmjene mogu se stvarati na svim \u010dvorovima klastera, \u0161to bli\u017ee kodu koji ih koristi.<\/li>\n<li>Jednostavnost.<br \/>\nUsmjerenost na minimiziranje \u0161ablonskog koda i jednostavnost kori\u0161tenja.<\/li>\n<li>Bolja izvedba.<br \/>\nNe poku\u0161avamo ponoviti funkcionalnost rabbitmq-a, ve\u0107 isti\u010demo samo arhitektonski i transportni sloj koji se jednostavno uklapa u OTP, minimiziraju\u0107i tro\u0161kove.<\/li>\n<li>Fleksibilnost.<br \/>\nSvaka usluga mo\u017ee kombinirati vi\u0161e obrazaca razmjene.<\/li>\n<li>Otpornost na gre\u0161ke, ugra\u0111ena u dizajn.<\/li>\n<li>Skalabilnost.<br \/>\nMessaging raste zajedno s aplikacijom. Kako se optere\u0107enje pove\u0107ava, to\u010dke razmjene se mogu prebaciti na posebne strojeve.<\/li>\n<\/ul>\n<p><\/p>\n<p><em>Napomena.<\/em> S aspekta organizacije koda, za slo\u017eene sustave na Erlangu\/Elixiru dobro su prikladni meta-projekti. Sav kod projekta nalazi se u jednom repozitoriju - krovnom projektu. U ovom slu\u010daju, mikroservisi su maksimalno izolirani i izvr\u0161avaju jednostavne operacije odgovorne za pojedina\u010dne entitete. Ovim pristupom lako se odr\u017eava API cijelog sustava, jednostavno se unose promjene, a prakti\u010dno je pisati jedin\u010dne i integracijske testove.<\/p>\n<p><\/p>\n<p>Komponente sustava me\u0111usobno komuniciraju izravno ili putem posrednika. S aspekta messaginga, svaka usluga ima nekoliko faza \u017eivota:<\/p>\n<p><\/p>\n<ul>\n<li>Inicijalizacija usluge.<br \/>\nU ovoj fazi dolazi do konfiguracije i pokretanja izvr\u0161ne usluge procesa i ovisnosti.<\/li>\n<li>Kreiranje to\u010dke razmjene.<br \/>\nUsluga mo\u017ee koristiti stati\u010dku to\u010dku razmjene definiranu u konfiguraciji \u010dvora, ili mo\u017ee dinami\u010dki kreirati to\u010dke razmjene. <\/li>\n<li>Registracija usluge.<br \/>\nKako bi usluga mogla obra\u0111ivati zahtjeve, potrebno ju je registrirati na to\u010dki razmjene.<\/li>\n<li>Normalno djelovanje.<br \/>\nUsluga obavlja korisni rad.<\/li>\n<li>Zavr\u0161etak rada.<br \/>\nMogu\u0107a su 2 na\u010dina zavr\u0161etka rada: redovni i izvanredni. U redovnom slu\u010daju usluga se isklju\u010duje s to\u010dke razmjene i zaustavlja. U izvanrednim slu\u010dajevima messaging provodi jedan od scenarija obrade gre\u0161aka.<\/li>\n<\/ul>\n<p><\/p>\n<p>Izgleda prili\u010dno slo\u017eeno, ali u kodu nije sve tako stra\u0161no. Primjeri koda s komentarima bit \u0107e prikazani u analizi predlo\u017eaka malo kasnije.<\/p>\n<p><\/p>\n<h2 id=\"exchanges\">Exchanges<\/h2>\n<p><\/p>\n<p>To\u010dka razmjene - proces messaginga koji implementira logiku interakcije s komponentama unutar predlo\u0161ka razmjene poruka. U svim primjerima predstavljenim u nastavku, komponente komuniciraju putem to\u010daka razmjene, \u010dija kombinacija oblikuje messaging.<\/p>\n<p><\/p>\n<h2 id=\"message-exchange-patterns-meps\">\u0160abloni razmjene poruka (MEPs)<\/h2>\n<p><\/p>\n<p>Globalno, \u0161abloni razmjene mogu se podijeliti na dvosmjerne i jednosmjerne. Prvi podrazumijevaju odgovor na primljenu poruku, dok drugi ne. Klasi\u010dni primjer dvosmjernog \u0161ablona u klijent-server arhitekturi je \u0161ablon zahtjeva-odgovora. Razmotrimo \u0161ablon i njegove modifikacije.<\/p>\n<p><\/p>\n<h3 id=\"requestresponse-ili-rpc\">Zahtjev-odgovor ili RPC<\/h3>\n<p><\/p>\n<p>RPC se koristi kada trebamo dobiti odgovor od drugog procesa. Ovaj proces mo\u017ee biti pokrenut na istom \u010dvoru ili se nalaziti na drugom kontinentu. Ispod je prikazana shema interakcije klijenta i <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/hr\/server\/dts-los-angeles\/\"   title=\"poslu\u017eitelja\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3483\">poslu\u017eitelja<\/a> putem messaginga.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/091725fc108d6ce1a5fc9ae866e2c395.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Budu\u0107i da je messaging potpuno asinkron, klijentska razmjena dijeli se na 2 faze:<\/p>\n<p><\/p>\n<ol>\n<li>\n<p>Slanje zahtjeva<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).<\/code><\/pre>\n<p><\/p>\n<p><em>Razmjena<\/em> \u2012 jedinstveno ime razmjene.<br \/>\n<em>ResponseMatchingTag<\/em> \u2012 lokalna oznaka za obradu odgovora. Na primjer, u slu\u010daju slanja vi\u0161e identi\u010dnih zahtjeva koji pripadaju razli\u010ditim korisnicima.<br \/>\n<em>RequestDefinition<\/em> \u2012 tijelo zahtjeva.<br \/>\n<em>HandlerProcess<\/em> \u2012 PID obrtnika. Ovaj proces \u0107e primiti odgovor s poslu\u017eitelja.<\/p>\n<p>\n<\/li>\n<li>\n<p>Obrada odgovora<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">handle_info(#'$msg'{exchange = EXCHANGE, tag = ResponseMatchingTag,message = ResponsePayload}, State)<\/code><\/pre>\n<p><\/p>\n<p><em>ResponsePayload<\/em> \u2012 odgovor poslu\u017eitelja.<\/p>\n<p>\n<\/li>\n<\/ol>\n<p><\/p>\n<p>Za poslu\u017eitelj proces se tako\u0111er sastoji od 2 faze:<\/p>\n<p><\/p>\n<ol>\n<li>Inicijalizacija to\u010dke razmjene<\/li>\n<li>Obrada pristiglih zahtjeva<\/li>\n<\/ol>\n<p><\/p>\n<p>Ilustrirat \u0107emo ovaj predlo\u017eak kodom. Pretpostavimo da trebamo implementirati jednostavnu uslugu koja pru\u017ea jedinu metodu za to\u010dno vrijeme.<\/p>\n<p><\/p>\n<h4 id=\"kod-servera\">Kod poslu\u017eitelja<\/h4>\n<p><\/p>\n<p>Izvadimo definiciju API-ja usluge u api.hrl:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% =====================================================\n%%  entiteti\n%% =====================================================\n-record(time, {\n  unixtime :: non_neg_integer(),\n  datetime :: binary()\n}).\n\n-record(time_error, {\n  code :: non_neg_integer(),\n  error :: term()\n}).\n\n%% =====================================================\n%%  metode\n%% =====================================================\n-record(time_req, {\n  opts :: term()\n}).\n-record(time_resp, {\n  result :: #time{} | #time_error{}\n}).<\/code><\/pre>\n<p><\/p>\n<p>Definirajmo kontroler usluge u time_controller.erl<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% U primjeru je prikodan samo zna\u010dajan kod. Umetanjem u predlo\u017eak gen_server mo\u017eete dobiti radnu uslugu.\n\n%% inicijalizacija gen_server\ninit(Args) -&gt;\n  %% povezivanje na to\u010dku razmjene\n  messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())\n  {ok, #{}}.\n\n%% obrada doga\u0111aja gubitka veze s to\u010dkom razmjene. Ovaj doga\u0111aj dolazi ako to\u010dka razmjene jo\u0161 nije pokrenuta.\nhandle_info(#exchange_die{exchange = ?EXCHANGE}, State) -&gt;\n  erlang:send(self(), monitor_exchange),\n  {noreply, State};\n\n%% obrada API-ja\nhandle_info(#time_req{opts = _Opts}, State) -&gt;\n  messaging:response_once(Client, #time_resp{\nresult = #time{ unixtime = time_utils:unixtime(now()), datetime = time_utils:iso8601_fmt(now())}\n  });\n  {noreply, State};\n\n%% zavr\u0161etak rada gen_server\nterminate(_Reason, _State) -&gt;\n  messaging:demonitor_exchange(req_resp, ?EXCHANGE, default, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<h4 id=\"kod-klienta\">Kod klijenta<\/h4>\n<p><\/p>\n<p>Da biste poslali zahtjev usluzi, bilo gdje u klijentu mo\u017eete pozvati messaging request API:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">case messaging:request(?EXCHANGE, tag, #time_req{opts = #{}}, self()) of\n    ok -&gt; ok;\n    _ -&gt; %% logika ponavljanja ili neuspjeha\nend<\/code><\/pre>\n<p><\/p>\n<p>U distribuiranom sustavu konfiguracija komponenti mo\u017ee biti razli\u010dita, a tijekom zahtjeva messaging mo\u017eda jo\u0161 nije pokrenut ili kontroler usluge ne\u0107e biti spreman opslu\u017eiti zahtjev. Stoga moramo provjeriti odgovor messaging i obraditi slu\u010daj neuspjeha.<br \/>\nNakon uspje\u0161nog slanja, klijentu \u0107e od usluge sti\u0107i odgovor ili pogre\u0161ka.<br \/>\nObradit \u0107emo oba slu\u010daja u handle_info:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time{unixtime = Utime}}}, State) -&gt;\n  ?debugVal(Utime),\n  {noreply, State};\n\nhandle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time_error{code = ErrorCode}}}, State) -&gt;\n  ?debugVal({error, ErrorCode}),\n  {noreply, State};<\/code><\/pre>\n<p><\/p>\n<h3 id=\"request-chunked-response\">Zahtjev-Chunkski odgovor<\/h3>\n<p><\/p>\n<p>Bolje je izbje\u0107i slanje velikih poruka. To utje\u010de na odziv i stabilnost cijelog sustava. Ako odgovor na zahtjev zauzima puno memorije, segmentacija je obavezna.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/bd60742a933a8e4e3eeaf7f4adf00f2a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Navest \u0107u nekoliko primjera takvih slu\u010dajeva:<\/p>\n<p><\/p>\n<ul>\n<li>Komponente razmjenjuju binarne podatke, na primjer datoteke. Segmentacija odgovora na manje dijelove poma\u017ee u\u010dinkovito raditi s datotekama bilo koje veli\u010dine i sprje\u010dava preoptere\u0107enje memorije.<\/li>\n<li>Listi. Na primjer, trebamo odabrati sve unose iz velike tablice u bazi i prenijeti ih drugoj komponenti.<\/li>\n<\/ul>\n<p><\/p>\n<p>Nazivam takve odgovore vlakom. U svakom slu\u010daju, 1024 poruke od 1 MB bolje su od jedne poruke od 1 GB. <\/p>\n<p><\/p>\n<p>U Erlang klasteru dobivamo dodatnu korist - smanjenje optere\u0107enja na mjestu razmjene i mre\u017ei, jer se odgovori odmah \u0161alju primatelju, zaobilaze\u0107i to\u010dku razmjene.<\/p>\n<p><\/p>\n<h3 id=\"response-with-request\">Odgovor s zahtjevom<\/h3>\n<p><\/p>\n<p>To je prili\u010dno rijetka modifikacija RPC obrasca za izgradnju dijalogue sustava.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/9b350a0b48ca8acdca973da2f7eadb76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h3 id=\"publish-subscribe-data-distribution-tree\">Publish-subscribe (stablo distribucije podataka)<\/h3>\n<p><\/p>\n<p>Sustavi temeljeni na doga\u0111ajima isporu\u010duju podatke potro\u0161a\u010dima kad su ti podaci spremni. Na taj na\u010din, sustavi su skloniji push modelu nego pull ili poll. Ova karakteristika omogu\u0107uje da se ne tro\u0161e resursi na stalno upitavanje i \u010dekanje podataka.<br \/>\nNa slici je prikazan proces distribucije poruka potro\u0161a\u010dima koji su se prijavili na odre\u0111enu temu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/e211d5dcfeb5ce8513699eac8e3b6d84.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Klasi\u010dni primjeri kori\u0161tenja ovog obrasca uklju\u010duju distribuciju stanja: virtualnog svijeta u ra\u010dunalnim igrama, tr\u017ei\u0161nih podataka na burzama, korisnih informacija u data feedovima.<\/p>\n<p><\/p>\n<p>Razmotrit \u0107emo kod pretplatnika:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">init(_Args) -&gt;\n  %% prijavljujemo se na razmjenik, klju\u010d = key\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {ok, #{}}.\n\nhandle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) -&gt;\n  %% ako razmjenik nije dostupan, poku\u0161avamo ponovo povezati\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {noreply, State};\n\n%% obra\u0111ujemo primljene poruke\nhandle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) -&gt;\n  ?debugVal(Msg),\n  {noreply, State};\n\n%% prilikom zaustavljanja potro\u0161a\u010da - odjavljujemo se s razmjenika\nterminate(_Reason, _State) -&gt;\n  messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p>Izvor mo\u017ee pozvati funkciju objavljivanja poruke na bilo kojem prikladnom mjestu:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:publish_message(Exchange, Key, Message).<\/code><\/pre>\n<p><\/p>\n<p><em>Razmjena<\/em> \u2012 naziv to\u010dke razmjene,<br \/>\n<em>Klju\u010d<\/em> \u2012 klju\u010d usmjeravanja,<br \/>\n<em>Poruka,<\/em> \u2012 payload.<\/p>\n<p><\/p>\n<h2 id=\"inverted-publish-subscribe\">Inverted Publish-subscribe<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/2ef7cd7de459455937bdcfa8a11fd028.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Implementacijom pub-sub modela mo\u017ee se dobiti obrazac pogodan za logiranje. Skup izvora i potro\u0161a\u010da mo\u017ee biti potpuno razli\u010dit. Na slici je prikazan slu\u010daj s jednim potro\u0161a\u010dem i vi\u0161e izvora.<\/p>\n<p><\/p>\n<h2 id=\"task-distribution-pattern\">Obrazac raspodjele zadataka.<\/h2>\n<p><\/p>\n<p>U gotovo svakom projektu javljaju se zadaci odgo\u0111enog izvr\u0161avanja, poput generiranja izvje\u0161taja, slanja obavijesti, dobivanja podataka iz vanjskih sustava. Propusnost sustava koji izvr\u0161ava te zadatke lako se skalira dodavanjem obra\u0111iva\u010da. Sve \u0161to trebamo je formirati klaster obra\u0111iva\u010da i ravnomjerno raspodijeliti zadatke izme\u0111u njih.<\/p>\n<p><\/p>\n<p>Razmotrimo pojave na primjeru 3 obra\u0111iva\u010da. Ve\u0107 u fazi raspodjele zadataka javlja se pitanje pravednosti i preoptere\u0107enja obra\u0111iva\u010da. Za pravednost \u0107e se pobrinuti round-robin raspodjela, a kako bismo izbjegli situacije preoptere\u0107enja obra\u0111iva\u010da, uvest \u0107emo ograni\u010denje <em>prefetch_limit<\/em>. U prijelaznim fazama <em>prefetch_limit<\/em> ne\u0107e dopustiti jednom obra\u0111iva\u010du da preuzme sve zadatke.<\/p>\n<p><\/p>\n<p>Messaging upravlja redovima i prioritetima obrade. Obra\u0111iva\u010di dobivaju zadatke kako dolaze. Izvr\u0161enje zadatka mo\u017ee zavr\u0161iti uspje\u0161no ili neuspje\u0161no:<\/p>\n<p><\/p>\n<ul>\n<li><code>messaging:ack(Tack)<\/code> \u2012 poziva se u slu\u010daju uspje\u0161nog obavljanja poruke.<\/li>\n<li><code>messaging:nack(Tack)<\/code> \u2012 poziva se u svim izvanrednim situacijama. Nakon vra\u0107anja zadatka, messaging \u0107e ga proslijediti drugom obra\u0111iva\u010du.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Gradivni blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje\" src=\"\/wp-content\/uploads\/2019\/04\/c2c632b6411247ee8b0dcfb3250a4503.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pretpostavimo da se tijekom obrade tri zadatka dogodila slo\u017eena gre\u0161ka: obra\u0111iva\u010d 1 se sru\u0161io nakon \u0161to je primio zadatak, ne uspjev\u0161i ni\u0161ta prijaviti to\u010dki razmjene. U tom slu\u010daju, to\u010dka razmjene, nakon isteka ack timeout-a, prenijet \u0107e zadatak drugom obra\u0111iva\u010du. Obra\u0111iva\u010d 3 iz nekog je razloga odbio zadatak i poslao nack, na kraju je i taj zadatak pre\u0161ao drugom obra\u0111iva\u010du koji ga je uspje\u0161no izvr\u0161io.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnyy-itog\">Preliminarni zaklju\u010dak<\/h2>\n<p><\/p>\n<p>Obradili smo osnovne sastavnice distribuiranih sustava i stekli osnovno razumijevanje njihove primjene u Erlangu\/Elixiru.<\/p>\n<p><\/p>\n<p>Kombiniranjem osnovnih obrazaca, mogu\u0107e je izgraditi slo\u017eene paradigme za rje\u0161avanje pojavljenih zadataka.<\/p>\n<p><\/p>\n<p>U zavr\u0161nom dijelu ciklusa razmotrit \u0107emo op\u0107a pitanja organizacije usluga, usmjeravanja i balansiranja, kao i prakti\u010dne aspekte skalabilnosti i otpornosti sustava.<\/p>\n<p><\/p>\n<p>Kraj drugog dijela.<\/p>\n<p><\/p>\n<p>Fotografija <noindex>Marius Christensen<\/noindex><br \/>\nIlustracije su pripremljene pomo\u0107u websequencediagrams.com<\/p>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446108\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043f\u043e\u0442\u043e\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0443\u0442\u044f\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 Erlang\/Elixir \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u043d\u0438\u0445: Request-response Request-Chunked Response Response with Request Publish-subscribe Inverted Publish-subscribe Task distribution SOA, MSA \u0438 \u043e\u0431\u043c\u0435\u043d \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 SOA, MSA \u2013 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22886,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30908","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-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. \u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-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:38:07+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:38:07+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\u0111evinski blokovi distribuiranih aplikacija. Prvo pribli\u017eavanje | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-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. \u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-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:38:07+00:00","article:modified_time":"2019-10-31T18:38:07+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30908","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-02-22 15:33:36","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:27:06","updated":"2026-02-22 15:33:36","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\/30908","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=30908"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/30908\/revisions"}],"predecessor-version":[{"id":162009,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/30908\/revisions\/162009"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/22886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=30908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=30908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=30908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}