{"id":35906,"date":"2019-10-31T22:07:29","date_gmt":"2019-10-31T19:07:29","guid":{"rendered":"https:\/\/prohoster.info\/blog\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\/"},"modified":"2019-10-31T22:07:29","modified_gmt":"2019-10-31T19:07:29","slug":"perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","title":{"rendered":"Transizione da monolite a microservizi: storia e pratica","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>In questo articolo parler\u00f2 di come il progetto su cui lavoro si \u00e8 trasformato da un grande monolite in un insieme di microservizi.<\/p>\n<p>Il progetto ha iniziato la sua storia molto tempo fa, all'inizio degli anni 2000. Le prime versioni furono scritte in Visual Basic 6. Con il passare del tempo, \u00e8 diventato chiaro che lo sviluppo in questo linguaggio sarebbe stato difficile da mantenere in futuro, poich\u00e9 l'IDE e il linguaggio stesso si sviluppano lentamente. Alla fine degli anni 2000, si decise di passare a C# pi\u00f9 promettente. La nuova versione \u00e8 stata scritta parallelamente al miglioramento della vecchia, con sempre pi\u00f9 codice su .NET. Il backend in C# inizialmente era orientato verso un'architettura di servizi, tuttavia nello sviluppo sono state utilizzate librerie comuni con logica, e i servizi venivano avviati in un unico processo. \u00c8 risultato un'applicazione che chiamavamo \"monolite di servizio\". <\/p>\n<p>Uno dei pochi vantaggi di tale accoppiamento era la possibilit\u00e0 per i servizi di chiamarsi a vicenda tramite API esterne. C'erano chiare premesse per passare a un'architettura di servizi pi\u00f9 corretta e, in prospettiva, a un'architettura a microservizi. <\/p>\n<p>Abbiamo iniziato il nostro lavoro di decomposizione intorno al 2015. Anche se non abbiamo ancora raggiunto uno stato ideale - ci sono rimasti parti del grande progetto che sono difficili da chiamare monoliti, ma non assomigliano nemmeno a microservizi. Tuttavia, i progressi sono significativi. <br \/>\nDi questo parler\u00f2 nell'articolo.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/132bb4ea6b9dbcdd202ee090f2b86289.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Contenuto<\/h3>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#1\"> Architettura e problemi della soluzione esistente<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#2\">Aspettative dai microservizi<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#3\">Problemi nella transizione<\/a><\/noindex><\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"#4\">Come passare da un monolite a microservizi<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#5\">Primo modo<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#6\">Secondo modo<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#7\">Terzo modo<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#8\">Quarto modo<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#9\">Creiamo un database \u2014 MySQL. Se hai PhpMyAdmin installato, crea un nuovo database \"<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#10\">Separazione delle tabelle esistenti<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#11\">Separazione con rielaborazione<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#12\">Lavoro con il codice sorgente<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#13\">Problemi di infrastruttura<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#16\">Installazione manuale negli ambienti<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#14\">Logging separato<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#15\">Testing e debug dei servizi correlati<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><noindex><a rel=\"nofollow\" name=\"1\"><\/a><\/noindex><b><\/p>\n<h3>Architettura e problemi della soluzione esistente<\/h3>\n<p><\/b><br \/>\nInizialmente, l'architettura era la seguente: UI \u2014 applicazione separata, parte monolitica scritta in Visual Basic 6, applicazione su .NET rappresentava un insieme di servizi correlati, che lavoravano con un database piuttosto grande.<\/p>\n<p><b>Svantaggi della soluzione precedente<\/b><\/p>\n<p><u>Unico punto di fallimento<\/u><br \/>\nAvevamo un unico punto di fallimento: l'applicazione su .NET veniva eseguita in un unico processo. Se uno dei moduli andava in errore, l'intera applicazione smetteva di funzionare e doveva essere riavviata. Poich\u00e9 automatizziamo un gran numero di processi per diversi utenti, a causa di un guasto in uno di essi, tutti non potevano lavorare per un certo periodo. E in caso di errore di programmazione, nemmeno la riserva era di aiuto. <\/p>\n<p><u>Coda delle modifiche<\/u><br \/>\nQuesto difetto \u00e8 principalmente organizzativo. La nostra applicazione ha molteplici clienti, e tutti vogliono apportare modifiche il prima possibile. In passato, era impossibile farlo in parallelo e tutti i clienti dovevano mettersi in coda. Questo processo creava frustrazione per il business, poich\u00e9 dovevano dimostrare che il loro compito aveva valore. E il team di sviluppo spendeva tempo per organizzare questa coda. Questo richiedeva molte energie e il prodotto alla fine non poteva cambiare cos\u00ec rapidamente come avrebbero voluto.<\/p>\n<p><u>Utilizzo inefficiente delle risorse<\/u><br \/>\nQuando posizionavamo i servizi in un unico processo, copiavamo sempre completamente la configurazione da un server all'altro. Volevamo posizionare i servizi pi\u00f9 gravosi separatamente, per non sprecare risorse e ottenere una gestione pi\u00f9 flessibile del nostro schema di distribuzione.<\/p>\n<p><u>Difficolt\u00e0 nell'implementazione di tecnologie moderne<\/u><br \/>\nUn problema familiare a tutti gli sviluppatori: c'\u00e8 la voglia di introdurre tecnologie moderne nel progetto, ma non ci sono possibilit\u00e0. Con una soluzione monolitica, qualsiasi aggiornamento della libreria corrente, per non parlare del passaggio a una nuova, diventa un compito piuttosto complesso. Occorre molto tempo per convincere il team leader che questo porter\u00e0 pi\u00f9 vantaggi delle energie spese. <\/p>\n<p><u>Difficolt\u00e0 nell'implementare cambiamenti<\/u><br \/>\nQuesto era il problema pi\u00f9 serio: emettevamo rilasci ogni due mesi. <br \/>\nOgni rilascio si trasformava in una vera catastrofe per la banca, nonostante i test e gli sforzi degli sviluppatori. Il business capiva che all'inizio della settimana non avrebbe funzionato parte della funzionalit\u00e0. E gli sviluppatori sapevano che li aspettava una settimana di seri incidenti. <br \/>\nDesiderio di cambiare la situazione c'era da parte di tutti. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"2\"><\/a><\/noindex><b><\/p>\n<h3>Aspettative dai microservizi<\/h3>\n<p><\/b><br \/>\n<u>Emessa la componente al termine della preparazione. <\/u>Emessa la componente man mano che era pronta grazie alla decomposizione della soluzione e alla separazione dei vari processi.<\/p>\n<p><u>Piccole squadre di prodotto.<\/u> \u00c8 importante perch\u00e9 gestire un grande team che lavora su un vecchio monolite \u00e8 difficile. Un team del genere deve seguire un processo rigoroso, mentre c'\u00e8 desiderio di maggiore creativit\u00e0 e indipendenza. Solo le piccole squadre possono permetterselo.<\/p>\n<p><u>Isolamento dei servizi in processi separati.<\/u> Idealmente, vorremmo isolare in contenitori, ma un gran numero di servizi scritti su .NET Framework viene eseguito solo su Windows. Attualmente stanno emergendo servizi su .NET Core, ma ce ne sono ancora pochi.<\/p>\n<p><u>Flessibilit\u00e0 nel deployment.<\/u> Vorremmo combinare i servizi come necessario per noi, e non come impone il codice.<\/p>\n<p><u>Utilizzo di nuove tecnologie.<\/u> \u00c8 un aspetto interessante per qualsiasi programmatore.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"3\"><\/a><\/noindex><b><\/p>\n<h3>Problemi nella transizione<\/h3>\n<p><\/b><br \/>\nCerto, se fosse facile suddividere un monolite in microservizi, non se ne parlerebbe nei convegni e non si scriverebbero articoli. Ci sono molte insidie in questo processo, descriver\u00f2 le principali che ci hanno ostacolato.<\/p>\n<p><b>Il primo problema<\/b> tipica della maggior parte dei monoliti: la coesione della logica di business. Quando scriviamo un monolite, vogliamo riutilizzare le nostre classi per non scrivere codice superfluo. Ma nel passaggio ai microservizi questo diventa un problema: tutto il codice \u00e8 abbastanza rigidamente legato e risulta difficile separare i servizi.<\/p>\n<p>Al momento dell'inizio dei lavori nel repository c'erano pi\u00f9 di 500 progetti e oltre 700.000 righe di codice. Questa \u00e8 una soluzione piuttosto grande e <b>il secondo problema<\/b>. Non era possibile semplicemente prenderlo e dividerlo in microservizi.<\/p>\n<p><b>Il terzo problema<\/b> \u2014 mancanza di infrastruttura necessaria. Di fatto, ci occupavamo di copiare manualmente il codice sorgente sui server.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"4\"><\/a><\/noindex><b><\/p>\n<h3>Come passare da un monolite a microservizi<\/h3>\n<p><\/b><br \/>\n<u>Identificazione dei microservizi<\/u><\/p>\n<p>Innanzitutto, abbiamo subito stabilito che la separazione dei microservizi \u00e8 un processo iterativo. Ci \u00e8 sempre stato richiesto di condurre parallelamente lo sviluppo delle attivit\u00e0 aziendali. Come realizzeremo tecnicamente ci\u00f2 \u00e8 un nostro problema. Pertanto, ci siamo preparati a un processo iterativo. Non pu\u00f2 essere altrimenti se hai una grande applicazione e non \u00e8 inizialmente pronta per essere riscritta.<\/p>\n<p>Quali metodi utilizziamo per identificare i microservizi?<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"5\"><\/a><\/noindex><b>Primo modo <\/b>\u2014 estrarre i moduli esistenti come servizi. In questo senso siamo stati fortunati: c'erano gi\u00e0 servizi configurati che operavano secondo il protocollo WCF. Erano distribuiti su diversi assembly. Li abbiamo trasferiti singolarmente, aggiungendo a ciascun assembly un piccolo modulo di avvio. Questo \u00e8 stato scritto utilizzando l'ottima libreria Topshelf, che consente di eseguire l'applicazione sia come servizio che come console. \u00c8 comodo per il debug, poich\u00e9 non richiede progetti aggiuntivi nella soluzione.<\/p>\n<p>I servizi erano collegati per logica aziendale, poich\u00e9 utilizzavano assembly comuni e lavoravano con un database condiviso. Era difficile definirli microservizi nel senso pi\u00f9 puro. Tuttavia, potevamo pubblicare questi servizi separatamente, in processi diversi. Gi\u00e0 questo permetteva di ridurre l'influenza reciproca, attenuando i problemi di sviluppo parallelo e il punto unico di errore.<\/p>\n<p>L'assembly con l'host \u00e8 composta da una sola riga di codice nella classe Program. Il lavoro con Topshelf \u00e8 stato nascosto in una classe di supporto.<\/p>\n<pre><code class=\"plaintext\">namespace RBA.Services.Accounts.Host\n{\n   internal class Program\n   {\n      private static void Main(string[] args)\n      {\n        HostRunner.Run(\"RBA.Services.Accounts.Host\");\n\n       }\n    }\n}\n<\/code><\/pre>\n<p>\n<noindex><a rel=\"nofollow\" name=\"6\"><\/a><\/noindex><b>Il secondo modo per estrarre microservizi:<\/b> crearne di nuovi per affrontare obiettivi. Se in questo modo il monolite non cresce, \u00e8 gi\u00e0 un ottimo segno, significa che stiamo procedendo nella direzione giusta. Per affrontare nuovi compiti cercavamo di creare servizi separati. Se c'era l'opportunit\u00e0, creavamo servizi pi\u00f9 \"canonici\", che gestiscono completamente il proprio modello di dati, con un database separato. <\/p>\n<p>Iniziammo, come molti, con servizi di autenticazione e autorizzazione. Questi sono perfetti per questo scopo. Sono indipendenti e, in genere, hanno un modello di dati isolato. Non interagiscono direttamente con il monolite, solo quest'ultimo si rivolge a loro per risolvere determinate questioni. Su questi servizi si pu\u00f2 iniziare la transizione verso una nuova architettura, debuggarvi l'infrastruttura, provare alcuni approcci legati alle librerie di rete, ecc. Nella nostra organizzazione non ci sono team che non siano riusciti a realizzare un servizio di autenticazione. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"7\"><\/a><\/noindex><b>Il terzo modo per estrarre microservizi<\/b>, che utilizziamo, \u00e8 un po' specifico per noi. Si tratta di estrarre la logica di business dallo strato UI. La nostra principale applicazione UI \u00e8 desktop, ed \u00e8 scritta in C#, cos\u00ec come il backend. Gli sviluppatori commettevano occasionalmente errori estraendo nello UI parti della logica che avrebbero dovuto esistere nel backend e essere riutilizzate. <\/p>\n<p>Se guardiamo un esempio reale dal codice della parte UI, si pu\u00f2 notare che gran parte di questa soluzione contiene reale logica di business, utile in altri processi, non solo per costruire il modulo UI. <\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/74c7b90ff94b343816ab3ac2fa0673c6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa logica reale dell'UI \u00e8 presente solo nelle ultime righe. L'abbiamo trasferita sul server per poterla riutilizzare, riducendo l'UI e ottenendo una corretta architettura.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"8\"><\/a><\/noindex><b>Il quarto, modo pi\u00f9 importante di distinguere i microservizi<\/b>, che consente di ridurre il monolite, \u00e8 quello di estrarre i servizi esistenti con una revisione. Quando estraiamo i moduli esistenti cos\u00ec come sono, il risultato non sempre piace agli sviluppatori, e il processo aziendale nel tempo dalla creazione della funzionalit\u00e0 potrebbe essere obsoleto. Grazie al refactoring, possiamo supportare un nuovo processo aziendale, poich\u00e9 le esigenze dell'azienda cambiano costantemente. Possiamo migliorare il codice sorgente, eliminare difetti noti, e creare un modello di dati di maggiore qualit\u00e0. Se accumulano molti vantaggi.<\/p>\n<p>La separazione dei servizi con revisione \u00e8 indissolubilmente legata al concetto di contesto limitato. Questo concetto proviene dal design orientato agli oggetti. Significa un'area del modello di dominio in cui tutti i termini di un linguaggio comune sono definiti in modo univoco. Prendiamo come esempio il contesto delle assicurazioni e delle fatture. Abbiamo un'applicazione monolitica, e dobbiamo lavorare con la fattura nelle assicurazioni. Ci aspettiamo che lo sviluppatore trovi in un'altra assembly la classe esistente \"Fattura\", faccia riferimento ad essa dalla classe \"Assicurazione\", e otteniamo un codice funzionante. Il principio DRY sar\u00e0 rispettato, e il compito sar\u00e0 completato pi\u00f9 rapidamente grazie all'uso del codice esistente.<\/p>\n<p>Alla fine si scopre che i contesti di conti e assicurazioni sono collegati. Quando appariranno nuove richieste, questo legame ostacoler\u00e0 lo sviluppo, aumentando la complessit\u00e0 di una logica di business gi\u00e0 complessa. Per affrontare questo problema, \u00e8 necessario nel codice individuare i confini tra i contesti e rimuovere le loro violazioni. Ad esempio, al contesto delle assicurazioni potrebbe essere sufficiente un numero di conto della Banca Centrale di 20 cifre e la data di apertura del conto. <\/p>\n<p>Per separare questi contesti limitati e avviare il processo di estrazione dei microservizi da una soluzione monolitica, abbiamo utilizzato un approccio come la creazione di API esterne all'interno dell'applicazione. Se sapevamo che un dato modulo doveva diventare un microservizio e modificarsi in qualche modo nel processo, immediatamente effettuavamo chiamate alla logica appartenente a un altro contesto limitato tramite chiamate esterne. Ad esempio, tramite REST o WCF.<\/p>\n<p>Abbiamo deciso di non evitare il codice che richiede di eseguire transazioni distribuite. Nel nostro caso, \u00e8 stato abbastanza facile rispettare questa regola. Finora non abbiamo mai incontrato situazioni in cui siano davvero necessarie transazioni distribuite rigorose: \u00e8 bastata la coerenza finale tra i moduli.<\/p>\n<p>Consideriamo un esempio concreto. Abbiamo il concetto di orchestratore \u2014 un nastro trasportatore che elabora l'entit\u00e0 \"richiesta\". Esso crea a turno un cliente, un conto e una carta bancaria. Se il cliente e il conto vengono creati con successo e la creazione della carta fallisce, la richiesta non passa allo stato di \"successo\" e rimane nello stato di \"carta non creata\". In futuro, un'attivit\u00e0 in background la recuperer\u00e0 e la concluder\u00e0. Il sistema rimarr\u00e0 per un certo periodo in uno stato di incoerenza, ma questo ci va bene nel complesso.<\/p>\n<p>Nel caso in cui si presenti comunque una situazione in cui sia necessario salvare in modo coerente una parte dei dati, probabilmente procederemo a un accorpamento del servizio per gestire tutto in un unico processo. <\/p>\n<p>Consideriamo un esempio di estrazione di un microservizio. Come possiamo portarlo in modo relativamente sicuro in produzione? In questo esempio abbiamo una parte separata del sistema \u2014 un modulo di gestione stipendi, uno dei quali segmenti di codice vogliamo rendere microserviziale.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/346af271b0c3f99897d330e56f713f18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIniziamo creando un microservizio, riscrivendo il codice. Ottimizziamo alcuni aspetti che non ci soddisfacevano. Implementiamo nuove requisiti di business del cliente. Aggiungiamo un API Gateway nel collegamento tra UI e backend, che garantir\u00e0 il passaggio delle chiamate. <\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/bec8d68f20f3ec53af0cef225a51c2b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSuccessivamente, rilasciamo questa configurazione in esercizio, ma in modalit\u00e0 pilota. La maggior parte degli utenti continua a lavorare con i vecchi processi aziendali. Per i nuovi utenti sviluppiamo una nuova versione dell'applicazione monolitica, che non contiene pi\u00f9 questo processo. Fondamentalmente abbiamo una combinazione di monolite e microservizio in modalit\u00e0 pilota.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/27e98812746bb7f142fa3a3c3a03b52f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCon un pilota di successo comprendiamo che la nuova configurazione \u00e8 davvero funzionante, possiamo escludere dal calcolo il vecchio monolite e mantenere la nuova configurazione al posto della vecchia soluzione.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/11dcf1d771b57d3921c0aa91b82646e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn sintesi, utilizziamo praticamente tutti i metodi esistenti per separare il codice sorgente del monolite. Tutti questi metodi ci permettono di ridurre le dimensioni delle parti dell'applicazione e di migrarle su nuove librerie, producendo un codice sorgente di qualit\u00e0 superiore.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"9\"><\/a><\/noindex><b><\/p>\n<h3>Creiamo un database \u2014 MySQL. Se hai PhpMyAdmin installato, crea un nuovo database \"<\/h3>\n<p><\/b><br \/>\nIl database si presta peggio alla separazione rispetto al codice sorgente, in quanto contiene non solo lo schema attuale, ma anche i dati storici accumulati.<\/p>\n<p>Il nostro database, come molti altri, aveva un altro importante svantaggio: una dimensione enorme. Questo database \u00e8 stato progettato secondo una logica aziendale complessa del monolite, e tra le tabelle di vari contesti limitati si sono accumulate relazioni.<\/p>\n<p>Nel nostro caso, per completare tutto questo (grande database, molte relazioni, a volte confini poco chiari tra le tabelle) \u00e8 emerso un problema comune a molti progetti di grandi dimensioni: l'uso del modello di database condiviso. I dati venivano prelevati dalle tabelle attraverso viste, tramite replica e trasferiti in altri sistemi dove era necessaria tale replica. Di conseguenza, non potevamo estrarre le tabelle in uno schema separato, poich\u00e9 erano utilizzate attivamente.<\/p>\n<p>Nella separazione ci aiuta proprio quella suddivisione in contesti limitati nel codice. Essa, di solito, ci fornisce un'ottima visione di come distribuiamo i dati a livello di database. Comprendiamo quali tabelle appartengono a un contesto limitato e quali a un altro.<\/p>\n<p>Abbiamo applicato due strategie globali per la separazione del database: la separazione delle tabelle esistenti e la separazione con riprogettazione.<\/p>\n<p>La separazione delle tabelle esistenti \u00e8 un metodo che si applica bene quando la struttura dei dati \u00e8 di qualit\u00e0, soddisfa i requisiti aziendali e va bene a tutti. In questo caso, possiamo \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c in uno schema separato le tabelle esistenti.<\/p>\n<p>La separazione con riprogettazione \u00e8 necessaria quando il modello di business \u00e8 cambiato notevolmente, e le tabelle non ci soddisfano pi\u00f9.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"10\"><\/a><\/noindex><b>Separazione delle tabelle esistenti.<\/b> Dobbiamo determinare cosa andremo a separare. Senza questa conoscenza non sar\u00e0 possibile, e qui ci aiuter\u00e0 la separazione dei contesti limitati nel codice. In genere, se riusciamo a comprendere i confini dei contesti nel codice sorgente, \u00e8 chiaro quali tabelle devono essere incluse nell\u2019elenco da separare.<\/p>\n<p>Immaginiamo di avere una soluzione in cui due moduli di un monolite interagiscono con un unico database. Dobbiamo fare in modo che solo un modulo interagisca con le tabelle da separare, mentre l'altro inizia a interagire con esse tramite API. Inizialmente, \u00e8 sufficiente che attraverso API vengano effettuate solo scritture. Questo \u00e8 un requisito fondamentale affinch\u00e9 possiamo parlare di indipendenza dei microservizi. I collegamenti in lettura possono rimanere, finch\u00e9 non ci sono grandi problemi.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/1602637ad752ac055f475cfa45d95e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIl passo successivo sar\u00e0 quello di separare il segmento di codice che lavora con le tabelle da separare, con riprogettazione o senza, in un microservizio separato e lanciarlo in un processo o contenitore a parte. Sar\u00e0 un servizio autonomo con un collegamento al database del monolite e alle tabelle che non gli appartengono direttamente. Il monolite continuer\u00e0 a interagire in lettura con la parte separata. <\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/36011f4e6be4f6a2f19f2f074b645dcb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSuccessivamente, rimuoveremo questo collegamento, ovvero anche la lettura dei dati dell'applicazione monolitica dalle tabelle separate sar\u00e0 trasferita su API.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/290f91bbfccac2a4b384078e4cf4e337.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPoi separeremo dalle tabelle dell'DB comune quelle con cui lavora solo il nuovo microservizio. Possiamo estrarre le tabelle in uno schema separato o persino in un database fisico separato. Rimane un collegamento in lettura tra il microservizio e il database del monolite, ma non c'\u00e8 nulla di cui preoccuparsi, in questa configurazione pu\u00f2 coesistere per un tempo abbastanza lungo.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/ab947ac6a38ffbccd4e2b51103aef609.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nL'ultimo passo \u00e8 rimuovere completamente tutte le connessioni. In questo caso, potrebbe essere necessario migrare i dati dalla banca dati principale. A volte vogliamo riutilizzare in diverse banche dati alcuni dati o registri replicati da sistemi esterni. Questo accade periodicamente da noi.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/f40cf17dd56b9575751e370c44f08344.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"11\"><\/a><\/noindex><b>Sezione con rielaborazione.<\/b> Questo metodo \u00e8 molto simile al primo, ma avviene in ordine inverso. Viene subito creata una nuova banca dati e un nuovo microservizio che interagisce con il monolite tramite API. Tuttavia, rimane un insieme di tabelle del database che intendiamo eliminare in futuro. Non ci servir\u00e0 pi\u00f9, nella nuova modellazione l'abbiamo sostituito.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/c94932033e47cfa1fd56595ab9a19246.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAffinch\u00e9 questo schema funzioni, probabilmente avremo bisogno di un periodo di transizione.<\/p>\n<p>Successivamente ci sono due approcci possibili.<\/p>\n<p><b>Primo<\/b>: dupliciamo tutti i dati nelle nuove e nelle vecchie banche. In questo caso abbiamo una ridondanza dei dati, possono sorgere problemi di sincronizzazione. Ma possiamo prendere due client diversi. Uno lavorer\u00e0 con la nuova versione, l'altro con la vecchia.<\/p>\n<p><b>Secondo<\/b>: separiamo i dati secondo qualche criterio di business. Ad esempio, nel nostro sistema c'erano 5 prodotti archiviati nella vecchia banca dati. Il sesto, nell'ambito di un nuovo obiettivo di business, lo mettiamo nella nuova banca dati. Ma avremo bisogno di un API Gateway che sincronizzi questi dati e mostri al client da dove e cosa prelevare.<\/p>\n<p>Entrambi gli approcci sono funzionali, scegliete in base alla situazione.<\/p>\n<p>Una volta assicurati che tutto funzioni, possiamo disabilitare la parte del monolite che lavora con le vecchie strutture dei database. <\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/973bf5015bdf49a290a5b901f89628cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nL'ultimo passo sar\u00e0 l'eliminazione delle vecchie strutture dati. <\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/fe83acc07077b7eb3717138e3c20c005.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn sintesi, possiamo dire che abbiamo problemi con i database: \u00e8 difficile lavorarci rispetto al codice sorgente, \u00e8 pi\u00f9 complicato separare, ma \u00e8 possibile e necessario farlo. Abbiamo trovato alcuni modi che ci permettono di farlo in modo ragionevolmente sicuro; \u00e8 comunque pi\u00f9 facile commettere errori con i dati rispetto al codice sorgente. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"12\"><\/a><\/noindex><b><\/p>\n<h3>Lavoro con il codice sorgente<\/h3>\n<p><\/b><br \/>\nEcco come appariva lo schema del codice sorgente quando abbiamo iniziato ad analizzare il progetto monolitico.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/a6d886e37117ccf8f63106d6616aa653.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00c8 possibile suddividerla in tre strati. Questo \u00e8 lo strato dei moduli, dei plugin, dei servizi e delle singole attivit\u00e0 avviabili. In effetti, erano i punti d'ingresso all'interno di una soluzione monolitica. Tutti erano rigidamente collegati da uno strato comune. In esso vi era la logica di business utilizzata dai servizi in comune e numerose interconnessioni. Ogni servizio e plugin utilizzava fino a 10 o pi\u00f9 assembly comuni, a seconda delle loro dimensioni e della coscienza degli sviluppatori.<\/p>\n<p>Siamo stati fortunati, avevamo librerie infrastrutturali che potevano essere utilizzate separatamente. <\/p>\n<p>A volte si presentava una situazione in cui alcuni oggetti comuni in realt\u00e0 non appartenevano a questo strato, ma erano librerie infrastrutturali. Questo veniva risolto rinominando.<\/p>\n<p>Le preoccupazioni principali riguardavano i contesti limitati. A volte, 3-4 contesti si mescolavano in un'unica assembly comune e si utilizzavano a vicenda all'interno di una stessa funzione di business. Era necessario capire dove fosse possibile separare e quali fossero i confini, e cosa fare dopo con il mapping di questa separazione sulle assembly del codice sorgente.<\/p>\n<p>Abbiamo formulato alcune regole per il processo di separazione del codice.<\/p>\n<p><b>Primo<\/b>: non volevamo pi\u00f9 condividere la logica di business tra servizi, attivit\u00e0 e plugin. Volevamo rendere la logica di business indipendente all'interno dei microservizi. D'altra parte, i microservizi, idealmente, sono percepiti come servizi che esistono completamente in modo indipendente. Ritengo che questo approccio sia un po' sprecone e difficile da raggiungere, poich\u00e9 ad esempio, i servizi in C# saranno comunque collegati dalla libreria standard. Il nostro sistema \u00e8 scritto in C#, altre tecnologie non sono state finora utilizzate. Pertanto, abbiamo deciso che potevamo permetterci di utilizzare assembly tecniche comuni. L'importante \u00e8 che non ci siano frammenti di logica di business al loro interno. Se hai un comodo wrapper sopra l'ORM che utilizzi, allora copiare da un servizio all'altro \u00e8 molto costoso.<\/p>\n<p>Il nostro team \u00e8 appassionato di progettazione orientata agli oggetti, quindi l'\u00abarchitettura a cipolla\u00bb si adatta perfettamente a noi. La base dei nostri servizi non \u00e8 stata il data access layer, ma una raccolta con logica di dominio, che contiene solo logica aziendale ed \u00e8 priva di collegamenti con l'infrastruttura. In questo modo possiamo modificare in modo indipendente la raccolta di dominio per affrontare i problemi legati ai framework.<\/p>\n<p>In questa fase abbiamo incontrato il primo serio problema. Il servizio doveva fare riferimento a una raccolta di dominio, volevamo rendere la logica indipendente, e in questo ci ostacolava fortemente il principio DRY. Gli sviluppatori volevano riutilizzare classi da raccolte vicine per evitare duplicazioni e, di conseguenza, i domini hanno ricominciato a collegarsi tra loro. Abbiamo analizzato i risultati e deciso che forse il problema risiedeva anche nel modo in cui era strutturato il repository del codice sorgente. Avevamo un grande repository in cui si trovavano tutti i codici sorgenti. Era molto difficile assemblare la soluzione per l'intero progetto sulla macchina locale. Di conseguenza, per le parti del progetto venivano creati piccoli solution separati, e a nessuno era vietato aggiungere in essi una raccolta Common o di dominio e riutilizzarla. L'unico strumento che non ci permetteva di farlo era il codice di revisione. Ma a volte anche questo falliva.<\/p>\n<p>Allora abbiamo iniziato a passare a un modello con repository separati. La logica aziendale ha smesso di trapelare da un servizio all'altro, i domini sono realmente diventati indipendenti. I contesti limitati sono supportati in modo pi\u00f9 chiaro. Come riutilizziamo le librerie infrastrutturali in questo caso? Le abbiamo isolate in un repository separato, poi le abbiamo inserite in pacchetti Nuget, che abbiamo posizionato in Artifactory. Qualsiasi modifica provoca un'assemblaggio e una pubblicazione automatici.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/8ddbc750dc7c6d397a459acf7825de90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nI nostri servizi hanno iniziato a fare riferimento ai pacchetti infrastrutturali interni esattamente come a quelli esterni. Scarichiamo le librerie esterne da Nuget. Per lavorare con Artifactory, dove posizionavamo questi pacchetti, abbiamo applicato due gestori di pacchetti. Nei piccoli repository abbiamo utilizzato anche Nuget. Nei repository con pi\u00f9 servizi abbiamo usato Paket, che garantisce maggiore coerenza delle versioni tra i moduli.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/672a25a70a481bff68baebe963184ccd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questo modo, lavorando sul codice sorgente, modificando leggermente l'architettura e separando i repository, rendiamo i nostri servizi pi\u00f9 indipendenti.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"13\"><\/a><\/noindex><b><\/p>\n<h3>Problemi di infrastruttura<\/h3>\n<p><\/b><br \/>\nLa maggior parte delle difficolt\u00e0 nel passaggio ai microservizi \u00e8 legata all'infrastruttura. Avrai bisogno di un deployment automatizzato e saranno necessarie nuove librerie per gestire l'infrastruttura.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"16\"><\/a><\/noindex><b>Installazione manuale negli ambienti<\/b><\/p>\n<p>Inizialmente, installavamo manualmente le soluzioni negli ambienti. Per automatizzare questo processo, abbiamo creato una pipeline CI\/CD. Abbiamo scelto il processo di continuous delivery, perch\u00e9 il continuous deployment al momento non \u00e8 accettabile per i nostri processi aziendali. Pertanto, il passaggio in produzione avviene su richiesta, mentre il testing \u00e8 automatico.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/0fc092326a48813398c6f3a031197bab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUtilizziamo Atlassian, Bitbucket per l'archiviazione del codice sorgente e Bamboo per la compilazione. Ci piace scrivere gli script di build in Cake, perch\u00e9 \u00e8 lo stesso C#. In Artifactory arrivano gi\u00e0 pacchetti pronti e Ansible viene trasferito automaticamente sui server di test, dove possono essere immediatamente testati.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/fcc743cfaa4a24b906ceeb40ec1ba0a0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"14\"><\/a><\/noindex><b><\/p>\n<h3>Logging separato<\/h3>\n<p><\/b><br \/>\nIn passato, una delle idee del monolite era garantire una registrazione unificata. Dovevamo anche capire come gestire i log separati che risiedono sui dischi. I log vengono scritti in file di testo. Abbiamo deciso di utilizzare il classico stack ELK. Non abbiamo optato per scrivere direttamente in ELK tramite provider, ma abbiamo deciso di affinare i log di testo e registrare in essi gli ID di tracciamento come identificatore, aggiungendo il nome del servizio, in modo che questi log possano essere successivamente analizzati.<\/p>\n<p><img decoding=\"async\" alt=\"Transizione da monolite a microservizi: storia e pratica\" src=\"\/wp-content\/uploads\/2019\/07\/8e58c66ac134e65abe34b59939f31483.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCon Filebeat otteniamo la possibilit\u00e0 di raccogliere i nostri log da <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/it\/server\/\"   title=\"server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1338\">server<\/a>, poi di elaborarli, utilizzare Kibana per costruire query nell'interfaccia utente e osservare come sono stati effettuati gli inviti tra i servizi. Questo \u00e8 particolarmente aiutato dagli ID di tracciamento.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"15\"><\/a><\/noindex><b><\/p>\n<h3>Testing e debug dei servizi correlati<\/h3>\n<p><\/b><br \/>\nInizialmente non capivamo appieno come ottimizzare i servizi che stavamo sviluppando. Con il monolite era tutto semplice, lo avviavamo sulla macchina locale. Allo stesso modo cercavamo di fare con i microservizi, ma a volte per eseguire un microservizio \u00e8 necessario avviarne anche altri, il che \u00e8 scomodo. Abbiamo capito che era necessario passare a un modello in cui lasciavamo sulla macchina locale solo il servizio o i servizi che volevamo debugare. Gli altri servizi vengono utilizzati da server configurati in modo identico a prod. Dopo il debug, durante i test, per ogni task sul server di test vengono distribuiti solo i servizi modificati. In questo modo, la soluzione viene testata nella forma in cui si presenter\u00e0 in futuro su prod.<\/p>\n<p>Ci sono server su cui sono installate solo versioni di produzione dei servizi. Questi server sono necessari in caso di incidenti, per verificare la distribuzione prima del deploy e per la formazione interna.<\/p>\n<p>Abbiamo aggiunto un processo di test automatico utilizzando la popolare libreria Specflow. I test vengono eseguiti automaticamente con NUnit subito dopo il dispiegamento da Ansible. Se la copertura del task \u00e8 completamente automatica, non \u00e8 necessaria la testazione manuale. Sebbene a volte sia comunque richiesto un ulteriore test manuale. Per determinare quali test eseguire per un task specifico, utilizziamo i tag in Jira.<\/p>\n<p>\u00c8 aumentata la necessit\u00e0 di test di carico, che in precedenza venivano eseguiti solo in rare occasioni. Per eseguire i test utilizziamo JMeter, per il loro stoccaggio InfluxDB, e per la creazione di grafici del processo Grafana.<\/p>\n<p><b><\/p>\n<h3>Cosa abbiamo ottenuto?<\/h3>\n<p><\/b><br \/>\nInnanzitutto, ci siamo liberati del concetto di \"rilascio\". Sono scomparsi i mostruosi rilasci bimestrali, quando questa macchina veniva distribuita nell'ambiente di produzione, interrompendo temporaneamente i processi aziendali. Ora distribuiamo i servizi in media ogni 1,5 giorni, raggruppandoli, poich\u00e9 entrano in esercizio dopo approvazione.<\/p>\n<p>Nel nostro sistema non ci sono crash fatali. Se rilasciamo un microservizio con un errore, la funzionalit\u00e0 a esso associata sar\u00e0 compromessa, mentre tutta l'altra funzionalit\u00e0 non sar\u00e0 influenzata. Questo migliora notevolmente l'esperienza dell'utente.<\/p>\n<p>Possiamo gestire lo schema di distribuzione. \u00c8 possibile separare i gruppi di servizi dal resto della soluzione se necessario.<\/p>\n<p>Inoltre, abbiamo notevolmente ridotto il problema dell'alta coda di revisioni. Sono emerse diverse squadre di prodotto che lavorano su alcune parte dei servizi in modo indipendente. Qui gi\u00e0 il processo Scrum si adatta bene. Un team specifico pu\u00f2 avere un proprietario di prodotto distinto che assegna i compiti. <\/p>\n<p><b><\/p>\n<h3>Riepilogo<\/h3>\n<p><\/b><\/p>\n<ul>\n<li>I microservizi si prestano bene alla scomposizione di sistemi complessi. Durante questo processo, iniziamo a capire cosa c'\u00e8 nel nostro sistema, quali sono i contesti limitati e dove si trovano i loro confini. Questo consente di distribuire correttamente le revisioni tra i moduli e di evitare confusione nel codice. <\/li>\n<li>I microservizi offrono vantaggi organizzativi. Si parla spesso di loro solo come architettura, ma qualsiasi architettura esiste per soddisfare le esigenze del business, non per se stessa. Pertanto, possiamo affermare che i microservizi sono adatti per affrontare compiti con piccoli team, considerando che attualmente lo Scrum \u00e8 molto popolare.<\/li>\n<li>La separazione \u00e8 un processo iterativo. Non si pu\u00f2 prendere un'applicazione e semplicemente dividerla in microservizi. Il prodotto risultante sar\u00e0 difficilmente funzionante. Quando si creano microservizi, \u00e8 vantaggioso riscrivere il legacy esistente, cio\u00e8 convertirlo in un codice che ci piace e che soddisfa meglio le esigenze del business in termini di funzionalit\u00e0 e velocit\u00e0.\n<p><i>Un piccolo avvertimento:<\/i> i costi per la transizione ai microservizi sono piuttosto significativi. Solo per risolvere il problema dell'infrastruttura ci \u00e8 voluto molto tempo. Quindi, se hai una piccola applicazione che non richiede scalabilit\u00e0 specifica, e se non ci sono molti clienti che competono per l'attenzione e il tempo del tuo team, allora potrebbe essere che i microservizi non siano ci\u00f2 di cui hai bisogno oggi. \u00c8 piuttosto costoso. Se inizi il processo con i microservizi, i costi iniziali saranno superiori rispetto a quelli dell'avvio dello stesso progetto con lo sviluppo di un monolite. <\/p>\n<p>P.S. Una narrazione pi\u00f9 emotiva (e come se fosse personale per te) \u2013 su <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=qTNbx18DzpQ\">link<\/a><\/noindex>. <br \/>\nEcco la versione completa della relazione.<\/li>\n<\/ul>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/raiffeisenbank\/blog\/458404\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26858,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35906","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=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.\" \/>\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\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\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\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\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-31T19:07:29+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:07:29+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\udd47Transizione dal monolite ai microservizi: storia e pratica | ProHoster","description":"In questo articolo parler\u00f2 di come il progetto in cui lavoro si sia trasformato da un grande monolite a un insieme di microservizi. Il progetto ha iniziato la sua storia parecchio tempo fa, all'inizio degli anni 2000.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","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\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster","og:description":"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","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-31T19:07:29+00:00","article:modified_time":"2019-10-31T19:07:29+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35906","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-02-09 17:04:56","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:54:38","updated":"2026-02-09 17:04:56","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\/35906","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=35906"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/35906\/revisions"}],"predecessor-version":[{"id":158582,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/35906\/revisions\/158582"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/26858"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=35906"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=35906"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=35906"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}