{"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 sto lavorando si sia trasformato da un grande monolite in una serie di microservizi.<\/p>\n<p>Il progetto ha avuto inizio molto tempo fa, all'inizio degli anni 2000. Le prime versioni erano scritte in Visual Basic 6. Nel corso del tempo, divenne chiaro che sarebbe stato difficile sostenere lo sviluppo in questo linguaggio in futuro, poich\u00e9 l'IDE e il linguaggio stesso si sviluppavano poco. Alla fine degli anni 2000, si decise di passare a C#, un linguaggio pi\u00f9 promettente. La nuova versione \u00e8 stata scritta parallelamente alla modifica della vecchia, con sempre pi\u00f9 codice in .NET. Il backend in C# inizialmente mirava a un'architettura basata su servizi, ma nello sviluppo venivano utilizzate librerie comuni con logica, e i servizi venivano avviati in un unico processo. Risult\u00f2 un'applicazione che chiamavamo 'monolite dei servizi'. <\/p>\n<p>Uno dei pochi vantaggi di questa combinazione era la possibilit\u00e0 di far s\u00ec che i servizi si chiamassero a vicenda tramite un'API esterna. C'erano chiare premesse per passare a un'architettura basata su servizi pi\u00f9 corretta e, in prospettiva, a una microservizio. <\/p>\n<p>Abbiamo iniziato il nostro lavoro di decomposizione intorno al 2015. Non abbiamo ancora raggiunto uno stato ideale: ci sono parti di un grande progetto che \u00e8 difficile chiamare monoliti, ma non somigliano 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 attuale<\/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 di transizione<\/a><\/noindex><\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"#4\">Come passare da un monolito a microservizi<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#5\">Primo metodo<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#6\">Secondo metodo<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#7\">Terzo metodo<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#8\">Quarto metodo<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#9\">Lavoro con il DB<\/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 riprogettazione<\/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\">Test e debugging 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 attuale<\/h3>\n<p><\/b><br \/>\nInizialmente, l'architettura era la seguente: l'UI era un'applicazione separata, la parte monolitica scritta in Visual Basic 6, e l'applicazione su .NET era 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>Punto unico di fault<\/u><br \/>\nAvevamo un unico punto di fallimento: l'applicazione .NET veniva eseguita all'interno di un solo processo. Se uno dei moduli andava in crash, 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 anche con un errore software, non aiutava la ridondanza. <\/p>\n<p><u>Coda di modifiche<\/u><br \/>\nQuesto difetto \u00e8 pi\u00f9 organizzativo. Nella nostra applicazione ci sono molti clienti, e tutti vogliono che le loro richieste vengano soddisfatte il prima possibile. In passato, non era possibile farlo in parallelo, e tutti i clienti si mettevano in fila. Questo processo generava frustrazione nel business, poich\u00e9 dovevano dimostrare che la loro richiesta avesse valore. E il team di sviluppo spendeva tempo per organizzare questa coda. Ci\u00f2 richiedeva molte risorse e il prodotto, alla fine, non poteva evolversi cos\u00ec rapidamente come avrebbero voluto.<\/p>\n<p><u>Utilizzo non ottimale delle risorse<\/u><br \/>\nNell'implementazione dei servizi in un unico processo, abbiamo sempre copiato completamente la configurazione da server a server. Volevamo separare i servizi pi\u00f9 carichi in modo da non sprecare risorse e ottenere una gestione pi\u00f9 flessibile del nostro schema di distribuzione.<\/p>\n<p><u>\u00c8 difficile adottare tecnologie moderne<\/u><br \/>\nUn problema noto a tutti gli sviluppatori: c'\u00e8 la volont\u00e0 di integrare tecnologie moderne nel progetto, ma mancano le opportunit\u00e0. In una grande soluzione monolitica, ogni aggiornamento della libreria esistente, per non parlare del passaggio a una nuova, diventa un compito piuttosto impegnativo. \u00c8 necessario convincere il team leader che questo porter\u00e0 pi\u00f9 vantaggi che nervosismo speso. <\/p>\n<p><u>Difficolt\u00e0 nell'applicazione delle modifiche<\/u><br \/>\nQuesta era la problematica pi\u00f9 seria: riuscivamo a fare un rilascio 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 sapeva che all'inizio della settimana non avrebbe avuto parte delle funzionalit\u00e0 operative. E gli sviluppatori capivano che li aspettava una settimana di seri incidenti. <br \/>\nTutti desideravano cambiare la situazione. <\/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>Uscita dei componenti al momento della disponibilit\u00e0. <\/u>Uscita dei componenti man mano che diventano disponibili, grazie alla decomposizione delle soluzioni e alla separazione dei vari processi.<\/p>\n<p><u>Piccole squadre di prodotto.<\/u> Questo \u00e8 importante perch\u00e9 gestire una grande squadra che lavora su un vecchio monolite \u00e8 complicato. Tale squadra \u00e8 costretta a seguire processi rigorosi, mentre c'\u00e8 il desiderio di maggiore creativit\u00e0 e autonomia. Solo le piccole squadre possono permetterselo.<\/p>\n<p><u>Isolamento dei servizi in processi separati.<\/u> Idealmente, si vorrebbe isolare all'interno di container, ma un gran numero di servizi scritti in .NET Framework funziona solo su Windows. Adesso iniziano a emergere servizi su .NET Core, ma sono ancora pochi.<\/p>\n<p><u>Flessibilit\u00e0 nel deployment.<\/u> Vorremmo combinare i servizi secondo le nostre necessit\u00e0, e non in base a quanto imposto dal codice.<\/p>\n<p><u>Utilizzo di nuove tecnologie.<\/u> Questo \u00e8 interessante per ogni programmatore.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"3\"><\/a><\/noindex><b><\/p>\n<h3>Problemi di transizione<\/h3>\n<p><\/b><br \/>\nCerto, se fosse semplice scomporre un monolite in microservizi, non ci sarebbe bisogno di parlarne alle conferenze o scrivere articoli. Ci sono molte insidie in questo processo, e descriver\u00f2 le principali che ci hanno ostacolato.<\/p>\n<p><b>Il primo problema<\/b> tipica per la maggior parte dei monoliti: coesione della logica aziendale. Quando scriviamo un monolite, vogliamo riutilizzare le nostre classi per evitare di scrivere codice superfluo. Ma con il passaggio ai microservizi, questo diventa un problema: tutto il codice \u00e8 abbastanza strettamente legato, e risulta difficile separare i servizi.<\/p>\n<p>Al momento dell'inizio dei lavori, nel repository c'erano oltre 500 progetti e oltre 700.000 righe di codice. Si tratta di una soluzione di dimensioni considerevoli e <b>il secondo problema<\/b>. Semplicemente prendere e dividerlo in microservizi non sembrava possibile.<\/p>\n<p><b>Il terzo problema<\/b> \u00e8 la mancanza dell'infrastruttura necessaria. In effetti, ci siamo occupati 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 monolito a microservizi<\/h3>\n<p><\/b><br \/>\n<u>Separazione dei microservizi<\/u><\/p>\n<p>Innanzitutto, abbiamo subito definito che la separazione dei microservizi \u00e8 un processo iterativo. Ci veniva sempre richiesto di portare avanti parallelamente lo sviluppo delle esigenze aziendali. Come intendiamo attuare tecnicamente questo \u00e8 un nostro problema. Pertanto, ci siamo preparati a un processo iterativo. In un'applicazione di grandi dimensioni, non si pu\u00f2 fare diversamente se non \u00e8 pronta a essere riscritta.<\/p>\n<p>Quali metodi utilizziamo per la separazione dei microservizi?<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"5\"><\/a><\/noindex><b>Primo metodo <\/b>\u2014 estrarre moduli esistenti come servizi. In questo caso, siamo stati fortunati: esistevano gi\u00e0 servizi configurati che funzionavano tramite il protocollo WCF. Erano distribuiti in assembly separati. Noi li trasferivamo singolarmente, aggiungendo a ciascun assembly un piccolo modulo di avvio. Questo era scritto utilizzando la fantastica libreria Topshelf, che consente di eseguire l'applicazione sia come servizio che come console. Questo \u00e8 comodo per il debug, poich\u00e9 non sono necessari progetti aggiuntivi nella soluzione.<\/p>\n<p>I servizi erano collegati dalla logica di business, poich\u00e9 utilizzavano assembly condivisi e operavano con un database comune. Era difficile definirli microservizi in senso stretto. Tuttavia, potevamo fornire questi servizi separatamente, in processi diversi. Gi\u00e0 questo riduceva l'impatto reciproco, diminuendo il problema dello sviluppo parallelo e del singolo punto di guasto.<\/p>\n<p>L'assembly con l'host \u00e8 solo una riga di codice nella classe Program. Abbiamo nascosto il lavoro con Topshelf 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 isolare i microservizi:<\/b> creare per affrontare nuove sfide. Se nel processo il monolite non cresce, \u00e8 gi\u00e0 un ottimo segno, significa che ci stiamo muovendo nella direzione giusta. Per affrontare nuove sfide, abbiamo cercato di realizzare servizi separati. Quando possibile, abbiamo creato servizi pi\u00f9 \"canonici\", che gestiscono completamente il proprio modello di dati e un database separato. <\/p>\n<p>Come molti, abbiamo iniziato con servizi di autenticazione e autorizzazione. Sono perfetti per questo scopo. Sono indipendenti, generalmente hanno un modello di dati separato. Non interagiscono con il monolite, ma solo lui si rivolge a loro per risolvere determinati compiti. Su questi servizi possiamo iniziare il passaggio a una nuova architettura, ottimizzare l'infrastruttura, provare alcune soluzioni legate 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\u2019 specifico per noi. Si tratta di separare la logica di business dallo strato UI. La nostra principale applicazione UI \u00e8 desktop e, come il backend, \u00e8 scritta in C#. Gli sviluppatori commettevano errori e a volte portavano nella UI logiche 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 vedere che gran parte di questa soluzione contiene la reale logica di business, utile in altri processi, non solo per costruire moduli 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 della UI \u00e8 rappresentata solo dagli ultimi pochi righi. L'abbiamo trasferita sul server per poterla riutilizzare, riducendo cos\u00ec l\u2019UI e raggiungendo una corretta architettura.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"8\"><\/a><\/noindex><b>Il quarto, il modo pi\u00f9 importante per evidenziare i microservizi<\/b>, che consente di ridurre il monolite, \u00e8 l'estrazione dei servizi esistenti con ristrutturazione. Quando estraiamo i moduli esistenti cos\u00ec come sono, il risultato non sempre soddisfa gli sviluppatori, e il processo aziendale potrebbe essere diventato obsoleto dal momento della creazione delle funzionalit\u00e0. Grazie al refactoring, possiamo sostenere un nuovo processo aziendale, poich\u00e9 le esigenze del business cambiano continuamente. Possiamo migliorare il codice sorgente, eliminare difetti noti e creare un modello di dati di qualit\u00e0 superiore. Si accumulano molti vantaggi.<\/p>\n<p>La separazione dei servizi con gestione dei contesti \u00e8 indissolubilmente legata al concetto di contesto limitato. Questo concetto proviene dalla progettazione orientata agli oggetti. Indica un'area del modello di dominio in cui tutti i termini di un linguaggio univocamente definiti. Consideriamo ad esempio il contesto delle assicurazioni e delle fatture. Abbiamo un'applicazione monolitica e dobbiamo lavorare con una fattura nelle assicurazioni. Ci aspettiamo che lo sviluppatore trovi in un'altra build 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 verr\u00e0 completato pi\u00f9 velocemente utilizzando il codice esistente.<\/p>\n<p>Alla fine risulta che i contesti delle fatture e delle assicurazioni sono collegati. Quando emergeranno nuove esigenze, questa connessione ostacoler\u00e0 lo sviluppo, aumentando la complessit\u00e0 di una logica di business gi\u00e0 complicata. Per risolvere questo problema, \u00e8 necessario nel codice identificare i confini tra i contesti ed eliminare le loro violazioni. Ad esempio, per il contesto delle assicurazioni, potrebbe essere sufficiente un numero di fattura di 20 cifre e la data di apertura della fattura. <\/p>\n<p>Per separare questi contesti limitati e avviare il processo di estrazione dei microservizi da una soluzione monolitica, abbiamo adottato un approccio che prevede la creazione di API esterne all'interno dell'applicazione. Quando sapevamo che un certo modulo doveva diventare un microservizio o subire alcune modifiche nel processo, effettuavamo immediatamente chiamate alla logica che apparteneva a un altro contesto limitato tramite chiamate esterne. Ad esempio, attraverso REST o WCF.<\/p>\n<p>Abbiamo deciso fermamente di non evitare codice che richiederebbe l'uso di transazioni distribuite. Nel nostro caso, \u00e8 stato relativamente facile rispettare questa regola. Fino ad ora, non si sono verificate situazioni in cui fossero necessarie transazioni distribuite rigorose: \u00e8 sempre stata sufficiente la coerenza finale tra i moduli.<\/p>\n<p>Consideriamo un esempio concreto. Abbiamo il concetto di orchestratore \u2014 un pipeline che gestisce l'entit\u00e0 \"richiesta\". Creiamo a turno un cliente, un conto e una carta bancaria. Se il cliente e il conto vengono creati con successo, ma la creazione della carta fallisce, la richiesta non passa allo stato \"riuscita\" e rimane nello stato \"carta non creata\". In futuro, un'attivit\u00e0 in background la riprender\u00e0 e la completer\u00e0. Il sistema si trova per un certo periodo in uno stato di incoerenza, ma questo, fondamentalmente, ci va bene.<\/p>\n<p>Nel caso in cui si presentasse una situazione in cui sia necessario mantenere coerentemente parte dei dati, probabilmente procederemo a consolidare il servizio per gestire tutto in un unico processo. <\/p>\n<p>Esaminiamo l'esempio di estrazione di un microservizio. In che modo possiamo portarlo in produzione in modo relativamente sicuro? In questo esempio, abbiamo una parte separata del sistema \u2014 il modulo di gestione stipendi, uno dei cui segmenti di codice vorremmo 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 \/>\nInnanzitutto, creiamo un microservizio riscrivendo il codice. Miglioriamo alcuni aspetti che non ci soddisfacevano. Implementiamo le nuove esigenze aziendali del cliente. Aggiungiamo un API Gateway nel collegamento tra UI e backend, che fornir\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 produzione, ma in modalit\u00e0 pilota. La maggior parte degli utenti continua a utilizzare i vecchi processi aziendali. Per i nuovi utenti, sviluppiamo una nuova versione dell'applicazione monolitica, che non include pi\u00f9 questo processo. In sostanza, abbiamo un collegamento pilota tra il monolite e il microservizio.<\/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, ci rendiamo conto che la nuova configurazione \u00e8 effettivamente funzionante, possiamo eliminare il vecchio monolite e mantenere la nuova configurazione al posto della soluzione precedente.<\/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 ci permettono di ridurre le dimensioni delle parti dell'applicazione e di trasferirle a nuove librerie, migliorando cos\u00ec la qualit\u00e0 del codice sorgente.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"9\"><\/a><\/noindex><b><\/p>\n<h3>Lavoro con il DB<\/h3>\n<p><\/b><br \/>\nI database sono pi\u00f9 difficili da suddividere rispetto al codice sorgente, poich\u00e9 contengono non solo lo schema attuale, ma anche dati storici accumulati.<\/p>\n<p>Il nostro database, come molti altri, presentava un'altra importante mancanza: la sua enorme dimensione. Questo database era stato progettato seguendo una logica aziendale complessa e si erano accumulate connessioni tra tabelle di diversi contesti limitati.<\/p>\n<p>Nel nostro caso, per completare tutte le difficolt\u00e0 (grande database, molte connessioni e a volte confini poco chiari tra le tabelle) \u00e8 emerso un problema comune in molti progetti di grandi dimensioni: l'uso del modello di database condiviso. I dati venivano estratti dalle tabelle tramite view, attraverso replicazione e caricati in altri sistemi dove era necessaria tale replicazione. Di conseguenza, non potevamo estrarre le tabelle in uno schema separato, poich\u00e9 venivano utilizzate attivamente.<\/p>\n<p>Nella suddivisione ci aiuta proprio la segmentazione in contesti limitati nel codice. Questo generalmente ci offre una buona comprensione di come suddividiamo i dati a livello di database. Sappiamo quali tabelle appartengono a un contesto limitato e quali a un altro.<\/p>\n<p>Abbiamo adottato due approcci generali per la separazione del database: la separazione delle tabelle esistenti e la separazione con ristrutturazione.<\/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 per tutti. In questo caso, possiamo estrarre in uno schema separato le tabelle esistenti.<\/p>\n<p>La separazione con ristrutturazione \u00e8 necessaria quando il modello di business \u00e8 cambiato drasticamente e le tabelle non soddisfano pi\u00f9 le nostre esigenze.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"10\"><\/a><\/noindex><b>Separazione delle tabelle esistenti.<\/b> Dobbiamo determinare quali elementi separare. Senza questa conoscenza non otterremo risultati, e qui ci aiuta la separazione dei contesti limitati nel codice. In genere, se riusciamo a comprendere i confini dei contesti nel codice sorgente, diventa chiaro quali tabelle devono essere incluse nell'elenco per la separazione.<\/p>\n<p>Immaginiamo di avere una soluzione in cui due moduli di un monolite interagiscono con un'unica base di dati. Dobbiamo assicurarci che solo un modulo interagisca con la porzione di tabelle separabili, mentre l'altro inizi a interagire con essa tramite API. Inizialmente, \u00e8 sufficiente che tramite API avvenga solo la scrittura. Questa \u00e8 una condizione necessaria affinch\u00e9 possiamo parlare di indipendenza dei microservizi. Le connessioni 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 consiste gi\u00e0 nel poter estrarre la parte di codice che lavora con le tabelle separabili, con o senza riprogettazione, in un microservizio autonomo e farlo funzionare in un processo separato, in un container. Questo sar\u00e0 un servizio separato con una connessione alla base dati del monolite e alle tabelle che non lo riguardano direttamente. Il monolite continua 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, elimineremo questa connessione, cio\u00e8 trasferiremo anche la lettura dei dati dell'applicazione monolitica dalle tabelle separabili all'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 \/>\nIniziamo estraendo dalla base di dati generale le tabelle con cui interagisce solo il nuovo microservizio. Possiamo spostare le tabelle in uno schema separato o persino in un database fisico distinti. Rimane una connessione in lettura tra il microservizio e il database del monolite, ma non c'\u00e8 nulla di cui preoccuparsi, in questa configurazione pu\u00f2 funzionare a 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 passaggio \u00e8 rimuovere completamente tutte le connessioni. In questo caso, potrebbe essere necessaria una migrazione dei dati dalla base di dati principale. A volte desideriamo riutilizzare in diverse basi dati alcuni dati replicabili da sistemi esterni o delle referenze. Questo accade periodicamente.<\/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>Separazione con rielaborazione.<\/b> Questo metodo \u00e8 molto simile al primo, solo che avviene al contrario. Viene immediatamente creata una nuova base di dati e un nuovo microservizio, che interagisce con il monolite tramite API. Tuttavia, rimane un insieme di tabelle del database che vogliamo eliminare in futuro. Non ci sar\u00e0 pi\u00f9 bisogno di esse, nella nuova configurazione le abbiamo sostituite.<\/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>Ci sono due approcci possibili.<\/p>\n<p><b>Primo<\/b>: Duplichiamo tutti i dati nei nuovi e vecchi database. In questo caso, abbiamo un'eccesso di dati e possono sorgere problemi di sincronizzazione. Tuttavia, possiamo utilizzare due clienti diversi. Uno lavorer\u00e0 con la nuova versione, l'altro con quella vecchia.<\/p>\n<p><b>Secondo<\/b>: Separiamo i dati in base a un particolare criterio aziendale. Ad esempio, nel nostro sistema erano presenti 5 prodotti memorizzati nel vecchio database. Il sesto, per una nuova esigenza aziendale, viene inserito nel nuovo database. Ma avremo bisogno di un API Gateway per sincronizzare questi dati e mostrare al cliente da dove e cosa prelevare.<\/p>\n<p>Entrambi gli approcci sono validi, scegli in base alla situazione.<\/p>\n<p>Dopo aver verificato che tutto funziona, \u00e8 possibile disattivare la parte del monolite che gestisce le vecchie strutture del 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 eliminare le vecchie strutture di 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 il database: \u00e8 difficile lavorarci rispetto al codice sorgente, \u00e8 pi\u00f9 complicato dividerlo, ma \u00e8 possibile e necessario. Abbiamo trovato alcuni modi per farlo in modo abbastanza sicuro, poich\u00e9 \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 com'era la struttura 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 dividerlo in tre strati. Questo strato comprende moduli eseguibili, plugin, servizi e singole attivit\u00e0. In effetti, erano i punti di accesso all'interno della soluzione monolitica. Tutti erano strettamente uniti dallo strato Common. Qui si trovava la logica di business utilizzata dai servizi comuni e una miriade di legami. Ogni servizio e plugin utilizzava fino a 10 o pi\u00f9 assembly comuni, a seconda della loro grandezza e della correttezza degli sviluppatori.<\/p>\n<p>Siamo stati fortunati, avevamo librerie di infrastruttura che potevamo utilizzare separatamente. <\/p>\n<p>A volte si presentava la situazione in cui alcuni oggetti Common in realt\u00e0 non appartenevano a questo strato, ma erano librerie infrastrutturali. Questo veniva risolto attraverso il rinominare.<\/p>\n<p>Le preoccupazioni maggiori riguardavano i contesti limitati. A volte, 3-4 contesti si mescolavano in un'unica build comune e si utilizzavano l'uno con l'altro all'interno delle stesse funzioni aziendali. Era necessario capire dove poter separare e quali fossero i confini, e cosa fare successivamente con il mapping di questa separazione alle build 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 in totale indipendenza. Ritengo che questo approccio sia piuttosto dispendioso e difficile da raggiungere, poich\u00e9, ad esempio, i servizi C# saranno comunque collegati alla libreria standard. Il nostro sistema \u00e8 scritto in C#, e al momento non abbiamo dovuto utilizzare altre tecnologie. Pertanto, abbiamo deciso che ci possiamo permettere di utilizzare assembly tecnici comuni. L'importante \u00e8 che non ci siano frammenti di logica di business. Se avete un wrapper comodo per l'ORM che state utilizzando, copiarlo da un servizio all'altro \u00e8 molto costoso.<\/p>\n<p>Il nostro team \u00e8 appassionato di design orientato agli oggetti, quindi l'\u00abarchitettura a cipolla\u00bb si \u00e8 rivelata perfetta per noi. Alla base dei nostri servizi non c'\u00e8 un data access layer, ma un'aggregazione con logica di dominio, che contiene solo la logica di business ed \u00e8 priva di legami con l'infrastruttura. In questo modo, possiamo sviluppare indipendentemente l'aggregazione di dominio per risolvere i problemi legati ai framework.<\/p>\n<p>In questa fase abbiamo incontrato il primo grande problema. Il servizio doveva fare riferimento a un'unica build di dominio, mentre volevamo creare una logica indipendente, e qui il principio DRY ci ha ostacolato notevolmente. Gli sviluppatori volevano evitare la duplicazione riutilizzando le classi da build adiacenti, e di conseguenza i domini hanno cominciato di nuovo a collegarsi tra loro. Abbiamo analizzato i risultati e abbiamo deciso che, forse, il problema risiedeva anche nell'architettura della memorizzazione del codice sorgente. Avevamo un grande repository che conteneva tutto il codice sorgente. Era molto difficile raccogliere la soluzione per l'intero progetto su una macchina locale. Pertanto, per le parti del progetto venivano create piccole soluzioni separate, e nessuno vietava di aggiungere in esse una Common- o una build di dominio e riutilizzarle. L'unico strumento che non ci permetteva di farlo era il code review. Ma anche questo talvolta 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 diventati realmente indipendenti. I contesti limitati sono supportati in modo pi\u00f9 chiaro. Come riutilizziamo le librerie infrastrutturali? Le abbiamo scorporate in un repository separato, quindi le abbiamo inserite in pacchetti Nuget, che abbiamo collocato in Artifactory. Con qualsiasi modifica, la compilazione e la pubblicazione avvengono automaticamente.<\/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 ora fanno riferimento ai pacchetti infrastrutturali interni proprio come a quelli esterni. Scarichiamo le librerie esterne da Nuget. Per lavorare con Artifactory, dove collocavamo questi pacchetti, abbiamo utilizzato due gestori di pacchetti. Nei piccoli repository abbiamo usato Nuget. Nei repository con pi\u00f9 servizi abbiamo utilizzato 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 degli svantaggi nel passaggio ai microservizi \u00e8 legata all'infrastruttura. Avrai bisogno di distribuzioni automatizzate e di nuove librerie per la gestione dell'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 sugli ambienti. Per automatizzare questo processo, abbiamo creato una pipeline CI\/CD. Abbiamo scelto il processo di continuous delivery, poich\u00e9 il continuous deployment non \u00e8 ancora accettabile per noi dal punto di vista dei processi aziendali. Pertanto, il rilascio in produzione avviene con un clic, mentre la fase di test \u00e8 automatica.<\/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 build. Ci piace scrivere script di build in Cake, poich\u00e9 \u00e8 lo stesso C#. I pacchetti pronti arrivano in Artifactory, e Ansible viene automaticamente inviato ai server di test, quindi possono essere testati immediatamente.<\/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 la registrazione condivisa. Dovevamo anche capire cosa fare con i singoli log che si trovavano sui dischi. I log vengono scritti in file di testo. Abbiamo deciso di utilizzare il classico stack ELK. Non abbiamo scritto direttamente in ELK tramite i provider, ma abbiamo scelto di modificare i log di testo e inserire in essi l'ID di tracciamento come identificatore, aggiungendo il nome del servizio, in modo da poter analizzare poi questi log.<\/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 abbiamo 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 elaborarli, costruire query con Kibana nell'interfaccia utente e vedere come avveniva la chiamata tra i servizi. In questo ci aiuta molto l'ID di tracciamento.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"15\"><\/a><\/noindex><b><\/p>\n<h3>Test e debugging dei servizi correlati<\/h3>\n<p><\/b><br \/>\nInizialmente non capivamo completamente come debbiamo fare il debug dei servizi in fase di sviluppo. Con il monolite era semplice, lo avviavamo sulla macchina locale. Inizialmente cercavamo di fare lo stesso con i microservizi, ma a volte per avviare completamente un microservizio \u00e8 necessario avviarne anche altri, e questo non \u00e8 pratico. Abbiamo capito che era necessario passare a un modello in cui lasciamo sulla macchina locale solo il servizio o i servizi che vogliamo debuggare. Gli altri servizi vengono utilizzati da server che corrispondono alla configurazione di produzione. Dopo il debug, durante i test, per ogni compito sul server di test vengono distribuiti solo i servizi modificati. In questo modo, la soluzione viene testata nella forma in cui si trover\u00e0 in produzione in futuro.<\/p>\n<p>Ci sono server che ospitano solo le versioni di produzione dei servizi. Questi server sono necessari in caso di incidenti, per verificare la distribuzione prima del deployment e per formazione interna.<\/p>\n<p>Abbiamo implementato un processo di test automatico utilizzando la popolare libreria Specflow. I test vengono eseguiti automaticamente tramite NUnit subito dopo il deploy da Ansible. Se la copertura del task \u00e8 completamente automatica, non \u00e8 necessaria la verifica manuale. Tuttavia, a volte \u00e8 comunque richiesto un ulteriore testing manuale. Per determinare quali test eseguire per un task specifico, utilizziamo i tag in Jira.<\/p>\n<p>Inoltre, \u00e8 aumentata la necessit\u00e0 di effettuare test di carico, precedentemente condotti solo in rare occasioni. Per eseguire i test utilizziamo JMeter, per il loro storage InfluxDB, e per visualizzare i grafici del processo Grafana.<\/p>\n<p><b><\/p>\n<h3>Quali risultati abbiamo ottenuto?<\/h3>\n<p><\/b><br \/>\nPrima di tutto, abbiamo eliminato il concetto di 'release'. Sono scomparsi i mostruosi rilasci bimestrali, quando questa macchina veniva distribuita in ambiente di produzione, interrompendo temporaneamente i processi aziendali. Ora distribuiamo servizi in media ogni 1,5 giorni, raggruppandoli, poich\u00e9 entrano in produzione dopo un'approvazione.<\/p>\n<p>Nel nostro sistema non ci sono errori fatali. Se rilasciamo un microservizio con un errore, la funzionalit\u00e0 associata sar\u00e0 compromessa, mentre tutte le altre funzionalit\u00e0 rimarranno intatte. Questo migliora notevolmente l'esperienza dell'utente.<\/p>\n<p>Possiamo gestire lo schema di distribuzione. \u00c8 possibile isolare i gruppi di servizi dal resto della soluzione, se necessario.<\/p>\n<p>Inoltre, abbiamo ridotto significativamente il problema delle lunghe code di modifiche. Abbiamo creato team di prodotto separati che lavorano su alcune parti dei servizi in modo indipendente. Qui, il processo Scrum si adatta bene. Ogni team pu\u00f2 avere un proprio proprietario di prodotto che assegna i compiti. <\/p>\n<p><b><\/p>\n<h3>Riepilogo<\/h3>\n<p><\/b><\/p>\n<ul>\n<li>I microservizi sono particolarmente adatti per la decomposizione di sistemi complessi. Durante il processo, iniziamo a capire cosa c'\u00e8 nel nostro sistema, quali contesti limitati esistono e dove passano i loro confini. Questo ci consente di distribuire correttamente le modifiche tra i moduli e di evitare che il codice si confonda. <\/li>\n<li>I micrservizi offrono vantaggi organizzativi. Spesso se ne parla solo come di architettura, ma ogni architettura \u00e8 necessaria per soddisfare le esigenze aziendali, e non esiste per s\u00e9 stessa. Pertanto, possiamo affermare che i micrservizi sono adatti per risolvere compiti in piccoli team, considerando la popolarit\u00e0 del Scrum al giorno d'oggi.<\/li>\n<li>La suddivisione \u00e8 un processo iterativo. Non \u00e8 possibile prendere un'applicazione e semplicemente dividerla in micrservizi. Il prodotto risultante difficilmente sar\u00e0 funzionante. Quando si estraggono i micrservizi, \u00e8 vantaggioso riscrivere il legacy esistente, cio\u00e8 trasformarlo in codice che ci piace e soddisfa meglio le esigenze aziendali in termini di funzionalit\u00e0 e velocit\u00e0.\n<p><i>Una piccola avvertenza:<\/i> I costi di transizione verso i microservizi sono piuttosto sostanziali. Solo per risolvere i problemi di infrastruttura \u00e8 stato impiegato molto tempo. Pertanto, se hai un'applicazione piccola che non richiede scalabilit\u00e0 specifica, se non ci sono molti clienti che competono per l'attenzione e il tempo del tuo team, allora forse i microservizi non sono ci\u00f2 di cui hai bisogno oggi. \u00c8 piuttosto costoso. Se inizi il processo con i microservizi, i costi iniziali saranno maggiori rispetto all'avvio dello stesso progetto con uno sviluppo monolitico. <\/p>\n<p>P.S. Una narrazione pi\u00f9 emotiva (come se fosse personale per te) \u2013 su <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=qTNbx18DzpQ\">link<\/a><\/noindex>. <br \/>\nQui c'\u00e8 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 4.9.10 - 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. \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\" \/>\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) 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\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. \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\" \/>\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 monolito ai microservizi: storia e pratica | ProHoster","description":"In questo articolo parler\u00f2 di come il progetto su cui lavoro si \u00e8 trasformato da un grande monolito a un insieme di microservizi. Il progetto ha avuto inizio tantissimo tempo fa, all'inizio del 2000. Le prime versioni erano scritte in Visual Basic 6. Con il tempo, \u00e8 diventato chiaro che lo sviluppo in questo linguaggio sarebbe stato difficile da supportare in futuro, poich\u00e9 l'IDE","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. \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","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"},"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}]}}