{"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\/ro\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","title":{"rendered":"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" src=\"\/wp-content\/uploads\/2019\/04\/7ef485e452075775ce317b557671274c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen trecut, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">pe care l-a\u021bi citit<\/a><\/noindex> Am discutat despre fundamentele teoretice ale arhitecturii reactive. A venit momentul s\u0103 vorbim despre fluxurile de date, c\u0103ile de implementare a sistemelor reactive Erlang\/Elixir \u0219i despre modelele de schimb de mesaje \u00een acestea:<\/p>\n<p><\/p>\n<ul>\n<li>Cerere-r\u0103spuns<\/li>\n<li>Cerere-R\u0103spuns Chunked<\/li>\n<li>R\u0103spuns cu Cerere<\/li>\n<li>Publicare-abonare<\/li>\n<li>Publicare-abonare inversat\u0103<\/li>\n<li>Distribu\u021bia sarcinilor<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"soa-msa-i-obmen-soobscheniyami\">SOA, MSA \u0219i schimbul de mesaje<\/h2>\n<p><\/p>\n<p>SOA, MSA \u2013 arhitecturi sistemice care definesc regulile de construire a sistemelor, \u00een timp ce messaging ofer\u0103 primitive pentru implementarea acestora.<\/p>\n<p><\/p>\n<p>Nu vreau s\u0103 promovez o arhitectur\u0103 sau alta pentru construirea sistemelor. Sus\u021bin aplicarea celor mai eficiente \u0219i utile practici pentru proiectul \u0219i afacerea specific\u0103. Indiferent de paradigma aleas\u0103, este mai bine s\u0103 cre\u0103m blocuri sistemice cu referire la principiul Unix: componente cu leg\u0103turi minime, responsabile pentru entit\u0103\u021bi separate. Metodele API efectueaz\u0103 ac\u021biuni c\u00e2t mai simple cu entit\u0103\u021bile.<\/p>\n<p><\/p>\n<p>Messaging \u2012 dup\u0103 cum sugereaz\u0103 numele \u2012 este un broker de mesaje. Principalul s\u0103u scop este de a primi \u0219i transmite mesaje. El se ocup\u0103 de interfe\u021bele de expediere a informa\u021biilor, de formarea canalelor logice de transmitere a informa\u021biilor \u00een cadrul sistemului, de rutare \u0219i echilibrare, precum \u0219i de gestionarea defectelor la nivel sistemic.<br \/>\nMessaging-ul dezvoltat nu \u00eencearc\u0103 s\u0103 concureze cu rabbitmq sau s\u0103-l \u00eenlocuiasc\u0103. Principalele sale caracteristici sunt:<\/p>\n<p><\/p>\n<ul>\n<li>Distribu\u021bia.<br \/>\nPunctele de schimb pot fi create pe toate nodurile clusterei, c\u00e2t mai aproape de codul care le utilizeaz\u0103.<\/li>\n<li>Simplitate.<br \/>\nOrientare c\u0103tre minimizarea codului standard \u0219i u\u0219urin\u021ba de utilizare.<\/li>\n<li>Performan\u021b\u0103 superioar\u0103.<br \/>\nNu \u00eencerc\u0103m s\u0103 replic\u0103m func\u021bionalitatea rabbitmq, ci ne concentr\u0103m doar pe stratul arhitectural \u0219i de transport, pe care \u00eel integr\u0103m c\u00e2t mai simplu \u00een OTP, minimiz\u00e2nd costurile.<\/li>\n<li>Flexibilitatea.<br \/>\nFiecare serviciu poate combina numeroase modele de schimb.<\/li>\n<li>Resilien\u021ba, \u00eenr\u0103d\u0103cinat\u0103 \u00een design.<\/li>\n<li>Scalabilitate.<br \/>\nMessaging-ul cre\u0219te \u00eempreun\u0103 cu aplica\u021bia. Pe m\u0103sur\u0103 ce sarcina cre\u0219te, punctele de schimb pot fi mutate pe ma\u0219ini separate.<\/li>\n<\/ul>\n<p><\/p>\n<p><em>Observa\u021bie.<\/em> Din perspectiva organiz\u0103rii codului, pentru sisteme complexe \u00een Erlang\/Elixir, proiectele meta sunt foarte potrivite. Tot codul proiectului se afl\u0103 \u00eentr-un singur depozit - un proiect umbrel\u0103. \u00cen acest context, microserviciile sunt c\u00e2t mai izolate posibil \u0219i efectueaz\u0103 opera\u021bii simple, fiecare fiind responsabil\u0103 pentru o entitate separat\u0103. Cu un astfel de abordare, este u\u0219or de men\u021binut API-ul \u00eentregului sistem, modific\u0103rile sunt simple de realizat, iar scrierea testelor unitare \u0219i de integrare este convenabil\u0103.<\/p>\n<p><\/p>\n<p>Componentele sistemului interac\u021bioneaz\u0103 direct sau prin intermediul unui broker. Din perspectiva messaging-ului, fiecare serviciu are mai multe faze de via\u021b\u0103:<\/p>\n<p><\/p>\n<ul>\n<li>Ini\u021bializarea serviciului.<br \/>\n\u00cen aceast\u0103 etap\u0103 se face configurarea \u0219i pornirea procesului care execut\u0103 serviciul \u0219i a dependen\u021belor.<\/li>\n<li>Crearea unui punct de schimb.<br \/>\nServiciul poate folosi un punct de schimb static, definit \u00een configura\u021bia nodului, sau poate crea puncte de schimb dinamic. <\/li>\n<li>\u00cenregistrarea serviciului.<br \/>\nPentru ca serviciul s\u0103 poat\u0103 gestiona solicit\u0103rile, trebuie \u00eenregistrat la punctul de schimb.<\/li>\n<li>Func\u021bionarea normal\u0103.<br \/>\nServiciul \u00eendepline\u0219te o munc\u0103 util\u0103.<\/li>\n<li>Finalizarea muncii.<br \/>\nExist\u0103 2 tipuri de finalizare a activit\u0103\u021bii: normal\u0103 \u0219i de urgen\u021b\u0103. \u00cen cazul normal, serviciul se deconecteaz\u0103 de la punctul de schimb \u0219i se opre\u0219te. \u00cen cazuri de urgen\u021b\u0103, messaging-ul execut\u0103 unul dintre scenariile de gestionare a defec\u021biunilor.<\/li>\n<\/ul>\n<p><\/p>\n<p>Pare destul de complex, dar \u00een cod nu este totul at\u00e2t de \u00eenfrico\u0219\u0103tor. Exemple de cod cu comentarii vor fi prezentate \u00een analiza \u0219abloanelor pu\u021bin mai t\u00e2rziu.<\/p>\n<p><\/p>\n<h2 id=\"exchanges\">Exchanges<\/h2>\n<p><\/p>\n<p>Punctul de schimb este un proces de messaging care implementeaz\u0103 logica interac\u021biunii cu componentele \u00een cadrul \u0219ablonului de schimb de mesaje. \u00cen toate exemplele prezentate mai jos, componentele interac\u021bioneaz\u0103 prin puncte de schimb, combina\u021bia c\u0103rora formeaz\u0103 messaging-ul.<\/p>\n<p><\/p>\n<h2 id=\"message-exchange-patterns-meps\">Modelele de schimb de mesaje (MEPs)<\/h2>\n<p><\/p>\n<p>\u00cen mod global, modelele de schimb pot fi \u00eemp\u0103r\u021bite \u00een bidirec\u021bionale \u0219i unidirec\u021bionale. Primele implic\u0103 un r\u0103spuns la mesajul primit, cele din urm\u0103 nu. Un exemplu clasic de model bidirec\u021bional \u00een arhitectura client-server este modelul Request-response. S\u0103 examin\u0103m modelul \u0219i modific\u0103rile sale.<\/p>\n<p><\/p>\n<h3 id=\"requestresponse-ili-rpc\">Request\u2013response sau RPC<\/h3>\n<p><\/p>\n<p>RPC este utilizat atunci c\u00e2nd avem nevoie s\u0103 ob\u021binem un r\u0103spuns de la un alt proces. Acest proces poate fi pornit pe acela\u0219i nod sau poate fi situat pe un alt continent. Mai jos este prezentat\u0103 schema de interac\u021biune \u00eentre client \u0219i <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/ro\/server\/dts-los-angeles\/\"   title=\"server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3483\">server<\/a> prin messaging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" src=\"\/wp-content\/uploads\/2019\/04\/091725fc108d6ce1a5fc9ae866e2c395.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Deoarece messaging-ul este complet asincron, pentru client schimbul este \u00eemp\u0103r\u021bit \u00een 2 faze:<\/p>\n<p><\/p>\n<ol>\n<li>\n<p>Trimiterea unei solicit\u0103ri<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).<\/code><\/pre>\n<p><\/p>\n<p><em>Exchange<\/em> \u2012 numele unic al punctului de schimb<br \/>\n<em>ResponseMatchingTag<\/em> \u2012 eticheta local\u0103 pentru procesarea r\u0103spunsului. De exemplu, \u00een cazul trimiterii mai multor cereri identice, care apar\u021bin unor utilizatori diferi\u021bi.<br \/>\n<em>RequestDefinition<\/em> \u2012 corpul cererii<br \/>\n<em>HandlerProcess<\/em> \u2012 PID-ul handler-ului. Acest proces va primi r\u0103spunsul de la server.<\/p>\n<p>\n<\/li>\n<li>\n<p>Procesarea r\u0103spunsului<\/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 r\u0103spunsul serverului.<\/p>\n<p>\n<\/li>\n<\/ol>\n<p><\/p>\n<p>Pentru server, procesul const\u0103 de asemenea \u00een 2 faze:<\/p>\n<p><\/p>\n<ol>\n<li>Ini\u021bializarea punctului de schimb<\/li>\n<li>Procesarea cererilor primite<\/li>\n<\/ol>\n<p><\/p>\n<p>Vom ilustra acest \u0219ablon cu cod. S\u0103 presupunem c\u0103 trebuie s\u0103 implement\u0103m un serviciu simplu care ofer\u0103 o singur\u0103 metod\u0103 pentru ore exacte.<\/p>\n<p><\/p>\n<h4 id=\"kod-servera\">Codul serverului<\/h4>\n<p><\/p>\n<p>Vom extrage definirea API-ului serviciului \u00een api.hrl:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% =====================================================\n%%  entit\u0103\u021bi\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>Vom defini controlerul serviciului \u00een time_controller.erl<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% Exemplul arat\u0103 doar codul relevant. Introduc\u00e2ndu-l \u00een \u0219ablonul gen_server se poate ob\u021bine un serviciu func\u021bional.\n\n%% ini\u021bializarea gen_server\ninit(Args) -&gt;\n  %% conectare la punctul de schimb\n  messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())\n  {ok, #{}}.\n\n%% procesarea evenimentului de pierdere a conexiunii cu punctul de schimb. Acest eveniment este primit \u0219i dac\u0103 punctul de schimb nu a \u00eenceput \u00eenc\u0103.\nhandle_info(#exchange_die{exchange = ?EXCHANGE}, State) -&gt;\n  erlang:send(self(), monitor_exchange),\n  {noreply, State};\n\n%% procesarea API-ului\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%% finalizarea activit\u0103\u021bii 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\">Codul clientului<\/h4>\n<p><\/p>\n<p>Pentru a trimite o cerere serviciului, \u00een orice loc al clientului se poate apela API-ul de cerere messaging:<\/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; %% logic\u0103 de repetare sau eroare\nend<\/code><\/pre>\n<p><\/p>\n<p>\u00centr-un sistem distribuit, configura\u021bia componentelor poate fi foarte variat\u0103 \u0219i \u00een momentul cererii messaging poate s\u0103 nu fi pornit, sau controlerul serviciului nu va fi preg\u0103tit s\u0103 proceseze cererea. De aceea, este necesar s\u0103 verific\u0103m r\u0103spunsul messaging \u0219i s\u0103 gestion\u0103m cazul de e\u0219ec.<br \/>\nDup\u0103 trimiterea cu succes, clientul va primi un r\u0103spuns sau o eroare din partea serviciului.<br \/>\nS\u0103 proces\u0103m ambele cazuri \u00een 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\">Cerere-R\u0103spuns Chunked<\/h3>\n<p><\/p>\n<p>Este mai bine s\u0103 nu permite\u021bi transmiterea de mesaje mari. Acest lucru afecteaz\u0103 r\u0103spunsul \u0219i func\u021bionarea stabil\u0103 a \u00eentregului sistem. Dac\u0103 r\u0103spunsul la o solicitare consum\u0103 mult\u0103 memorie, atunci fragmentarea pe p\u0103r\u021bi este obligatorie.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" src=\"\/wp-content\/uploads\/2019\/04\/bd60742a933a8e4e3eeaf7f4adf00f2a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Voi oferi c\u00e2teva exemple de astfel de cazuri:<\/p>\n<p><\/p>\n<ul>\n<li>Componentele schimb\u0103 date binare, cum ar fi fi\u0219ierele. Fragmentarea r\u0103spunsului \u00een p\u0103r\u021bi mici ajut\u0103 la gestionarea eficient\u0103 a fi\u0219ierelor de orice dimensiune \u0219i la evitarea dep\u0103\u0219irilor de memorie.<\/li>\n<li>List\u0103ri. De exemplu, trebuie s\u0103 select\u0103m toate \u00eenregistr\u0103rile dintr-un tabel imens din baz\u0103 \u0219i s\u0103 le transmitem unei alte componente.<\/li>\n<\/ul>\n<p><\/p>\n<p>Numesc astfel de r\u0103spunsuri tren. \u00cen orice caz, 1024 de mesaje de 1 MB sunt mai bune dec\u00e2t un singur mesaj de 1 GB. <\/p>\n<p><\/p>\n<p>\u00cen clusterul Erlang, ob\u021binem un avantaj suplimentar - reducerea sarcinii pe punctul de schimb \u0219i pe re\u021bea, deoarece r\u0103spunsurile sunt direc\u021bionate imediat c\u0103tre destinatar, ocolind punctul de schimb.<\/p>\n<p><\/p>\n<h3 id=\"response-with-request\">R\u0103spuns cu Cerere<\/h3>\n<p><\/p>\n<p>Aceasta este o modificare destul de rar\u0103 a modelului RPC pentru construirea sistemelor de dialog.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" 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\">Publicare-abonare (copac de distribu\u021bie a datelor)<\/h3>\n<p><\/p>\n<p>Sistemele orientate pe evenimente livreaz\u0103 datele consumatorilor pe m\u0103sur\u0103 ce devin disponibile. Astfel, sistemele sunt mai \u00eenclinate spre modelul push dec\u00e2t spre pull sau poll. Aceast\u0103 caracteristic\u0103 permite evitarea risipei de resurse prin a solicita constant \u0219i a a\u0219tepta date.<br \/>\n\u00cen imagine este prezentat procesul de distribu\u021bie a mesajelor c\u0103tre consumatorii abona\u021bi la un anumit subiect.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" src=\"\/wp-content\/uploads\/2019\/04\/e211d5dcfeb5ce8513699eac8e3b6d84.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Exemple clasice de utilizare a acestui \u0219ablon sunt distribu\u021bia st\u0103rii: lumea jocurilor video, datele de pe pie\u021be, informa\u021bii utile \u00een fluxuri de date.<\/p>\n<p><\/p>\n<p>S\u0103 analiz\u0103m codul abonatului:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">init(_Args) -&gt;\n  %% ne abon\u0103m la punctul de schimb, cheie = key\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {ok, #{}}.\n\nhandle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) -&gt;\n  %% dac\u0103 punctul de schimb nu este disponibil, \u00eencerc\u0103m s\u0103 ne reconect\u0103m\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {noreply, State};\n\n%% prelu\u0103m mesajele primite\nhandle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) -&gt;\n  ?debugVal(Msg),\n  {noreply, State};\n\n%% la oprirea consumatorului - ne deconect\u0103m de la punctul de schimb\nterminate(_Reason, _State) -&gt;\n  messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p>Sursa poate apela func\u021bia de publicare a mesajelor \u00een orice loc convenabil:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:publish_message(Exchange, Key, Message).<\/code><\/pre>\n<p><\/p>\n<p><em>Exchange<\/em> \u2012 numele punctului de schimb,<br \/>\n<em>Cheie<\/em> \u2012 cheia de rutare,<br \/>\n<em>Mesaj<\/em> \u2012 \u00eenc\u0103rc\u0103tura util\u0103.<\/p>\n<p><\/p>\n<h2 id=\"inverted-publish-subscribe\">Publicare-abonare inversat\u0103<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" src=\"\/wp-content\/uploads\/2019\/04\/2ef7cd7de459455937bdcfa8a11fd028.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dup\u0103 implementarea pub-sub, se poate ob\u021bine un model confortabil pentru logare. Setul de surse \u0219i consumatori poate fi complet diferit. \u00cen imagine este prezentat un caz cu un singur consumator \u0219i multe surse.<\/p>\n<p><\/p>\n<h2 id=\"task-distribution-pattern\">Model de distribu\u021bie a sarcinilor<\/h2>\n<p><\/p>\n<p>\u00cen aproape fiecare proiect apar sarcini de procesare \u00eent\u00e2rziate, cum ar fi generarea de rapoarte, livrarea de notific\u0103ri, ob\u021binerea de date din sisteme externe. Capacitatea sistemului care execut\u0103 aceste sarcini se scaleaz\u0103 cu u\u0219urin\u021b\u0103 prin ad\u0103ugarea de procesatori. Tot ce ne r\u0103m\u00e2ne de f\u0103cut este s\u0103 form\u0103m un cluster de procesatori \u0219i s\u0103 distribuim sarcinile uniform \u00eentre ei.<\/p>\n<p><\/p>\n<p>S\u0103 examin\u0103m situa\u021biile ap\u0103rute prin exemplul a 3 procesatori. Chiar \u0219i \u00een etapa de distribu\u021bie a sarcinilor apare \u00eentrebarea echit\u0103\u021bii distribu\u021biei \u0219i a supraaglomer\u0103rii procesatorilor. R\u0103spunderea pentru echitate va fi asigurat\u0103 de distribu\u021bia round-robin, iar pentru a preveni situa\u021biile de supraaglomerare a procesatorilor, vom introduce o limit\u0103, <em>prefetch_limit<\/em>. \u00cen regimuri tranzitorii, <em>prefetch_limit<\/em> nu va permite unui procesator s\u0103 primeasc\u0103 toate sarcinile.<\/p>\n<p><\/p>\n<p>Messaging gestioneaz\u0103 cozile \u0219i prioritatea de procesare. Procesatorii primesc sarcinile pe m\u0103sur\u0103 ce sosesc. Executarea unei sarcini poate fi finalizat\u0103 cu succes sau poate fi refuzat\u0103:<\/p>\n<p><\/p>\n<ul>\n<li><code>messaging:ack(Tack)<\/code> \u2012 este apelat \u00een cazul proces\u0103rii reu\u0219ite a mesajului;<\/li>\n<li><code>messaging:nack(Tack)<\/code> \u2012 este apelat \u00een toate situa\u021biile neprev\u0103zute. Dup\u0103 returnarea sarcinii, messaging o va transmite unui alt procesator.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocuri de construc\u021bie ale aplica\u021biilor distribuite. Prima aproximare\" src=\"\/wp-content\/uploads\/2019\/04\/c2c632b6411247ee8b0dcfb3250a4503.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>S\u0103 presupunem c\u0103, \u00een timpul proces\u0103rii a trei sarcini, a avut loc o eroare complex\u0103: procesatorul 1 a picat dup\u0103 primirea sarcinii, f\u0103r\u0103 a reu\u0219i s\u0103 comunice ceva punctului de schimb. \u00cen acest caz, punctul de schimb, dup\u0103 expirarea timeout-ului ack, va transmite sarcina unui alt procesator. Procesatorul 3, dintr-un anumit motiv, a refuzat sarcina \u0219i a trimis nack; \u00een cele din urm\u0103, sarcina a trecut \u0219i la alt procesator care a executat-o cu succes.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnyy-itog\">Rezumat preliminar<\/h2>\n<p><\/p>\n<p>Am trecut \u00een revist\u0103 principalele elemente ale sistemelor distribuite \u0219i am ob\u021binut o \u00een\u021belegere de baz\u0103 a aplic\u0103rii acestora \u00een Erlang\/Elixir.<\/p>\n<p><\/p>\n<p>Combin\u00e2nd modelele de baz\u0103, se pot construi paradigme complexe pentru a rezolva sarcinile ap\u0103rute.<\/p>\n<p><\/p>\n<p>\u00cen partea final\u0103 a ciclului, vom explora \u00eentreb\u0103rile generale privind organizarea serviciilor, rutarea \u0219i balansarea, precum \u0219i vom discuta partea practic\u0103 a scalabilit\u0103\u021bii \u0219i rezilien\u021bei sistemelor.<\/p>\n<p><\/p>\n<p>Sf\u00e2r\u0219itul p\u0103r\u021bii a doua.<\/p>\n<p><\/p>\n<p>Fotografie <noindex>Marius Christensen<\/noindex><br \/>\nIlustra\u021biile au fost create cu ajutorul websequencediagrams.com<\/p>\n<p>Sursa: <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.2.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\/ro\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47Blocuri de construc\u021bie pentru aplica\u021bii distribuite. Prima aproximare | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/30908","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=30908"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/30908\/revisions"}],"predecessor-version":[{"id":162009,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/30908\/revisions\/162009"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/22886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=30908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=30908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=30908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}