{"id":52389,"date":"2019-11-07T00:00:00","date_gmt":"2019-11-06T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions"},"modified":"2020-02-18T14:00:05","modified_gmt":"2020-02-18T11:00:05","slug":"kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","title":{"rendered":"Come viene realizzata un'architettura web resiliente nella piattaforma Mail.ru Cloud Solutions","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/fe7af07f3ac5ca4e75009993b742293e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCiao, Habr! Sono Artem Karamychev, il responsabile del team di amministrazione dei sistemi. <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.Ru Cloud Solutions (MCS)<\/a><\/noindex>. Negli ultimi dodici mesi abbiamo lanciato molti nuovi prodotti. Abbiamo cercato di garantire che i servizi API fossero facilmente scalabili, resilienti e pronti a gestire un rapido aumento del carico degli utenti. La nostra piattaforma \u00e8 costruita su OpenStack e voglio raccontarvi quali problemi di resilienza dei componenti abbiamo dovuto affrontare per ottenere un sistema robusto. Penso che sar\u00e0 interessante per chi sviluppa anche prodotti su OpenStack.<\/p>\n<p>La resilienza complessiva della piattaforma \u00e8 composta dalla robustezza dei suoi componenti. Quindi, passeremo gradualmente attraverso tutti i livelli in cui abbiamo individuato rischi e li abbiamo mitigati.<\/p>\n<p>Puoi vedere la versione video di questa storia, originata da un intervento alla conferenza Uptime Day 4, organizzata da <noindex><a rel=\"nofollow\" href=\"http:\/\/www.itsumma.ru\">ITSumma<\/a><\/noindex>, su <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=3b06MVou-vg&amp;list=PLmXjIrLllpkjwuIGkzBkLbI7oHtUadmvZ&amp;index=5\">YouTube-Channel Uptime Community<\/a><\/noindex>. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Resilienza dell'architettura fisica<\/h2>\n<p>\nLa parte pubblica del cloud MCS si basa attualmente su due data center di livello Tier III, con una connessione in fibra ottica dedicata e riservata a livello fisico tramite percorsi diversi, con una capacit\u00e0 di 200 Gbit\/s. Il livello Tier III assicura il necessario livello di resilienza dell'infrastruttura fisica. <\/p>\n<p>La fibra ottica \u00e8 riservata sia a livello fisico che logico. Il processo di riservazione dei canali \u00e8 stato iterativo, con problemi occasionali, e stiamo costantemente migliorando la connessione tra i data center. <\/p>\n<blockquote><p>Ad esempio, di recente, durante dei lavori in un pozzetto vicino a uno dei data center, un escavatore ha colpito un tubo, all'interno del quale si trovavano sia il cavo in fibra ottica principale che quello di riserva. Il nostro canale resiliente con il data center \u00e8 risultato vulnerabile in un singolo punto, nel pozzetto. Pertanto, abbiamo perso parte dell'infrastruttura. Abbiamo tratto delle conclusioni e intrapreso una serie di azioni, tra cui la posa di ulteriore fibra ottica in un pozzetto adiacente.<\/p><\/blockquote>\n<p>\nNei data center ci sono punti di presenza dei fornitori di servizi di telecomunicazione, a cui trasmettiamo i nostri prefissi tramite BGP. Per ogni direzione di rete viene selezionata la metrica migliore, il che consente di garantire ai vari clienti la migliore qualit\u00e0 di connessione. Se la connessione tramite un fornitore si interrompe, riorganizziamo il nostro instradamento tramite fornitori disponibili.<\/p>\n<p>In caso di guasto del fornitore, passiamo automaticamente al successivo. In caso di guasto di uno dei data center, abbiamo una copia speculare dei nostri servizi nel secondo data center, che assorbe tutto il carico.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/295ca212f48dd074d834154666e5b0c3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Resilienza dell'infrastruttura fisica<\/i><\/p>\n<h2>Cosa usiamo per la resilienza a livello applicativo<\/h2>\n<p>\nIl nostro servizio \u00e8 costruito su un insieme di componenti open source. <\/p>\n<p><b>ExaBGP<\/b> \u2014 un servizio che implementa alcune funzionalit\u00e0 utilizzando il protocollo di instradamento dinamico basato su BGP. Lo utilizziamo attivamente per annunciare i nostri indirizzi IP pubblici, attraverso cui gli utenti accedono all'API.<\/p>\n<p><b>HAProxy<\/b> \u2014 un bilanciatore di carico ad alta intensit\u00e0, che consente di impostare regole molto flessibili per il bilanciamento del traffico a diversi livelli del modello OSI. Lo utilizziamo per il bilanciamento davanti a tutti i servizi: database, broker di messaggi, servizi API, servizi web, i nostri progetti interni \u2014 tutto \u00e8 gestito da HAProxy.<\/p>\n<p><b>API application<\/b> \u2014 un'applicazione web scritta in python, tramite la quale l'utente gestisce la propria infrastruttura, il proprio servizio.<\/p>\n<p><b>Worker application <\/b>(di seguito semplicemente worker) \u2014 nei servizi OpenStack, \u00e8 un demone infrastrutturale che consente di trasmettere comandi API all'infrastruttura. Ad esempio, la creazione di un disco avviene proprio nel worker, mentre la richiesta di creazione \u00e8 nell'API application. <\/p>\n<h2>Architettura standard di OpenStack Application<\/h2>\n<p>\nLa maggior parte dei servizi sviluppati per OpenStack cerca di seguire un'unica par\u00f2di. Il servizio in genere consiste di 2 parti: API e worker (esecutori backend). Di norma, l'API \u00e8 un'applicazione WSGI in python, che viene eseguita come processo autonomo (demone) o tramite un server web come Nginx o Apache. L'API gestisce la richiesta dell'utente e trasmette ulteriori istruzioni all'applicazione worker. La trasmissione avviene tramite un broker di messaggi, di solito RabbitMQ, mentre gli altri sono poco supportati. Quando i messaggi raggiungono il broker, vengono elaborati dai worker e, se necessario, restituiscono una risposta. <\/p>\n<p>Questa particolare architettura implica punti di guasto isolati: RabbitMQ e il database. Tuttavia, RabbitMQ \u00e8 isolato all'interno di un singolo servizio e, idealmente, pu\u00f2 essere dedicato a ciascun servizio. Pertanto, noi di MCS separiamo al massimo questi servizi, creando un database e un RabbitMQ separati per ogni progetto. Questo approccio \u00e8 vantaggioso perch\u00e9, in caso di guasti in alcuni punti vulnerabili, non si interrompe l'intero servizio, ma solo una sua parte.<\/p>\n<p>Il numero di applicazioni worker non \u00e8 limitato, quindi l'API pu\u00f2 facilmente scalare orizzontalmente attraverso i bilanciatori per aumentare le prestazioni e la tolleranza agli errori.<\/p>\n<blockquote><p>In alcuni servizi \u00e8 necessaria una coordinazione interna \u2014 quando si verificano operazioni complesse e sequenziali tra API e worker. In questo caso, si utilizza un centro di coordinazione unificato, un sistema cluster come Redis, Memcache, etcd, che permette a un worker di comunicare a un altro che questo compito \u00e8 assegnato a lui (\"tu, per favore, non occuparcene\"). Noi utilizziamo etcd. Di norma, i worker interagiscono attivamente con il database, scrivendo e leggendo informazioni. Come database utilizziamo mariadb, che si trova in un cluster multimaster.\n<\/p><\/blockquote>\n<p>\nQuesto classico servizio singolo \u00e8 organizzato in modo convenzionale per OpenStack. Pu\u00f2 essere visto come un sistema chiuso, per il quale sono chiari i metodi di scalabilit\u00e0 e tolleranza agli errori. Ad esempio, per garantire la tolleranza agli errori, \u00e8 sufficiente mettere un bilanciatore davanti all'API. La scalabilit\u00e0 dei worker \u00e8 ottenuta aumentando il loro numero. <\/p>\n<p>Il punto debole di tutto lo schema \u00e8 rappresentato da RabbitMQ e MariaDB. La loro architettura merita un articolo a parte. In questo articolo voglio concentrarmi sulla tolleranza agli errori dell'API.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/f39e5a8ae350864e311bf4db3b9c34b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Architettura Openstack Application. Bilanciamento e tolleranza agli errori della piattaforma cloud<\/i><\/p>\n<h2>Rendiamo il bilanciatore HAProxy tollerante agli errori con ExaBGP<\/h2>\n<p>\nPer garantire che le nostre API siano scalabili, veloci e tolleranti agli errori, abbiamo posto un bilanciatore davanti a loro. Abbiamo scelto HAProxy. A mio avviso, possiede tutte le caratteristiche necessarie per il nostro compito: bilanciamento a pi\u00f9 livelli OSI, interfaccia di gestione, flessibilit\u00e0 e scalabilit\u00e0, ampia gamma di metodi di bilanciamento, supporto per le tabelle di sessione.<\/p>\n<p>Il primo problema da risolvere \u00e8 la tolleranza agli errori del bilanciatore stesso. L'installazione di un bilanciatore crea anch'essa un punto di guasto: se il bilanciatore si guasta, il servizio crolla. Per evitare ci\u00f2, abbiamo utilizzato HAProxy insieme a ExaBGP.<\/p>\n<p>ExaBGP consente l'implementazione di un meccanismo di monitoraggio dello stato del servizio. Abbiamo utilizzato questo meccanismo per controllare il funzionamento di HAProxy e, in caso di problemi, disattivare il servizio HAProxy dal BGP. <\/p>\n<p><b>Schema ExaBGP+HAProxy<\/b><\/p>\n<ol>\n<li>Installiamo il software necessario, ExaBGP e HAProxy, su tre server. <\/li>\n<li>Su ciascuno dei server creiamo un'interfaccia loopback.<\/li>\n<li>Su tutti e tre i server configuriamo lo stesso indirizzo IP pubblico per questa interfaccia.<\/li>\n<li>L'indirizzo IP pubblico viene annunciato su Internet tramite ExaBGP. <\/li>\n<\/ol>\n<p>\nLa tolleranza agli errori \u00e8 raggiunta annunciando lo stesso indirizzo IP da tutti e tre i server. Dal punto di vista della rete, lo stesso indirizzo \u00e8 accessibile da tre diversi next hop. Il router vede tre percorsi identici e seleziona, in base alla propria metrica, il pi\u00f9 prioritario (di solito \u00e8 sempre lo stesso) e il traffico va solo su uno dei server. <\/p>\n<p>In caso di problemi con HAProxy o di guasto di un server, ExaBGP smette di annunciare il percorso e il traffico si sposta gradualmente su un altro server. <\/p>\n<p>Cos\u00ec abbiamo ottenuto la tolleranza agli errori del bilanciatore.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/9fba0718176dc1266f25a2c01ec87348.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Tolleranza agli errori dei bilanciatori HAProxy<\/i><\/p>\n<p>Lo schema risultante non \u00e8 ideale: abbiamo imparato a riservare HAProxy, ma non a distribuire il carico all'interno dei servizi. Pertanto, abbiamo leggermente ampliato questo schema: siamo passati a un bilanciamento tra pi\u00f9 indirizzi IP pubblici.<\/p>\n<h2>Bilanciamento basato su DNS pi\u00f9 BGP<\/h2>\n<p>\nRimane irrisolto il problema della distribuzione del carico davanti ai nostri HAProxy. Tuttavia, questo pu\u00f2 essere risolto piuttosto semplicemente, come abbiamo fatto noi.<\/p>\n<p>Per bilanciare tre server, saranno necessari 3 indirizzi IP pubblici e il buon vecchio DNS. Ognuno di questi indirizzi \u00e8 assegnato all'interfaccia loopback di ciascun HAProxy e annunciato su Internet. <\/p>\n<p>In OpenStack, per gestire le risorse, si utilizza un catalogo dei servizi, in cui si definisce l'endpoint API di ciascun servizio. In questo catalogo registriamo il nome di dominio \u2014 public.infra.mail.ru, che viene risolto tramite DNS in tre diversi indirizzi IP. Di conseguenza, otteniamo una distribuzione del carico tra i tre indirizzi tramite DNS. <\/p>\n<p>Tuttavia, poich\u00e9 non gestiamo le priorit\u00e0 di selezione del server durante l'annuncio degli indirizzi IP pubblici, finch\u00e9 non si tratta di bilanciamento. Di solito, verr\u00e0 selezionato solo un server in base alla anzianit\u00e0 dell'indirizzo IP, mentre gli altri due rimarranno inattivi poich\u00e9 non sono specificate metriche in BGP.<\/p>\n<p>Abbiamo iniziato a pubblicare le rotte tramite ExaBGP con metriche diverse. Ogni bilanciatore annuncia tutti e tre gli indirizzi IP pubblici, ma uno di essi, principale per quel bilanciatore, viene annunciato con la metrica minima. Cos\u00ec, finch\u00e9 tutti e tre i bilanciatori sono operativi, le richieste al primo indirizzo IP vanno al primo bilanciatore, le richieste al secondo al secondo, e al terzo al terzo.<\/p>\n<p>Cosa succede nel momento in cui uno dei bilanciatori si guasta? In caso di guasto di uno qualsiasi dei bilanciatori, l'indirizzo principale viene comunque annunciato dagli altri due, e il traffico tra di loro viene ridistribuito. In questo modo, restituiamo all'utente attraverso DNS diversi indirizzi IP. Attraverso il bilanciamento DNS e metriche diverse otteniamo una distribuzione uniforme del carico su tutti e tre i bilanciatori, senza compromettere la resilienza.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/1485367a934aea06b68c6d05c184d263.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Bilanciamento HAProxy basato su DNS + BGP<\/i><\/p>\n<h2>Interazione tra ExaBGP e HAProxy<\/h2>\n<p>\nQuindi, abbiamo implementato la resilienza in caso di uscita di un server, basata sulla cessazione dell'annuncio delle rotte. Ma HAProxy pu\u00f2 disattivarsi per altri motivi oltre al guasto del server: errori di amministrazione, malfunzionamenti interni del servizio. Vogliamo rimuovere il bilanciatore guasto dal carico anche in questi casi, e ci serve un altro meccanismo. <\/p>\n<p>Pertanto, ampliando lo schema precedente, abbiamo implementato un heartbeat tra ExaBGP e HAProxy. Questa \u00e8 un'implementazione software dell'interazione tra ExaBGP e HAProxy, in cui ExaBGP utilizza script personalizzati per controllare lo stato delle applicazioni.<\/p>\n<p>Per questo, nel file di configurazione di ExaBGP, \u00e8 necessario impostare un health checker che possa verificare lo stato di HAProxy. Nel nostro caso, abbiamo impostato il backend di health in HAProxy, mentre dal lato di ExaBGP controlliamo con una semplice richiesta GET. Se l'annuncio smette di avvenire, HAProxy probabilmente non funziona, e non \u00e8 necessario annunciarlo. <\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/d5cda30043fe02ab81355b28c0d83ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Controllo dello stato HAProxy<\/i><\/p>\n<h2>HAProxy Peers: sincronizzazione delle sessioni <\/h2>\n<p>\nLa prossima cosa da fare \u00e8 sincronizzare le sessioni. Quando si lavora attraverso bilanciatori distribuiti, \u00e8 difficile organizzare la conservazione delle informazioni sulle sessioni dei clienti. Ma HAProxy \u00e8 uno dei pochi bilanciatori in grado di farlo grazie alla funzionalit\u00e0 Peers, che consente di trasmettere tra diversi processi HAProxy le tabelle delle sessioni. <\/p>\n<p>Esistono diversi metodi di bilanciamento: semplici, come <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Round-robin_(%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)\">round-robin<\/a><\/noindex>, e avanzati, in cui viene memorizzata la sessione del cliente, e ogni volta finisce sullo stesso server di prima. Volevamo implementare la seconda opzione.<\/p>\n<p>In HAProxy, per mantenere le sessioni del cliente, si utilizzano stick-tables. Queste memorizzano l'indirizzo IP originale del cliente, l'indirizzo del target scelto (backend) e alcune informazioni di servizio. Di solito, le stick-table vengono utilizzate per salvare la coppia source-IP + destination-IP, il che \u00e8 particolarmente utile per le applicazioni che non possono trasmettere il contesto della sessione dell'utente quando cambiano bilanciatore, come nel caso del bilanciamento RoundRobin.<\/p>\n<p>Se si insegna alla stick-table a muoversi tra i diversi processi di HAProxy (tra i quali avviene il bilanciamento), i nostri bilanciatori potranno lavorare con un unico pool di stick-table. Questo abiliter\u00e0 uno switching senza soluzione di continuit\u00e0 della rete del cliente in caso di guasto di uno dei bilanciatori, e la gestione delle sessioni dei clienti continuer\u00e0 sugli stessi backend precedentemente selezionati.<\/p>\n<p>Per un corretto funzionamento deve essere risolto il problema dell'indirizzo IP di origine del bilanciatore da cui \u00e8 stata stabilita la sessione. Nel nostro caso, si tratta di un indirizzo dinamico sull'interfaccia loopback. <\/p>\n<p>Il corretto funzionamento dei peers si ottiene solo in determinate condizioni. Cio\u00e8, i timeout TCP devono essere sufficientemente grandi o il passaggio deve essere abbastanza veloce, affinch\u00e9 la sessione TCP non venga interrotta. Tuttavia, questo consente uno switching senza soluzione di continuit\u00e0. <\/p>\n<p>Nella nostra IaaS, abbiamo un servizio costruito con la stessa tecnologia. \u00c8 <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/app\/services\/infra\/balancers-list\/\">Load Balancer come servizio per OpenStack<\/a><\/noindex>, chiamato Octavia. Si basa su due processi HAProxy e supporta inizialmente i peers. In questo servizio, si sono dimostrati molto efficaci.<\/p>\n<p>Nell'immagine \u00e8 schematicamente rappresentato il movimento delle tabelle dei peers tra tre istanze HAProxy, con una configurazione proposta su come impostarlo:<\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/d31fab761da627923345b7ace7f0b943.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>HAProxy Peers (sincronizzazione delle sessioni)<\/i><\/p>\n<p>Se implementerete uno schema simile, \u00e8 necessario testare attentamente il suo funzionamento. Non \u00e8 garantito che funzioni allo stesso modo nel 100% dei casi. Ma, almeno, non perderete le stick-table quando \u00e8 necessario ricordare l'IP del cliente.<\/p>\n<h2>Limitazione del numero di richieste simultanee da un singolo cliente<\/h2>\n<p>\nQualsiasi servizio reso pubblico, compresi i nostri API, pu\u00f2 essere soggetto a picchi di richieste. Le cause possono variare, dagli errori degli utenti agli attacchi mirati. Periodicamente subiamo attacchi DDoS per indirizzo IP. I clienti spesso commettono errori nei loro script, causando mini-DDoS.<\/p>\n<p>In ogni caso, \u00e8 necessario prevedere una protezione aggiuntiva. Una soluzione ovvia \u00e8 limitare il numero di richieste alle API e risparmiare tempo di elaborazione per le richieste dannose.<\/p>\n<p>Per implementare tali limitazioni utilizziamo i rate limits, organizzati su HAProxy, tramite le stick tables. I limiti vengono configurati in modo semplice e consentono di limitare l'utente nel numero di richieste alle API. L'algoritmo memorizza l'indirizzo IP sorgente da cui vengono effettuate le richieste e limita il numero di richieste simultanee da un singolo utente. Naturalmente, abbiamo calcolato il profilo medio del carico sulle API per ogni servizio e stabilito un limite di circa 10 volte superiore a questo valore. Continuiamo a monitorare attentamente la situazione, tenendo il polso della situazione.<\/p>\n<p>Come si presenta in pratica? Abbiamo clienti che utilizzano costantemente le nostre API per il ridimensionamento automatico. Creano circa duecento- trecento macchine virtuali al mattino e le eliminano in serata. Per OpenStack, creare una macchina virtuale, specialmente con i servizi PaaS, richiede almeno 1000 richieste API, poich\u00e9 l'interazione tra i servizi avviene anch'essa tramite API. <\/p>\n<p>Tali flussi di lavoro generano un carico significativo. Abbiamo valutato questo carico, raccolto i picchi giornalieri, incrementati dieci volte, e questo \u00e8 diventato il nostro rate limit. Rimaniamo vigili. Spesso osserviamo bot e scanner che cercano di capire se abbiamo degli script CGA che possono essere eseguiti, e li blocchiamo attivamente.<\/p>\n<h2>Come aggiornare il codice senza che gli utenti se ne accorgano<\/h2>\n<p>\nImplementiamo la resilienza anche a livello di processi di distribuzione del codice. Durante i deploy possono verificarsi errori, ma possiamo minimizzare il loro impatto sulla disponibilit\u00e0 dei servizi.<\/p>\n<p>Aggiorniamo costantemente i nostri servizi e dobbiamo garantire un processo di aggiornamento della base di codice senza effetti per gli utenti. Questa sfida \u00e8 stata risolta utilizzando le funzionalit\u00e0 di gestione di HAProxy e implementando il Graceful Shutdown nei nostri servizi.<\/p>\n<p>Per affrontare questa problematica, \u00e8 necessario garantire la gestione del bilanciatore e una corretta disattivazione dei servizi:<\/p>\n<ul>\n<li>Nel caso di HAProxy, la gestione avviene attraverso un file di stats, che di fatto \u00e8 un socket e deve essere definito nella configurazione di HAProxy. Le istruzioni possono essere inviate tramite stdio. Tuttavia, il nostro principale strumento di controllo delle configurazioni \u00e8 ansible, che ha un modulo integrato per gestire HAProxy. Lo utilizziamo attivamente. <\/li>\n<li>La maggior parte dei nostri servizi API e Engine supporta tecnologie di graceful shutdown: durante lo spegnimento attendono il completamento della task in corso, sia essa una richiesta http o un qualche task di servizio. Lo stesso vale per il worker. Sa tutte le attivit\u00e0 che sta eseguendo e si ferma quando ha concluso con successo tutto. <\/li>\n<\/ul>\n<p>\nGrazie a questi due aspetti, il nostro algoritmo di deployment sicuro appare come segue.<\/p>\n<ol>\n<li>Lo sviluppatore compila un nuovo pacchetto di codice (per noi \u00e8 un RPM), lo testa nell'ambiente di sviluppo, lo testa nell'ambiente di staging e lo lascia nel repository di staging.<\/li>\n<li>Lo sviluppatore registra una richiesta di deployment con la massima descrizione dettagliata degli 'artefatti': versione del nuovo pacchetto, descrizione della nuova funzionalit\u00e0 e altri dettagli del deployment se necessario.<\/li>\n<li>L'amministratore di sistema inizia l'aggiornamento. Avvia il playbook Ansible, che a sua volta procede come segue: \n<ul>\n<li>Prende il pacchetto dal repository di staging e aggiorna la versione del pacchetto nel repository di produzione.<\/li>\n<li>Compila l'elenco dei backend del servizio che deve essere aggiornato.<\/li>\n<li>Disattiva il primo servizio da aggiornare in HAProxy e attende il completamento dei suoi processi. Grazie al graceful shutdown, siamo certi che tutte le richieste in corso dei clienti verranno completate con successo.<\/li>\n<li>Dopo l'arresto completo delle API, dei worker e lo spegnimento di HAProxy, si procede all'aggiornamento del codice.<\/li>\n<li>Ansible avvia i servizi.<\/li>\n<li>Per ciascun servizio verifica alcuni 'interruttori' che eseguono test di unit\u00e0 su una serie di test chiave predefiniti. Viene eseguita una verifica di base del nuovo codice.<\/li>\n<li>Se non sono emersi errori nel passaggio precedente, il backend viene attivato.<\/li>\n<li>Passiamo al backend successivo.<\/li>\n<\/ul>\n<\/li>\n<li>Dopo l'aggiornamento di tutti i backend, vengono eseguiti test funzionali. Se non sono sufficienti, lo sviluppatore esamina qualsiasi nuova funzionalit\u00e0 che ha implementato.<\/li>\n<\/ol>\n<p>\nCon questa deployment \u00e8 concluso.<\/p>\n<p><img decoding=\"async\" alt=\"Come viene realizzata un&#039;architettura web resiliente nella piattaforma Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/2d889fe1af33653e4bfebabe1cce6552.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ciclo di aggiornamento del servizio<\/i><\/p>\n<p>Questo schema non sarebbe praticabile se non avessimo una regola fondamentale. Mantenere in produzione sia la versione vecchia che quella nuova. Sin dall'inizio, durante lo sviluppo del software, si pianifica che anche se ci saranno modifiche nel database del servizio, non romperanno il codice precedente. Di conseguenza, si realizza un aggiornamento graduale del codice.<\/p>\n<h2>Conclusione<\/h2>\n<p>\nCondividendo i miei pensieri sull'architettura web resiliente, voglio ribadire i suoi punti chiave:<\/p>\n<ul>\n<li>resilienza fisica;<\/li>\n<li>resilienza di rete (bilanciatori, BGP);<\/li>\n<li>resilienza del software in uso e in sviluppo.<\/li>\n<\/ul>\n<p>\nA tutti un uptime stabile!<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/474180\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0410\u0440\u0442\u0435\u043c \u041a\u0430\u0440\u0430\u043c\u044b\u0448\u0435\u0432, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Mail.Ru Cloud Solutions (MCS). \u0417\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0433\u043e\u0434 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432. \u041c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b API-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c, \u0431\u044b\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u043c\u0438 \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u043a \u0431\u044b\u0441\u0442\u0440\u043e\u043c\u0443 \u0440\u043e\u0441\u0442\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041d\u0430\u0448\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 OpenStack, \u0438 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044c, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52389","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\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\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.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\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\".\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\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-11-06T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:05+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\udd47Come si realizza un'architettura web resiliente nella piattaforma Mail.ru Cloud Solutions | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","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\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster","og:description":".","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","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-11-06T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:05+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52389","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-24 03:27:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:44:43","updated":"2026-01-24 03:27:21","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\/52389","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=52389"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52389\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=52389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=52389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=52389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}