{"id":80035,"date":"2020-05-02T13:42:54","date_gmt":"2020-05-02T11:42:54","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny"},"modified":"2020-05-02T13:42:54","modified_gmt":"2020-05-02T11:42:54","slug":"udobnye-arhitekturnye-patterny","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"Pattern architettonici pratici","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ciao, Habr!<\/p>\n<p><\/p>\n<p>Alla luce degli eventi attuali legati al coronavirus, diversi servizi online hanno registrato un aumento del carico. Ad esempio, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.independent.co.uk\/life-style\/gadgets-and-tech\/news\/coronavirus-ocado-down-app-website-stockpiling-food-online-delivery-a9402216.html\">una delle catene di distribuzione nel Regno Unito ha semplicemente chiuso il sito per gli ordini online<\/a><\/noindex>, poich\u00e9 non disponeva di risorse sufficienti. E non sempre \u00e8 possibile aumentare la capacit\u00e0 di un server semplicemente investendo in hardware pi\u00f9 potente, ma \u00e8 necessario gestire le richieste dei clienti (altrimenti andranno dai concorrenti).<\/p>\n<p><\/p>\n<p>In questo articolo parler\u00f2 brevemente delle pratiche popolari che possono consentire di creare un servizio rapido e resiliente. Tuttavia, tra gli approcci di sviluppo, ho selezionato solo quelli che ora <strong>sono facilmente accessibili<\/strong>. Per ciascun punto, avete gi\u00e0 a disposizione librerie pronte oppure avete la possibilit\u00e0 di risolvere il problema utilizzando una piattaforma cloud.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Scalabilit\u00e0 orizzontale<\/h1>\n<p><\/p>\n<p>Il punto pi\u00f9 semplice e noto. In linea di massima, esistono due schemi di distribuzione del carico: la scalabilit\u00e0 orizzontale e quella verticale. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C#%D0%93%D0%BE%D1%80%D0%B8%D0%B7%D0%BE%D0%BD%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\">Nel primo caso<\/a><\/noindex> si consente ai servizi di lavorare in parallelo, distribuendo cos\u00ec il carico tra di essi. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C#%D0%92%D0%B5%D1%80%D1%82%D0%B8%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\">Nel secondo<\/a><\/noindex> si ordinano server pi\u00f9 potenti o si ottimizza il codice.<\/p>\n<p><\/p>\n<p>Per esempio, prender\u00f2 un'astrazione di un cloud storage per file, simile a OwnCloud, OneDrive e cos\u00ec via.<\/p>\n<p><\/p>\n<p>L'immagine standard di uno schema simile \u00e8 qui sotto, ma essa dimostra solo la complessit\u00e0 del sistema. Dobbiamo trovare un modo per sincronizzare i servizi. Cosa succede se un utente salva un file dal tablet e poi vuole visualizzarlo sul telefono?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nLa differenza tra gli approcci: nel ridimensionamento verticale siamo pronti ad aumentare la potenza dei nodi, mentre in quello orizzontale aggiungiamo nuovi nodi per distribuire il carico.<\/p>\n<p><\/p>\n<h1 id=\"cqrs\">CQRS<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/martinfowler.com\/bliki\/CQRS.html\">Command Query Responsibility Segregation<\/a><\/noindex> \u00e8 un pattern piuttosto importante, poich\u00e9 permette a diversi clienti di connettersi a vari servizi e di ricevere flussi di eventi identici. I suoi vantaggi non sono cos\u00ec evidenti per un'applicazione semplice, ma sono fondamentali (e semplici) per un servizio ad alto carico. La sua essenza \u00e8 che i flussi di dati in entrata e in uscita non devono sovrapporsi. In altre parole, non puoi inviare una richiesta e aspettarti una risposta; invece, invii una richiesta al servizio A e ricevi una risposta nel servizio B.<\/p>\n<p><\/p>\n<p>Il primo vantaggio di questo approccio \u00e8 la possibilit\u00e0 di interruzione della connessione (in senso ampio) durante l'esecuzione di una richiesta lunga. Prendiamo come esempio una sequenza pi\u00f9 o meno standard:<\/p>\n<p><\/p>\n<ol>\n<li>Il cliente ha inviato una richiesta al server.<\/li>\n<li>Il server ha avviato un'elaborazione lunga.<\/li>\n<li>Il server ha risposto al cliente con il risultato.<\/li>\n<\/ol>\n<p><\/p>\n<p>Immaginiamo che al punto 2 si sia verificata un'interruzione della connessione (o la rete ha riavviato la connessione, o l'utente \u00e8 passato a un'altra pagina, interrompendo la connessione). In questo caso, sar\u00e0 difficile per il server inviare una risposta all'utente con le informazioni su cosa sia stato elaborato. Applicando CQRS, la sequenza sar\u00e0 un po' diversa:<\/p>\n<p><\/p>\n<ol>\n<li>Il cliente si \u00e8 iscritto agli aggiornamenti.<\/li>\n<li>Il cliente ha inviato una richiesta al server.<\/li>\n<li>Il server ha risposto \"richiesta ricevuta\".<\/li>\n<li>Il server ha risposto con il risultato attraverso il canale del \"1\".<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Come si pu\u00f2 vedere, lo schema \u00e8 leggermente pi\u00f9 complesso. Inoltre, l'approccio intuitivo request-response qui \u00e8 assente. Tuttavia, come si pu\u00f2 notare, l'interruzione della connessione durante l'elaborazione della richiesta non porter\u00e0 a un errore. Inoltre, se l'utente \u00e8 realmente connesso al servizio da pi\u00f9 dispositivi (ad esempio, da un telefono cellulare e da un tablet), \u00e8 possibile fare in modo che la risposta arrivi a entrambi i dispositivi.<\/p>\n<p><\/p>\n<p>\u00c8 interessante notare che il codice per gestire i messaggi in arrivo diventa simile (non al 100%) sia per gli eventi influenzati dal cliente stesso, sia per gli altri eventi, inclusi quelli provenienti da altri clienti.<\/p>\n<p><\/p>\n<p>Tuttavia, nella realt\u00e0, otteniamo ulteriori vantaggi poich\u00e9 il flusso unidirezionale pu\u00f2 essere gestito in uno stile funzionale (utilizzando RX e analoghi). Questo \u00e8 un vantaggio significativo, poich\u00e9 in sostanza l'applicazione pu\u00f2 essere realizzata in modo completamente reattivo, utilizzando anche un approccio funzionale. Per le applicazioni pi\u00f9 complesse, questo pu\u00f2 ridurre notevolmente le risorse necessarie per lo sviluppo e la manutenzione.<\/p>\n<p><\/p>\n<p>Se si combina questo approccio con la scalabilit\u00e0 orizzontale, otteniamo anche la possibilit\u00e0 di inviare richieste a un server e ricevere risposte da un altro. In questo modo, il cliente pu\u00f2 scegliere il servizio pi\u00f9 conveniente per lui, mentre il sistema interno riesce comunque a gestire correttamente gli eventi.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Event Sourcing<\/h1>\n<p><\/p>\n<p>Come sapete, una delle caratteristiche principali di un sistema distribuito \u00e8 l'assenza di un tempo comune e di una sezione critica condivisa. Per un singolo processo, potete eseguire la sincronizzazione (sugli stessi mutex), all'interno della quale siete certi che nessun altro stia eseguendo quel codice. Tuttavia, per un sistema distribuito, ci\u00f2 \u00e8 pericoloso, poich\u00e9 comporta delle spese generali e compromette l'intero vantaggio della scalabilit\u00e0: tutti i componenti dovranno comunque aspettare uno.<\/p>\n<p><\/p>\n<p>Da ci\u00f2 deriva un fatto importante: un sistema distribuito veloce non pu\u00f2 essere sincronizzato, altrimenti ridurremo le prestazioni. D'altra parte, spesso \u00e8 necessaria una certa coerenza dei componenti. Per questo motivo, si pu\u00f2 adottare l'approccio della <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, dove si garantisce che, in assenza di modifiche ai dati, dopo un certo intervallo di tempo dall'ultimo aggiornamento (\u00abin fin dei conti\u00bb), tutte le richieste restituiranno l'ultimo valore aggiornato.<\/p>\n<p><\/p>\n<p>\u00c8 importante comprendere che per i database classici si applica spesso <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">coerenza rigorosa<\/a><\/noindex>, dove ogni nodo possiede le stesse informazioni (questo si ottiene spesso quando una transazione \u00e8 considerata stabilita solo dopo la risposta del secondo server). Ci sono alcune eccezioni dovute ai livelli di isolamento, ma il concetto generale rimane lo stesso: puoi vivere in un mondo completamente coerente.<\/p>\n<p><\/p>\n<p>Tornando quindi al compito iniziale. Se una parte del sistema pu\u00f2 essere costruita con <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, si pu\u00f2 costruire il seguente schema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Caratteristiche chiave di questo approccio:<\/p>\n<p><\/p>\n<ul>\n<li>Ogni richiesta in entrata viene inserita in una coda.<\/li>\n<li>Durante l'elaborazione della richiesta, il servizio pu\u00f2 anche inserire task in altre code.<\/li>\n<li>Ogni evento in entrata ha un identificatore (necessario per la deduplicazione).<\/li>\n<li>\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u0441\u0445\u0435\u043c\u0435 &quot;append only&quot;. \u0418\u0437 \u043d\u0435\u0451 \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445.<\/li>\n<li>La coda funziona secondo lo schema FIFO (chiedo scusa per la tautologia). Se \u00e8 necessario eseguire in parallelo, bisogna spostare gli oggetti in diverse code in uno degli stadi.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ricordo che stiamo considerando il caso di uno spazio di archiviazione online. In questo caso, il sistema apparir\u00e0 all'incirca cos\u00ec:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 importante notare che i servizi nel diagramma non devono necessariamente rappresentare server separati. Anche i processi possono essere gli stessi. Ci\u00f2 che conta \u00e8 che, ideologicamente, queste cose sono separate in modo da poter facilmente applicare la scalabilit\u00e0 orizzontale.<\/p>\n<p><\/p>\n<p>Per due utenti, lo schema apparir\u00e0 cos\u00ec (i servizi destinati a diversi utenti sono contrassegnati con colori diversi):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I vantaggi di una simile combinazione:<\/p>\n<p><\/p>\n<ul>\n<li>I servizi di elaborazione delle informazioni sono separati. Anche le code sono separate. Se dobbiamo aumentare la capacit\u00e0 del sistema, basta avviare pi\u00f9 servizi su un numero maggiore di server.<\/li>\n<li>Quando riceviamo informazioni dall'utente, non \u00e8 necessario attendere il salvataggio completo dei dati. Al contrario, \u00e8 sufficiente rispondere \u00abok\u00bb e iniziare a lavorare gradualmente. Inoltre, la coda attenua i picchi, poich\u00e9 l'aggiunta di un nuovo oggetto avviene rapidamente, evitando all'utente di attendere un passaggio completo attraverso l'intero ciclo.<\/li>\n<li>Per esempio, ho aggiunto un servizio di deduplicazione che cerca di unire file identici. Se lavora a lungo in caso di 1%, il cliente praticamente non se ne accorger\u00e0 (vedi sopra), il che \u00e8 un grande vantaggio, poich\u00e9 da noi non \u00e8 richiesta una velocit\u00e0 e un'affidabilit\u00e0 del cento per cento.<\/li>\n<\/ul>\n<p><\/p>\n<p>Tuttavia, sono subito evidenti anche i contro:<\/p>\n<p><\/p>\n<ul>\n<li>La nostra sistema ha perso la rigorosa coerenza. Questo significa che, per esempio, se ci si iscrive a vari servizi, \u00e8 teoricamente possibile ricevere stati diversi (poich\u00e9 uno dei servizi potrebbe non riuscire a ricevere la notifica dalla coda interna). Come ulteriore conseguenza, ora il sistema non ha un tempo comune. Non \u00e8 possibile, quindi, ordinare tutti gli eventi semplicemente in base all'orario di arrivo, poich\u00e9 gli orologi tra i server potrebbero non essere sincronizzati (per di pi\u00f9, avere lo stesso orario su due server \u00e8 un'utopia).<\/li>\n<li>Nessun evento pu\u00f2 ora essere semplicemente annullato (come si potrebbe fare con un database). Invece, \u00e8 necessario aggiungere un nuovo evento \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, che cambier\u00e0 l'ultimo stato necessario. Un esempio da un campo simile: senza riscrivere la cronologia (che \u00e8 svantaggioso in alcuni casi) in git non si pu\u00f2 annullare un commit, ma si pu\u00f2 fare un'operazione speciale <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">commit di rollback<\/a><\/noindex>, che in sostanza riporter\u00e0 semplicemente allo stato precedente. Tuttavia, nella cronologia rimarr\u00e0 sia il commit errato che il rollback.<\/li>\n<li>Lo schema dei dati pu\u00f2 cambiare da una release all'altra, ma ora non sar\u00e0 possibile aggiornare i vecchi eventi al nuovo standard (poich\u00e9 gli eventi non possono in linea generale essere modificati).<\/li>\n<\/ul>\n<p><\/p>\n<p>Come dimostrato, l'Event Sourcing si integra perfettamente con il CQRS. Anzi, implementare un sistema con code efficienti e facili da usare, ma senza separazione dei flussi di dati, \u00e8 gi\u00e0 di per s\u00e9 una sfida, in quanto dovranno essere aggiunti punti di sincronizzazione che annulleranno tutto il vantaggio delle code. Applicando entrambi gli approcci contemporaneamente, \u00e8 necessario apportare lievi modifiche al codice del programma. Nel nostro caso, quando un file viene inviato al server, la risposta restituisce solo \"ok\", il che significa semplicemente che \"l'operazione di aggiunta del file \u00e8 stata registrata\". Formalmente, questo non implica che i dati siano gi\u00e0 accessibili su altri dispositivi (ad esempio, il servizio di deduplica potrebbe ripristinare l'indice). Tuttavia, dopo un po', il cliente ricever\u00e0 una notifica del tipo \"il file X \u00e8 stato salvato\".<\/p>\n<p><\/p>\n<p>Come risultato:<\/p>\n<p><\/p>\n<ul>\n<li>Il numero di stati di invio dei file aumenta: invece del classico \"file inviato\", otteniamo due stati: \"file aggiunto alla coda sul server\" e \"file salvato nell'archivio\". Quest'ultimo indica che altri dispositivi possono iniziare a ricevere il file (tenendo conto che le code operano a velocit\u00e0 diverse).<\/li>\n<li>Poich\u00e9 le informazioni sull'invio ora arrivano attraverso diversi canali, \u00e8 necessario trovare soluzioni per ottenere lo stato di elaborazione del file. Di conseguenza: a differenza della classica richiesta-risposta, il cliente pu\u00f2 essere riavviato durante l'elaborazione del file, ma lo stato di tale elaborazione sar\u00e0 corretto. Questo punto funziona, essenzialmente, out of the box. Di conseguenza, ora siamo pi\u00f9 tolleranti ai fallimenti.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Come descritto sopra, nei sistemi con event sourcing non esiste una coerenza rigorosa. Questo significa che possiamo utilizzare pi\u00f9 archivi senza alcuna sincronizzazione tra di essi. Avvicinandoci al nostro compito, possiamo:<\/p>\n<p><\/p>\n<ul>\n<li>Separare i file per tipologia. Ad esempio, le immagini\/i video possono essere decodificati e possiamo scegliere un formato pi\u00f9 efficiente.<\/li>\n<li>Separare gli account per paese. A causa di molte leggi, questo potrebbe essere necessario, ma questo schema architetturale offre questa possibilit\u00e0 in modo automatico.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0435, \u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0443\u0436\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e, \u0430 \u043f\u043e\u0442\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0451. \u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u00ab\u043d\u0430 \u043b\u0435\u0442\u0443\u00bb \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e, \u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u043f\u043a\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><\/p>\n<ul>\n<li>\u0412 Event Source \u043a\u0430\u0436\u0434\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 (\u0432 \u0438\u0434\u0435\u0430\u043b\u0435 \u2014 \u043d\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u044e\u0449\u0438\u0439\u0441\u044f). \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0435 \u2014 id \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.<\/li>\n<li>\u0414\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 (\u043f\u0435\u0440\u0432\u043e\u0435 \u2014 \u044d\u0442\u043e \u0442\u043e, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0436\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u0432\u0442\u043e\u0440\u043e\u0435 \u2014 \u043d\u043e\u0432\u043e\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u043f\u043e\u043a\u0430 \u043f\u0443\u0441\u0442\u043e\u0435). \u0412\u0442\u043e\u0440\u0430\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f.<\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u0442\u043e\u0440\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c (\u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439).<\/li>\n<li>\u041a\u043e\u0433\u0434\u0430 \u043d\u043e\u0432\u0430\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0443\u0441\u0442\u0430 (\u0442.\u0435. \u0441\u0440\u0435\u0434\u043d\u044f\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043c\u0435\u0436\u0434\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438 \u0435\u0433\u043e \u0436\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u0430), \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u043d\u043e\u0432\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/li>\n<\/ul>\n<p><\/p>\n<p>Come si pu\u00f2 vedere, nel nostro sistema non c'\u00e8 mai stata e non c'\u00e8 una rigorosa coerenza. Esiste solo una coerenza eventuale, ovvero la garanzia che gli eventi vengano elaborati nello stesso ordine (tuttavia, con ritardi potenzialmente diversi). E, sfruttando questo, possiamo trasferire i dati senza interrompere il sistema dall'altra parte del mondo.<\/p>\n<p><\/p>\n<p>Pertanto, continuando con il nostro esempio di archiviazione online per i file, questa architettura ci offre gi\u00e0 diversi vantaggi:<\/p>\n<p><\/p>\n<ul>\n<li>Possiamo spostare gli oggetti pi\u00f9 vicino agli utenti, in modo dinamico. In questo modo possiamo migliorare la qualit\u00e0 del servizio. <\/li>\n<li>Possiamo memorizzare parte dei dati all'interno delle aziende. Ad esempio, gli utenti Enterprise spesso richiedono di mantenere i loro dati in data center sotto controllo (per evitare perdite di dati). Grazie allo sharding, possiamo facilmente supportare questo. E la questione diventa ancora pi\u00f9 semplice se il cliente dispone di un cloud compatibile (ad esempio, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-gb\/azure-stack\/asdk\/asdk-what-is?view=azs-1910\">Azure self hosted<\/a><\/noindex>).<\/li>\n<li>E la cosa pi\u00f9 importante \u00e8 che non siamo obbligati a farlo. Infatti, per cominciare, ci basterebbe avere un'unica repository per tutti gli account (per iniziare a lavorare pi\u00f9 rapidamente). E la caratteristica chiave di questo sistema \u00e8 che, sebbene sia scalabile, \u00e8 abbastanza semplice nelle fasi iniziali. Non \u00e8 necessario scrivere subito codice per gestire milioni di code indipendenti, ecc. Se in futuro sar\u00e0 necessario, si potr\u00e0 sempre fare.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Hosting di contenuti statici<\/h1>\n<p><\/p>\n<p>Questo punto potrebbe sembrare ovvio, ma \u00e8 comunque necessario per un'applicazione standard con carichi di lavoro considerevoli. La sua essenza \u00e8 semplice: tutto il contenuto statico viene distribuito non dallo stesso server in cui si trova l'applicazione, ma da server dedicati appositamente a questo scopo. Di conseguenza, queste operazioni vengono eseguite pi\u00f9 rapidamente (un condizionale nginx fornisce file in modo pi\u00f9 veloce e meno costoso rispetto a un server Java). Inoltre, l'architettura CDN (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Content Delivery Network<\/a><\/noindex>) consente di posizionare i nostri file pi\u00f9 vicino agli utenti finali, il che migliora l'esperienza d'uso del servizio.<\/p>\n<p><\/p>\n<p>Il pi\u00f9 semplice e standard esempio di contenuto statico \u00e8 un insieme di script e immagini per un sito web. Con questi \u00e8 tutto semplice: sono noti in anticipo e poi l'archivio viene caricato sui server CDN, da cui viene distribuito agli utenti finali.<\/p>\n<p><\/p>\n<p>Tuttavia, in realt\u00e0 \u00e8 possibile applicare un approccio simile a quello dell'architettura lambda per il contenuto statico. Torniamo al nostro compito (archiviazione online dei file), in cui dobbiamo distribuire file agli utenti. La soluzione pi\u00f9 semplice sarebbe creare un servizio che, per ogni richiesta dell'utente, esegue tutte le necessarie verifiche (autenticazione, ecc.) e poi scarica il file direttamente dal nostro archivio. Il principale svantaggio di questo approccio \u00e8 che il contenuto statico (e un file con una determinata revisione \u00e8 essenzialmente un contenuto statico) viene distribuito dallo stesso server che gestisce la logica aziendale. Invece, possiamo realizzare il seguente schema:<\/p>\n<p><\/p>\n<ul>\n<li>Il server fornisce un URL per il download. Questo pu\u00f2 avere la forma file_id + key, dove key \u00e8 una mini-firma digitale che conferisce accesso alla risorsa per le prossime 24 ore.<\/li>\n<li>La distribuzione dei file \u00e8 gestita da un semplice nginx con le seguenti opzioni:\n<ul>\n<li>Cache del contenuto. Poich\u00e9 questo servizio potrebbe trovarsi su un server dedicato, abbiamo previsto la possibilit\u00e0 di memorizzare sul disco tutti i file scaricati pi\u00f9 recenti.<\/li>\n<li>Verifica della chiave al momento della creazione della connessione<\/li>\n<\/ul>\n<\/li>\n<li>Facoltativo: elaborazione in streaming del contenuto. Ad esempio, se comprimiamo tutti i file nel servizio, \u00e8 possibile eseguire la decompressione direttamente in questo modulo. Di conseguenza: le operazioni di IO vengono eseguite dove \u00e8 pi\u00f9 opportuno. Un compressore in Java occuperebbe facilmente molta memoria extra, tuttavia riscrivere il servizio con logica commerciale in linguaggi come Rust\/C++ potrebbe rivelarsi poco efficace. Nel nostro caso, utilizziamo processi diversi (o addirittura servizi), il che consente di separare in modo abbastanza efficace la logica commerciale dalle operazioni di IO.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questo schema non assomiglia molto alla distribuzione di contenuti statici (poich\u00e9 non stiamo trasferendo l'intero pacchetto di statiche da nessuna parte), tuttavia, in realt\u00e0, tale approccio si occupa proprio della distribuzione di dati immutabili. Inoltre, questo schema pu\u00f2 essere generalizzato ad altri casi in cui il contenuto non \u00e8 solo statico, ma pu\u00f2 essere rappresentato come un insieme di blocchi immutabili e non eliminabili (anche se possono essere aggiunti).<\/p>\n<p><\/p>\n<p>\u041a\u0430\u043a \u0435\u0449\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 (\u0434\u043b\u044f \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f): \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441 Jenkins\/TeamCity, \u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u043e\u0431\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Java. \u041e\u0431\u0430 \u043e\u043d\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 Java-\u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0431\u0438\u043b\u0434\u043e\u0432, \u0442\u0430\u043a \u0438 \u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0443 \u043d\u0438\u0445 \u043e\u0431\u043e\u0438\u0445 \u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u0438\u0434\u0430 &quot;\u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b\/\u043f\u0430\u043f\u043a\u0443 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430&quot;. \u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440: \u0432\u044b\u0434\u0430\u0447\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u043a\u043e\u0433\u0434\u0430 \u0430\u0433\u0435\u043d\u0442 \u043d\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0430 \u0437\u0430 \u043d\u0435\u0433\u043e \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440), \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043b\u043e\u0433\u0430\u043c. \u0412\u0441\u0435 \u044d\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043d\u0430 IO. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u0437\u0430\u043e\u0434\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u043c\u0435\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0431\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0418 \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435, \u043f\u043e\u0434\u043e\u0431\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043c\u0443 \u0436\u0435 nginx&#8217;\u0443 \u043f\u043e \u0440\u043e\u0432\u043d\u043e \u0442\u043e\u0439 \u0436\u0435 \u0441\u0445\u0435\u043c\u0435 (\u0440\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043b\u044e\u0447 \u0434\u0430\u043d\u043d\u044b\u0445).<\/p>\n<p><\/p>\n<p>Tuttavia, se torniamo al nostro sistema, risulta una schematizzazione simile:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pattern architettonici pratici\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Come si pu\u00f2 vedere, il sistema \u00e8 diventato radicalmente pi\u00f9 complesso. Non \u00e8 pi\u00f9 solo un mini-processo che memorizza \u0444\u0430\u0439\u043b\u043e\u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. Ora richiede un supporto pi\u00f9 articolato, il controllo delle versioni API, ecc. Pertanto, dopo aver tracciato tutti i diagrammi, \u00e8 meglio valutare attentamente se vale la pena investire in tale scalabilit\u00e0. Tuttavia, se desiderate avere la possibilit\u00e0 di espandere il sistema (inclusa la gestione di un numero ancora maggiore di utenti), dovrete considerare soluzioni di questo tipo. Il risultato \u00e8 che l'architettura del sistema \u00e8 pronta ad affrontare un carico maggiore (praticamente ogni componente pu\u00f2 essere clonato per una scalabilit\u00e0 orizzontale). Il sistema pu\u00f2 essere aggiornato senza arrestarlo (alcune operazioni potrebbero solo rallentare leggermente).<\/p>\n<p><\/p>\n<p>Come gi\u00e0 accennato all'inizio, diversi servizi online stanno ora affrontando carichi aumentati. Alcuni di essi hanno smesso di funzionare correttamente. In sostanza, i sistemi hanno ceduto proprio nel momento in cui il business avrebbe dovuto generare guadagni. Quindi, invece di un'opzione di consegna posticipata o di offrire ai clienti \"pianificate la consegna nei prossimi mesi\", il sistema ha semplicemente detto \"andate dai competitor\". Questa \u00e8, appunto, la conseguenza di una bassa performance: le perdite si verificano proprio quando i profitti potrebbero essere al massimo.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Conclusione<\/h1>\n<p><\/p>\n<p>Tutti questi approcci erano gi\u00e0 noti in precedenza. Ad esempio, VK utilizza da tempo l'idea di Static Content Hosting per la distribuzione delle immagini. Molti giochi online adottano uno schema di Sharding per separare i giocatori per regioni o per suddividere le aree di gioco (se il mondo \u00e8 unico). L'approccio Event Sourcing \u00e8 ampiamente utilizzato nelle email. La maggior parte delle applicazioni di trading, dove i dati arrivano continuamente, sono in realt\u00e0 costruite su un approccio CQRS, per poter filtrare i dati ricevuti. Inoltre, la scalabilit\u00e0 orizzontale \u00e8 stata applicata da tempo in molti servizi.<\/p>\n<p><\/p>\n<p>Tuttavia, ci\u00f2 che \u00e8 pi\u00f9 importante, tutti questi modelli sono diventati molto facili da applicare nelle moderne applicazioni (se pertinenti, ovviamente). I cloud offrono Sharding e scalabilit\u00e0 orizzontale fin da subito, il che \u00e8 molto pi\u00f9 semplice rispetto all'ordinare server dedicati in vari data center da soli. CQRS \u00e8 diventato molto pi\u00f9 facile grazie allo sviluppo di librerie come RX. Dieci anni fa, pochi siti web erano in grado di supportare tutto ci\u00f2. Anche l'Event Sourcing si configura incredibilmente facilmente grazie ai contenitori gi\u00e0 pronti con Apache Kafka. Dieci anni fa sarebbe stata un'innovazione, ora \u00e8 una consuetudine. Allo stesso modo, anche l'hosting di contenuti statici: grazie a tecnologie pi\u00f9 accessibili (in parte perch\u00e9 esiste una documentazione dettagliata e una vasta banca di risposte), questo approccio \u00e8 diventato ancora pi\u00f9 semplice.<\/p>\n<p><\/p>\n<p>In sintesi, l'implementazione di vari complessi pattern architetturali \u00e8 diventata molto pi\u00f9 semplice, il che significa che vale la pena prenderli in considerazione in anticipo. Se in un'applicazione decennale si \u00e8 rinunciato a una delle soluzioni citate a causa dei costi elevati di implementazione e gestione, ora, in una nuova applicazione o dopo una refactoring, si pu\u00f2 creare un servizio che sia architettonicamente sia scalabile (dal punto di vista delle prestazioni), sia pronto per nuove richieste dai clienti (ad esempio, per la localizzazione dei dati personali).<\/p>\n<p><\/p>\n<p>E la cosa pi\u00f9 importante: per favore, non utilizzate questi approcci se avete un'applicazione semplice. S\u00ec, sono belli e interessanti, tuttavia per un sito con un picco di 100 visitatori si pu\u00f2 spesso fare a meno di un classico monolite (almeno dall'esterno, mentre all'interno tutto pu\u00f2 essere suddiviso in moduli, e cos\u00ec via).<\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dbtc\/blog\/499758\/\">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! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0432 \u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430 \u0441\u0430\u0439\u0442 \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0437\u0430\u043a\u0430\u0437\u0430\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e (\u0438\u043b\u0438 \u043e\u043d\u0438 \u0443\u0439\u0434\u0443\u0442 \u043a \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c). \u0412 \u044d\u0442\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":80036,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-80035","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0432 \u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430 \u0441\u0430\u0439\u0442 \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0437\u0430\u043a\u0430\u0437\u0430\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e (\u0438\u043b\u0438 \u043e\u043d\u0438 \u0443\u0439\u0434\u0443\u0442 \u043a \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c). \u0412 \u044d\u0442\u043e\u0439\" \/>\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\/udobnye-arhitekturnye-patterny\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\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\u0423\u0434\u043e\u0431\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0432 \u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430 \u0441\u0430\u0439\u0442 \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0437\u0430\u043a\u0430\u0437\u0430\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e (\u0438\u043b\u0438 \u043e\u043d\u0438 \u0443\u0439\u0434\u0443\u0442 \u043a \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c). \u0412 \u044d\u0442\u043e\u0439\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny\" \/>\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=\"2020-05-02T11:42:54+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-02T11:42:54+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\udd47Modelli architettonici convenienti | ProHoster","description":"Ciao, Habr! In seguito agli attuali eventi legati al coronavirus, molti servizi online stanno registrando un aumento del carico. Ad esempio, una delle catene di negozi nel Regno Unito ha semplicemente bloccato il sito di ordini online perch\u00e9 non disponeva delle risorse necessarie. E non sempre \u00e8 possibile accelerare il server semplicemente aggiungendo hardware pi\u00f9 potente; tuttavia, le richieste dei clienti devono essere gestite (altrimenti passeranno ai concorrenti). In questo","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","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\u0423\u0434\u043e\u0431\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0432 \u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430 \u0441\u0430\u0439\u0442 \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0437\u0430\u043a\u0430\u0437\u0430\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e (\u0438\u043b\u0438 \u043e\u043d\u0438 \u0443\u0439\u0434\u0443\u0442 \u043a \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c). \u0412 \u044d\u0442\u043e\u0439","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","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":"2020-05-02T11:42:54+00:00","article:modified_time":"2020-05-02T11:42:54+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"80035","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:26:40","updated":"2022-09-28 01:38:29"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/80035","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=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}