{"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\/it\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","title":{"rendered":"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" src=\"\/wp-content\/uploads\/2019\/04\/7ef485e452075775ce317b557671274c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nell'articolo precedente <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">abbiamo chiarito il corretto completamento dei programmi che utilizzano il mediastreamer.<\/a><\/noindex> Abbiamo esaminato le basi teoriche dell'architettura reattiva. \u00c8 giunto il momento di parlare dei flussi di dati, dei modi di implementazione dei sistemi reattivi Erlang\/Elixir e dei modelli di scambio di messaggi in essi:<\/p>\n<p><\/p>\n<ul>\n<li>Richiesta-risposta<\/li>\n<li>Risposta Richiesta-Chunked<\/li>\n<li>Risposta con Richiesta<\/li>\n<li>Pubblica-sottoscritta<\/li>\n<li>Pubblica-sottoscritta Inversa<\/li>\n<li>Distribuzione dei compiti<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"soa-msa-i-obmen-soobscheniyami\">SOA, MSA e scambio di messaggi<\/h2>\n<p><\/p>\n<p>SOA e MSA sono architetture di sistema che definiscono le regole per la costruzione dei sistemi, mentre il messaging fornisce i primitivi per la loro implementazione.<\/p>\n<p><\/p>\n<p>Non voglio promuovere un'architettura o l'altra per la costruzione dei sistemi. Sono a favore dell'adozione delle pratiche pi\u00f9 efficienti e utili per il progetto e il business specifico. Qualunque paradigma scegliamo, \u00e8 meglio creare i blocchi di sistema seguendo il modo Unix: componenti con una minima interconnessione, responsabili di entit\u00e0 separate. I metodi API eseguono azioni il pi\u00f9 semplici possibile con le entit\u00e0.<\/p>\n<p><\/p>\n<p>Il Messaging \u2012 come suggerisce il nome \u2012 \u00e8 un broker di messaggi. Il suo obiettivo principale \u00e8 ricevere e consegnare messaggi. Si occupa delle interfacce di invio delle informazioni, della formazione di canali logici di trasmissione delle informazioni all'interno del sistema, del routing e del bilanciamento, nonch\u00e9 della gestione dei guasti a livello di sistema.<br \/>\nIl messaging in fase di sviluppo non cerca di competere con rabbitmq o di sostituirlo. Le sue principali caratteristiche sono:<\/p>\n<p><\/p>\n<ul>\n<li>Distributed.<br \/>\nI punti di scambio possono essere creati su tutti i nodi del cluster, il pi\u00f9 vicino possibile al codice che li utilizza.<\/li>\n<li>Semplicit\u00e0.<br \/>\nOrientato alla minimizzazione del codice standard e alla facilit\u00e0 d'uso.<\/li>\n<li>Migliore performance.<br \/>\nNon stiamo cercando di replicare la funzionalit\u00e0 di rabbitmq, ma isoliamo solo il livello architettonico e di trasporto, che integriamo nel OTP nel modo pi\u00f9 semplice possibile, minimizzando i costi.<\/li>\n<li>Flessibilit\u00e0.<br \/>\nOgni servizio pu\u00f2 combinare molti modelli di scambio.<\/li>\n<li>Resilienza, incorporata nel design.<\/li>\n<li>Scalabilit\u00e0.<br \/>\nIl messaging cresce insieme all'applicazione. Con l'aumento del carico, \u00e8 possibile spostare i punti di scambio su macchine separate.<\/li>\n<\/ul>\n<p><\/p>\n<p><em>Nota.<\/em> Dal punto di vista dell'organizzazione del codice, per sistemi complessi su Erlang\/Elixir, i meta-progetti sono molto adatti. Tutto il codice del progetto si trova in un unico repository \u2012 un progetto ombrello. In questo modo, i microservizi sono massimamente isolati e svolgono operazioni semplici, responsabili di un'entit\u00e0 separata. Con questo approccio \u00e8 facile mantenere l'API dell'intero sistema, apportare modifiche e scrivere test unitari e di integrazione in modo conveniente.<\/p>\n<p><\/p>\n<p>I componenti del sistema interagiscono direttamente o tramite un broker. Da un punto di vista del messaging, ogni servizio ha diverse fasi di vita:<\/p>\n<p><\/p>\n<ul>\n<li>Inizializzazione del servizio.<br \/>\nIn questa fase avviene la configurazione e l'avvio del processo di servizio eseguibile e delle dipendenze.<\/li>\n<li>Creazione di un punto di scambio.<br \/>\nIl servizio pu\u00f2 utilizzare un punto di scambio statico definito nella configurazione del nodo, oppure creare punti di scambio dinamicamente. <\/li>\n<li>Registrazione del servizio.<br \/>\nAffinch\u00e9 il servizio possa gestire le richieste, deve essere registrato al punto di scambio.<\/li>\n<li>Funzionamento normale.<br \/>\nIl servizio svolge lavoro utile.<\/li>\n<li>Termine del lavoro.<br \/>\nEsistono 2 tipi di termine del lavoro: normale e anomalo. Nel primo caso, il servizio si disconnette dal punto di scambio e si ferma. In caso di anomalie, il messaging esegue uno dei percorsi di gestione degli errori.<\/li>\n<\/ul>\n<p><\/p>\n<p>Sembra piuttosto complesso, ma nel codice non \u00e8 tutto cos\u00ec spaventoso. Esempi di codice con commenti saranno presentati nell'analisi dei template poco dopo.<\/p>\n<p><\/p>\n<h2 id=\"exchanges\">Exchanges<\/h2>\n<p><\/p>\n<p>Il punto di scambio \u00e8 un processo di messaging che implementa la logica di interazione con i componenti nell'ambito del template di scambio di messaggi. In tutti gli esempi presenti di seguito, i componenti interagiscono tramite punti di scambio, la cui combinazione forma il messaging.<\/p>\n<p><\/p>\n<h2 id=\"message-exchange-patterns-meps\">Schemi di scambio messaggi (MEPs)<\/h2>\n<p><\/p>\n<p>Globalmente, gli schemi di scambio possono essere suddivisi in bidirezionali e unidirezionali. I primi implicano una risposta al messaggio ricevuto, i secondi no. Un esempio classico di schema bidirezionale nell'architettura client-server \u00e8 il template Request-response. Esaminiamo il template e le sue modifiche.<\/p>\n<p><\/p>\n<h3 id=\"requestresponse-ili-rpc\">Request\u2013response o RPC<\/h3>\n<p><\/p>\n<p>L'RPC viene utilizzato quando abbiamo bisogno di ricevere una risposta da un altro processo. Questo processo pu\u00f2 essere avviato sullo stesso nodo o trovarsi su un altro continente. Di seguito \u00e8 mostrato un schema di interazione tra il client e <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/it\/server\/dts-los-angeles\/\"   title=\"server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3483\">server<\/a> attraverso il messaging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" src=\"\/wp-content\/uploads\/2019\/04\/091725fc108d6ce1a5fc9ae866e2c395.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poich\u00e9 il messaging \u00e8 completamente asincrono, per il client lo scambio si divide in 2 fasi:<\/p>\n<p><\/p>\n<ol>\n<li>\n<p>Invio della richiesta<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).<\/code><\/pre>\n<p><\/p>\n<p><em>Scambio<\/em> \u2012 nome unico del punto di scambio<br \/>\n<em>ResponseMatchingTag<\/em> \u2012 etichetta locale per l'elaborazione della risposta. Ad esempio, nel caso di invio di pi\u00f9 richieste identiche, appartenenti a utenti diversi.<br \/>\n<em>RequestDefinition<\/em> \u2012 corpo della richiesta<br \/>\n<em>HandlerProcess<\/em> \u2012 PID del gestore. A questo processo arriver\u00e0 la risposta dal server.<\/p>\n<p>\n<\/li>\n<li>\n<p>Elaborazione della risposta<\/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 risposta del server.<\/p>\n<p>\n<\/li>\n<\/ol>\n<p><\/p>\n<p>Per il server, il processo consiste anche in 2 fasi:<\/p>\n<p><\/p>\n<ol>\n<li>Inizializzazione del punto di scambio<\/li>\n<li>Elaborazione delle richieste in arrivo<\/li>\n<\/ol>\n<p><\/p>\n<p>Illustriamo questo modello con un codice. Supponiamo di dover implementare un semplice servizio che fornisce un unico metodo per l'orario esatto.<\/p>\n<p><\/p>\n<h4 id=\"kod-servera\">Codice del server<\/h4>\n<p><\/p>\n<p>Portiamo la definizione dell'API del servizio in api.hrl:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% =====================================================\n%%  entit\u00e0\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%%  metodi\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>Definiamo il controllore del servizio in time_controller.erl<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% L'esempio mostra solo il codice significativo. Inserendolo nel modello gen_server si pu\u00f2 ottenere un servizio funzionante.\n\n%% inizializzazione gen_server\ninit(Args) -&gt;\n  %% connessione al punto di scambio\n  messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())\n  {ok, #{}}.\n\n%% elaborazione dell'evento di perdita di connessione con il punto di scambio. Questo stesso evento arriva se il punto di scambio non \u00e8 ancora stato avviato.\nhandle_info(#exchange_die{exchange = ?EXCHANGE}, State) -&gt;\n  erlang:send(self(), monitor_exchange),\n  {noreply, State};\n\n%% elaborazione API\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%% conclusione del lavoro 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\">Codice del client<\/h4>\n<p><\/p>\n<p>Per inviare una richiesta al servizio, in qualsiasi punto del client \u00e8 possibile chiamare l'API di richiesta di 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; %% logica di ripetizione o errore\nend<\/code><\/pre>\n<p><\/p>\n<p>In un sistema distribuito, la configurazione dei componenti pu\u00f2 essere variabile e al momento della richiesta, messaging potrebbe non essere ancora avviato, oppure il controllore del servizio potrebbe non essere pronto a gestire la richiesta. Pertanto, \u00e8 necessario controllare la risposta di messaging e gestire il caso di errore.<br \/>\nDopo l'invio riuscito, al client arriver\u00e0 una risposta o un errore dal servizio.<br \/>\nGestiamo entrambi i casi in 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\">Risposta Richiesta-Chunked<\/h3>\n<p><\/p>\n<p>\u00c8 meglio evitare di inviare messaggi di grandi dimensioni. Questo influisce sulla reattivit\u00e0 e sulla stabilit\u00e0 dell'intero sistema. Se la risposta a una richiesta occupa molta memoria, \u00e8 obbligatorio suddividerla in parti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" src=\"\/wp-content\/uploads\/2019\/04\/bd60742a933a8e4e3eeaf7f4adf00f2a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ecco un paio di esempi di tali casi:<\/p>\n<p><\/p>\n<ul>\n<li>I componenti scambiano dati binari, ad esempio file. Suddividere la risposta in piccole parti aiuta a lavorare in modo efficiente con file di qualsiasi dimensione senza incorrere in problemi di sovraccarico della memoria.<\/li>\n<li>Elencazioni. Ad esempio, dobbiamo selezionare tutte le righe da un enorme tavolo nel database e trasmetterle a un altro componente.<\/li>\n<\/ul>\n<p><\/p>\n<p>Chiamo queste risposte un treno. In ogni caso, 1024 messaggi da 1 MB sono migliori di un singolo messaggio di 1 GB. <\/p>\n<p><\/p>\n<p>In un cluster Erlang, otteniamo un ulteriore vantaggio: ridurre il carico sul punto di scambio e sulla rete, poich\u00e9 le risposte vengono inviate immediatamente al destinatario, bypassando il punto di scambio.<\/p>\n<p><\/p>\n<h3 id=\"response-with-request\">Risposta con Richiesta<\/h3>\n<p><\/p>\n<p>Questa \u00e8 una modifica abbastanza rara del pattern RPC per costruire sistemi di dialogo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" 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\">Pubblica-ritira (data distribution tree)<\/h3>\n<p><\/p>\n<p>I sistemi eventi-oriented forniscono i dati ai consumatori man mano che diventano disponibili. In questo modo, questi sistemi sono pi\u00f9 propensi a un modello push piuttosto che pull o poll. Questa caratteristica consente di non sprecare risorse richiedendo costantemente e aspettando i dati.<br \/>\nL'immagine mostra il processo di diffusione del messaggio ai consumatori che si sono iscritti a un determinato argomento.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" src=\"\/wp-content\/uploads\/2019\/04\/e211d5dcfeb5ce8513699eac8e3b6d84.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esempi classici di utilizzo di questo modello includono la distribuzione di stati: del mondo di gioco nei videogiochi, dei dati di mercato nelle borse, delle informazioni utili nei data feed.<\/p>\n<p><\/p>\n<p>Consideriamo il codice dell'abbonato:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">init(_Args) -&gt;\n  %% ci iscriviamo al punto di scambio, chiave = key\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {ok, #{}}.\n\nhandle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) -&gt;\n  %% se il punto di scambio non \u00e8 disponibile, proviamo a riconnetterci\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {noreply, State};\n\n%% trattiamo i messaggi in arrivo\nhandle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) -&gt;\n  ?debugVal(Msg),\n  {noreply, State};\n\n%% al fermo del consumatore - ci disconnettiamo dal punto di scambio\nterminate(_Reason, _State) -&gt;\n  messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p>La fonte pu\u00f2 invocare la funzione di pubblicazione di un messaggio in qualsiasi punto conveniente:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:publish_message(Exchange, Key, Message).<\/code><\/pre>\n<p><\/p>\n<p><em>Scambio<\/em> \u2012 nome del punto di scambio,<br \/>\n<em>Key<\/em> \u2012 chiave di instradamento<br \/>\n<em>Messaggio<\/em> \u2012 payload<\/p>\n<p><\/p>\n<h2 id=\"inverted-publish-subscribe\">Pubblica-sottoscritta Inversa<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" src=\"\/wp-content\/uploads\/2019\/04\/2ef7cd7de459455937bdcfa8a11fd028.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Attivando pub-sub, \u00e8 possibile ottenere uno schema utile per il logging. L'insieme di fonti e consumatori pu\u00f2 essere completamente diverso. Nella figura \u00e8 presentato un caso con un solo consumatore e molte fonti.<\/p>\n<p><\/p>\n<h2 id=\"task-distribution-pattern\">Schema di distribuzione del carico<\/h2>\n<p><\/p>\n<p>Quasi in ogni progetto si presentano attivit\u00e0 di elaborazione posticipata, come la generazione di report, la consegna di notifiche, l'ottenimento di dati da sistemi esterni. La capacit\u00e0 del sistema che esegue queste attivit\u00e0 \u00e8 facilmente scalabile aggiungendo elaboratori. Tutto ci\u00f2 che ci resta da fare \u00e8 formare un cluster di elaboratori e distribuire uniformemente i compiti tra di essi.<\/p>\n<p><\/p>\n<p>Consideriamo le situazioni che si presentano con 3 elaboratori. Gi\u00e0 nella fase di distribuzione dei compiti emerge la questione dell\u2019equit\u00e0 nella distribuzione e del sovraccarico degli elaboratori. L'equit\u00e0 sar\u00e0 garantita dalla distribuzione round-robin e per evitare situazioni di sovraccarico degli elaboratori, introdurremo un limite <em>prefetch_limit<\/em>. Nelle fasi transitorie <em>prefetch_limit<\/em> non permetter\u00e0 a un elaboratore di ricevere tutti i compiti.<\/p>\n<p><\/p>\n<p>Messaging gestisce le code e la priorit\u00e0 di elaborazione. Gli elaboratori ricevono i compiti man mano che arrivano. L'esecuzione di un compito pu\u00f2 concludersi con successo oppure con un fallimento:<\/p>\n<p><\/p>\n<ul>\n<li><code>messaging:ack(Tack)<\/code> \u2012 viene chiamato in caso di elaborazione riuscita del messaggio<\/li>\n<li><code>messaging:nack(Tack)<\/code> \u2012 viene chiamato in tutte le situazioni anomale. Dopo il ritorno del compito, messaging lo passer\u00e0 a un altro elaboratore.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione\" src=\"\/wp-content\/uploads\/2019\/04\/c2c632b6411247ee8b0dcfb3250a4503.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Supponiamo che, durante l'elaborazione di tre compiti, si verifichi un complesso fallimento: l'elaboratore 1, dopo aver ricevuto il compito, \u00e8 andato in crash senza riuscire a comunicare nulla al punto di scambio. In questo caso, il punto di scambio, dopo il timeout di ack, passer\u00e0 il compito a un altro elaboratore. L'elaboratore 3, per qualche motivo, ha rifiutato il compito e ha inviato nack, alla fine il compito \u00e8 passato a un altro elaboratore che l'ha completato con successo.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnyy-itog\">Risultato preliminare<\/h2>\n<p><\/p>\n<p>Abbiamo esaminato i principali elementi costitutivi dei sistemi distribuiti e abbiamo acquisito una comprensione di base della loro applicazione in Erlang\/Elixir.<\/p>\n<p><\/p>\n<p>Combinando gli schemi di base, \u00e8 possibile costruire paradigmi complessi per affrontare i compiti emergenti.<\/p>\n<p><\/p>\n<p>Nell'ultima parte del ciclo esamineremo questioni generali riguardanti l'organizzazione dei servizi, la routizzazione e il bilanciamento, e discuteremo anche l'aspetto pratico della scalabilit\u00e0 e della resilienza dei sistemi.<\/p>\n<p><\/p>\n<p>Fine della seconda parte.<\/p>\n<p><\/p>\n<p>Foto <noindex>Marius Christensen<\/noindex><br \/>\nLe illustrazioni sono state preparate con websequencediagrams.com<\/p>\n<p>Fonte: <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.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\/it\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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\udd47Blocchi di costruzione delle applicazioni distribuite. Prima approssimazione | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/30908","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=30908"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/30908\/revisions"}],"predecessor-version":[{"id":162009,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/30908\/revisions\/162009"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/22886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=30908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=30908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=30908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}