{"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\/it\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","title":{"rendered":"Blocchi fondamentali delle applicazioni distribuite. Secondo approccio","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Annuncio<\/strong><\/p>\n<p><\/p>\n<p><em>Colleghi, a met\u00e0 estate prevedo di pubblicare un altro ciclo di articoli sulla progettazione di sistemi di assistenza di massa: \u201cEsperimento VTrade\u201d \u2014 un tentativo di scrivere un framework per i sistemi di trading. Il ciclo analizzer\u00e0 la teoria e la pratica della costruzione di borse, aste e negozi. Alla fine dell'articolo vi invito a votare per gli argomenti che trovate pi\u00f9 interessanti.<br \/>\n<\/em><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Blocchi fondamentali delle applicazioni distribuite. Secondo approccio\" src=\"\/wp-content\/uploads\/2019\/04\/358996733e805327b587176f4f992aea.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questo \u00e8 l'articolo conclusivo del ciclo sulle applicazioni reattive distribuite in Erlang\/Elixir. In <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">articolo precedente<\/a><\/noindex> possiamo trovare le basi teoriche dell'architettura reattiva. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446108\/\">Il secondo articolo<\/a><\/noindex> illustra i principali modelli e meccanismi di costruzione di tali sistemi.<\/p>\n<p><\/p>\n<p>Oggi affronteremo le questioni relative all'evoluzione del codice e dei progetti in generale. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"organizaciya-servisov\">Organizzazione dei servizi<\/h2>\n<p><\/p>\n<p>Nella vita reale, durante lo sviluppo di un servizio, spesso \u00e8 necessario combinare diversi modelli di interazione all'interno di un unico controller. Ad esempio, il servizio users, che si occupa della gestione dei profili degli utenti del progetto, deve rispondere a richieste req-resp e comunicare aggiornamenti sui profili tramite pub-sub. Questo caso \u00e8 piuttosto semplice: per il messaging c'\u00e8 un unico controller che implementa la logica del servizio e pubblica aggiornamenti.<\/p>\n<p><\/p>\n<p>La situazione si complica quando dobbiamo implementare un servizio distribuito resistente ai guasti. Immaginiamo che i requisiti per users siano cambiati: <\/p>\n<p><\/p>\n<ol>\n<li>ora il servizio deve elaborare richieste su 5 nodi del cluster, <\/li>\n<li>essere in grado di eseguire compiti in background, <\/li>\n<li>nonch\u00e9 gestire dinamicamente gli elenchi di iscrizione agli aggiornamenti dei profili.<\/li>\n<\/ol>\n<p><\/p>\n<p><em>Nota:<\/em> Non consideriamo la questione della memorizzazione coerente e della replica dei dati. Supponiamo che queste problematiche siano state risolte in precedenza e che nel sistema esista gi\u00e0 uno strato di archiviazione affidabile e scalabile, e che i gestori abbiano meccanismi di interazione con esso.<\/p>\n<p><\/p>\n<p>La descrizione formale del servizio users \u00e8 diventata pi\u00f9 complessa. Dal punto di vista del programmatore, grazie all'uso del messaging, le modifiche sono minime. Per soddisfare il primo requisito, dobbiamo configurare il bilanciamento nel punto di scambio req-resp. <\/p>\n<p><\/p>\n<p>La necessit\u00e0 di elaborare compiti in background si presenta spesso. In users possono esserci controlli sui documenti degli utenti, elaborazione di media caricati o sincronizzazione dei dati con i social network. Questi compiti devono essere distribuiti in qualche modo all'interno del cluster e monitorati nel loro espletamento. Pertanto, abbiamo due opzioni per la risoluzione: o utilizzare il modello di distribuzione dei compiti dell'articolo precedente, o, se non va bene, scrivere un pianificatore di compiti personalizzato che gestisca il pool di elaboratori nel modo necessario. <\/p>\n<p><\/p>\n<p>Il punto 3 richiede un'estensione del modello pub-sub. E per l'implementazione, dopo aver creato il punto di scambio pub-sub, \u00e8 necessario avviare ulteriormente il controller di questo punto all'interno del nostro servizio. In questo modo, estraiamo logica di elaborazione delle iscrizioni e disiscrizioni dallo strato di messaging nella realizzazione di users.<\/p>\n<p><\/p>\n<p>Di conseguenza, la scomposizione del compito ha mostrato che per soddisfare i requisiti \u00e8 necessario avviare 5 istanze del servizio su nodi diversi e creare un ulteriore entit\u00e0: un controller pub-sub responsabile dell'iscrizione.<br \/>\nPer avviare 5 elaboratori non \u00e8 necessario modificare il codice del servizio. L'unica azione aggiuntiva \u00e8 la configurazione delle regole di bilanciamento sul punto di scambio, di cui parleremo pi\u00f9 avanti.<br \/>\n\u00c8 emersa anche una difficolt\u00e0 aggiuntiva: il controller pub-sub e il pianificatore di compiti personalizzato devono operare in una singola istanza. Ancora una volta, il servizio messaging, come fondamentale, deve fornire un meccanismo di scelta del leader.<\/p>\n<p><\/p>\n<h3 id=\"vybor-lidera\">Scelta del leader<\/h3>\n<p><\/p>\n<p>Nelle sistemazioni distribuite, la scelta del leader \u00e8 una procedura di designazione di un unico processo responsabile della pianificazione dell'elaborazione distribuita di qualche carico. <\/p>\n<p><\/p>\n<p>Nei sistemi non soggetti a centralizzazione, vengono applicati algoritmi universali e algoritmi basati su consenso, ad esempio paxos o raft.<br \/>\nPoich\u00e9 messaging \u00e8 un broker e un elemento centrale, conosce tutti i controller del servizio - candidati al ruolo di leader. Messaging pu\u00f2 designare un leader senza alcuna votazione.<\/p>\n<p><\/p>\n<p>Tutti i servizi, dopo l'avvio e la connessione al punto di scambio, ricevono un messaggio di sistema <code>#'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}<\/code>. Nel caso in cui <code>LeaderPid<\/code> corrisponde a <code>pid<\/code> del processo corrente, viene designato come leader, e l'elenco <code>Servers<\/code> include tutti i nodi e i loro parametri.<br \/>\nNel momento in cui compare un nuovo nodo e si disconnette un nodo funzionante del cluster, tutti i controller del servizio ricevono <code>#'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts}<\/code> e <code>#'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts}<\/code> rispettivamente.<\/p>\n<p><\/p>\n<p>In questo modo, tutti i componenti sono a conoscenza di tutte le modifiche, e nel cluster, in ogni momento, \u00e8 garantito che ci sia un solo leader.<\/p>\n<p><\/p>\n<h2 id=\"posredniki\">Intermediari<\/h2>\n<p><\/p>\n<p>Per implementare processi di elaborazione distribuiti complessi e per ottimizzare l'architettura esistente \u00e8 conveniente utilizzare degli intermediari.<br \/>\nPer evitare di modificare il codice dei servizi e risolvere, ad esempio, compiti di elaborazione aggiuntiva, instradamento o registrazione dei messaggi, \u00e8 possibile inserire un gestore proxy davanti al servizio, che eseguir\u00e0 tutto il lavoro aggiuntivo.<\/p>\n<p><\/p>\n<p>Un esempio classico di ottimizzazione pub-sub \u00e8 un'applicazione distribuita con un core aziendale che genera eventi di aggiornamento, come ad esempio il cambiamento dei prezzi sul mercato, e uno strato di accesso \u2014 N server che forniscono API websocket per i client web.<br \/>\nSe risolviamo la questione 'direttamente', il servizio al cliente appare nel modo seguente:<\/p>\n<p><\/p>\n<ul>\n<li>il cliente stabilisce connessioni con la piattaforma. Sul lato server, dove termina il traffico, viene avviato un processo che gestisce questa connessione.<\/li>\n<li>nel contesto del processo di gestione avviene l'autenticazione e l'iscrizione agli aggiornamenti. Il processo chiama il metodo subscribe per i topic.<\/li>\n<li>dopo la generazione di un evento nel core, esso viene recapitato ai processi che gestiscono le connessioni.<\/li>\n<\/ul>\n<p><\/p>\n<p>Immaginiamo di avere 50000 iscritti al topic 'news'. Gli iscritti sono distribuiti uniformemente su 5 server. Alla fine, ogni aggiornamento, arrivato al punto di scambio, verr\u00e0 replicato 50000 volte: 10000 volte su ogni server, in base al numero di iscritti su di esso. Non \u00e8 proprio un schema efficiente, vero?<br \/>\nPer migliorare la situazione, introduciamo un proxy che ha lo stesso nome del punto di scambio. Il registratore dei nomi globali deve essere in grado di restituire il processo pi\u00f9 vicino per nome, questo \u00e8 importante.<\/p>\n<p><\/p>\n<p>Avvieremo questo proxy sui server dello strato di accesso, e tutti i nostri processi che gestiscono l'API websocket si iscriveranno a esso, e non al punto di scambio pub-sub originale nel core. Il proxy si iscrive al core soltanto in caso di iscrizione unica e replica il messaggio ricevuto a tutti i suoi iscritti.<br \/>\nAlla fine, tra il core e i server di accesso verranno inoltrati 5 messaggi, invece di 50000.<\/p>\n<p><\/p>\n<h2 id=\"marshrutizaciya-i-balansirovka\">Instradamento e bilanciamento<\/h2>\n<p><\/p>\n<h3 id=\"req-resp\">Req-Resp<\/h3>\n<p><\/p>\n<p>Nell'attuale implementazione del messaging esistono 7 strategie per la distribuzione delle richieste:<\/p>\n<p><\/p>\n<ul>\n<li><code>default<\/code>. La richiesta viene inviata a tutti i controller.<\/li>\n<li><code>round-robin<\/code>. Si effettua un ciclo di elaborazione e distribuzione delle richieste tra i controller.<\/li>\n<li><code>consensus<\/code>. I controller che gestiscono il servizio sono divisi in un leader e seguaci. Le richieste vengono inviate solo al leader.<\/li>\n<li><code>consensus &amp; round-robin<\/code>. Nel gruppo c'\u00e8 un leader, ma le richieste vengono distribuite tra tutti i membri.<\/li>\n<li><code>sticky<\/code>. Viene calcolata una funzione hash e associata a un particolare gestore. Le richieste successive con questa firma vanno a questo stesso gestore.<\/li>\n<li><code>sticky-fun<\/code>. Durante l'inizializzazione del punto di scambio viene fornita anche una funzione per calcolare l'hash per <code>sticky<\/code> il bilanciamento.<\/li>\n<li><code>fun<\/code>. \u00c8 simile a sticky-fun, ma \u00e8 possibile anche reindirizzarlo, rifiutarlo o pre-elaborarlo. <\/li>\n<\/ul>\n<p><\/p>\n<p>La strategia di distribuzione \u00e8 definita durante l'inizializzazione del punto di scambio.<\/p>\n<p><\/p>\n<p>Oltre al bilanciamento, il messaging consente di contrassegnare le entit\u00e0. Esaminiamo i tipi di tag nel sistema:<\/p>\n<p><\/p>\n<ul>\n<li>Tag di connessione. Permette di capire tramite quale connessione sono arrivati gli eventi. Utilizzato quando il processo del controller si collega a un punto di scambio, ma con diverse chiavi di routing. <\/li>\n<li>Tag di servizio. Permette di raggruppare i gestori per un singolo servizio e ampliare le possibilit\u00e0 di routing e bilanciamento. Per il pattern req-resp, il routing \u00e8 lineare. Inviamo una richiesta al punto di scambio, che poi la inoltra al servizio. Ma se dobbiamo suddividere i gestori in gruppi logici, la suddivisione avviene tramite i tag. Specificando un tag, la richiesta verr\u00e0 indirizzata a un gruppo specifico di controller.<\/li>\n<li>Tag di richiesta. Permette di distinguere le risposte. Poich\u00e9 il nostro sistema \u00e8 asincrono, per elaborare le risposte del servizio \u00e8 necessario avere la possibilit\u00e0 di specificare il RequestTag durante l'invio della richiesta. Con questo possiamo capire a quale richiesta \u00e8 stata data risposta.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pub-sub\">Pub-sub<\/h3>\n<p><\/p>\n<p>Per pub-sub \u00e8 tutto un po' pi\u00f9 semplice. Abbiamo un punto di scambio al quale vengono pubblicati i messaggi. Il punto di scambio distribuisce i messaggi tra gli abbonati, che si sono iscritti alle chiavi di routing di loro interesse (si pu\u00f2 dire che \u00e8 analogo ai temi).<\/p>\n<p><\/p>\n<h2 id=\"masshtabiruemost-i-otkazoustoychivost\">Scalabilit\u00e0 e resilienza<\/h2>\n<p><\/p>\n<p>La scalabilit\u00e0 del sistema nel suo complesso dipende dal grado di scalabilit\u00e0 dei livelli e dei componenti del sistema:<\/p>\n<p><\/p>\n<ul>\n<li>I servizi si scalano aggiungendo ulteriori nodi con i gestori di questo servizio al cluster. Durante il processo di sperimentazione, \u00e8 possibile scegliere la politica di bilanciamento pi\u00f9 ottimale.<\/li>\n<li>Il servizio di messaging, nell'ambito di un cluster separato, di solito si scala o estraendo i punti di scambio particolarmente sovraccarichi su nodi separati del cluster, oppure aggiungendo processi proxy nelle zone del cluster particolarmente sovraccariche.<\/li>\n<li>La scalabilit\u00e0 dell'intero sistema come caratteristica dipende dalla flessibilit\u00e0 dell'architettura e dalla possibilit\u00e0 di unire singoli cluster in un'entit\u00e0 logica comune.<\/li>\n<\/ul>\n<p><\/p>\n<p>Il successo di un progetto dipende spesso dalla semplicit\u00e0 e dalla velocit\u00e0 di scalabilit\u00e0. Il messaging nell'implementazione attuale cresce insieme all'applicazione. Anche se non abbiamo a disposizione un cluster di 50-60 macchine, possiamo ricorrere alla federazione. Purtroppo, il tema della federazione va oltre l'ambito di questo articolo.<\/p>\n<p><\/p>\n<h2 id=\"rezervirovanie\">Ridondanza<\/h2>\n<p><\/p>\n<p>Nella discussione sul bilanciamento del carico abbiamo gi\u00e0 parlato della riserva dei controller dei servizi. Tuttavia, anche il messaging deve essere riservato. In caso di fallimento di un nodo o di una macchina, il messaging deve ripristinarsi automaticamente e nel minor tempo possibile.<\/p>\n<p><\/p>\n<p>Nei miei progetti utilizzo nodi aggiuntivi che raccolgono il carico in caso di guasto. In Erlang esiste un'implementazione standard della modalit\u00e0 distribuita per le applicazioni OTP. La modalit\u00e0 distribuita effettua proprio il ripristino in caso di guasto avviando l'applicazione non funzionante su un altro nodo precedentemente avviato. Il processo \u00e8 trasparente; dopo un guasto, l'applicazione si sposta automaticamente sul nodo di failover. Puoi leggere di pi\u00f9 su questa funzionalit\u00e0. <noindex><a rel=\"nofollow\" href=\"http:\/\/erlang.org\/doc\/design_principles\/distributed_applications.html\">qui<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2 id=\"proizvoditelnost\">Prestazioni<\/h2>\n<p><\/p>\n<p>Proviamo a confrontare, anche se in modo approssimativo, le prestazioni di rabbitmq e del nostro messaging personalizzato.<br \/>\nHo trovato <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.openstack.org\/developer\/performance-docs\/test_results\/mq\/rabbitmq\/cmsm\/index.html\">risultati ufficiali<\/a><\/noindex> dei test di rabbitmq del team openstack.<\/p>\n<p><\/p>\n<p>Nel punto 6.14.1.2.1.2.2 del documento originale \u00e8 riportato il risultato del RPC CAST:<br \/>\n<img decoding=\"async\" alt=\"Blocchi fondamentali delle applicazioni distribuite. Secondo approccio\" src=\"\/wp-content\/uploads\/2019\/04\/95f615d241d70a4523fe3c400179b8e6.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Preliminarmente, non faremo ulteriori configurazioni nel kernel del SO o nella erlang VM. Condizioni per il test:<\/p>\n<p><\/p>\n<ul>\n<li>erl opts: +A1 +sbtu.<\/li>\n<li>Il test all'interno di un singolo nodo erlang \u00e8 eseguito su un notebook con un vecchio i7 in versione mobile.<\/li>\n<li>I test cluster sono eseguiti su server con rete 10G.<\/li>\n<li>Il codice funziona in contenitori docker. Rete in modalit\u00e0 NAT.<\/li>\n<\/ul>\n<p><\/p>\n<p>Codice del test:<\/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>Scenario 1:<\/em> Il test viene eseguito su un laptop con un vecchio i7 mobile. Il test, il messaging e il servizio vengono eseguiti su un nodo all'interno di un \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 Docker:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Cicli sequenziali 10000 in ~0 secondi (26987 cicli\/s)\nCicli sequenziali 20000 in ~1 secondo (26915 cicli\/s)\nCicli sequenziali 100000 in ~4 secondi (26957 cicli\/s)\nCicli paralleli 2 100000 in ~2 secondi (44240 cicli\/s)\nCicli paralleli 4 100000 in ~2 secondi (53459 cicli\/s)\nCicli paralleli 10 100000 in ~2 secondi (52283 cicli\/s)\nCicli paralleli 100 100000 in ~3 secondi (49317 cicli\/s)<\/code><\/pre>\n<p><\/p>\n<p><em>Scenario 2<\/em>: 3 nodi in esecuzione su macchine diverse sotto Docker (NAT).<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Cicli sequenziali 10000 in ~1 secondo (8684 cicli\/s)\nCicli sequenziali 20000 in ~2 secondi (8424 cicli\/s)\nCicli sequenziali 100000 in ~12 secondi (8655 cicli\/s)\nCicli paralleli 2 100000 in ~7 secondi (15160 cicli\/s)\nCicli paralleli 4 100000 in ~5 secondi (19133 cicli\/s)\nCicli paralleli 10 100000 in ~4 secondi (24399 cicli\/s)\nCicli paralleli 100 100000 in ~3 secondi (34517 cicli\/s)<\/code><\/pre>\n<p><\/p>\n<p>In tutti i casi, l'utilizzo della CPU non ha superato il 250%<\/p>\n<p><\/p>\n<h2 id=\"itogi\">Conclusioni<\/h2>\n<p><\/p>\n<p>Spero che questo ciclo non appaia come un dumping mentale e che la mia esperienza possa portare un reale beneficio sia ai ricercatori di sistemi distribuiti che ai professionisti che sono all'inizio del percorso di costruzione di architetture distribuite per i loro sistemi aziendali e guardano con interesse a Erlang\/Elixir, ma si chiedono se ne valga la pena...<\/p>\n<p><\/p>\n<p>Foto <noindex><a rel=\"nofollow\" href=\"https:\/\/unsplash.com\/photos\/Q4bmoSPJM18\">@chuttersnap<\/a><\/noindex><\/p>\n<p class=\"for_users_only_msg\">Solo gli utenti registrati possono partecipare al sondaggio. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Accedi<\/a><\/noindex>, per favore.<\/p>\n<h2 class=\"default-block__polling-title\">Quali argomenti dovrei trattare con maggiore dettaglio nell'ambito del ciclo \"Esperimento VTrade\"?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Teoria: Mercati, ordini e durata degli ordini: DAY, GTD, GTC, IOC, FOK, MOO, MOC, LOO, LOC<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Libro degli ordini. Teoria e pratica dell'implementazione di un libro con raggruppamenti<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Visualizzazione del trading: Tick, barre, risoluzioni. Come immagazzinare e come comporre<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Back office. Pianificazione e sviluppo. Controllo del personale e investigazione di incidenti<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    API. Cerchiamo di capire quali interfacce servano e come realizzarle<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Archiviazione delle informazioni: PostgreSQL, Timescale, Tarantool nei sistemi di trading<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Reattivit\u00e0 nei sistemi di trading<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Altro. Scriver\u00f2 nei commenti<\/p>\n<\/li>\n<\/ul>\n<p>    Hanno votato 6 utenti. 4 utenti si sono astenuti.<br \/>\n<br \/>Fonte: <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.1.1 - 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\/it\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-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. \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\/it\/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\udd47Mattoni di applicazioni distribuite. Secondo approccio | ProHoster","description":"Annuncio Colleghi, a met\u00e0 estate ho in programma di pubblicare un altro ciclo di articoli sulla progettazione dei sistemi di servizio di massa: \u201cEsperimento VTrade\u201d \u2014 un tentativo di scrivere un framework per il trading.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-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. \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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/31124","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=31124"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/31124\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/23092"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=31124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=31124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=31124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}