Questo è il secondo tutorial di un percorso di apprendimento che ti insegna a modularizzare e containerizzare un'app monolitica.
Il percorso di apprendimento è costituito dai seguenti tutorial:
- Panoramica
- Informazioni sul monolite
- Modularizza il monolite (questo tutorial)
- Preparare l'app modulare per la containerizzazione
- Containerizzare l'app modulare
- Esegui il deployment dell'app in un cluster GKE
Nel tutorial precedente, Comprendere il monolite, hai scoperto un'app monolitica chiamata Cymbal Books. Hai eseguito il monolite sulla tua macchina locale e hai scoperto che le diverse parti del monolite comunicano tra loro tramite i rispettivi endpoint.
In questo tutorial vedrai come dividere il monolite in moduli per prepararlo alla containerizzazione. Non devi eseguire personalmente i passaggi di modularizzazione perché il codice è già stato aggiornato. Il tuo compito è seguire il tutorial ed esplorare la versione modulare dell'app nel repository per vedere in che modo si differenzia dal monolite originale.
Costi
Puoi completare questo tutorial senza incorrere in alcun addebito. Tuttavia, seguendo i passaggi descritti nell'ultimo tutorial di questa serie, verranno addebitati costi sul tuo accountGoogle Cloud . I costi iniziano quando abiliti GKE ed esegui il deployment dell'app Cymbal Books in un cluster GKE. Questi costi includono gli addebiti per cluster per GKE, come descritto nella pagina dei prezzi, e gli addebiti per l'esecuzione delle VM di Compute Engine.
Per evitare addebiti non necessari, assicurati di disabilitare GKE o eliminare il progetto al termine di questo tutorial.
Prima di iniziare
Prima di iniziare questo tutorial, assicurati di aver completato il primo tutorial, Comprendere il monolite. In questo tutorial, esegui la versione modulare di Cymbal Books sulla tua macchina locale. Per farlo, devi aver già configurato il tuo ambiente. Se hai già completato il primo tutorial, hai clonato un repository GitHub. Tutte e tre le versioni dell'app Cymbal Books si trovano in questo repository, all'interno delle seguenti cartelle:
monolith/
modular/
containerized/
Prima di continuare, controlla che queste cartelle siano presenti sul tuo computer. Inoltre, assicurati
che l'ambiente virtuale book-review-env
sia attivo. Se hai bisogno di un promemoria
su come attivarlo, consulta
Creare e attivare un ambiente virtuale del
primo tutorial. L'attivazione dell'ambiente garantisce che la versione modulare
dell'app abbia tutto ciò che serve per essere eseguita.
Che cos'è la modularizzazione?
In questo tutorial imparerai a modularizzare l'app monolitica per prepararla alla containerizzazione. La modularizzazione è il processo di trasformazione di un monolite in un'app modulare. Come hai imparato nel tutorial precedente, la caratteristica distintiva di un monolite è che i suoi componenti non possono essere eseguiti o scalati in modo indipendente. Un'app modulare è diversa: la sua funzionalità è suddivisa in moduli che possono essere eseguiti e scalati in modo indipendente.
Sebbene la modularizzazione e la containerizzazione vengano spesso eseguite insieme, in questa serie di tutorial vengono trattate come passaggi separati per aiutarti a comprendere chiaramente ogni concetto. Questo tutorial spiega come modularizzare un monolite e un tutorial successivo spiega come containerizzare l'app modulare.
Modularizzazione incrementale
Negli ambienti di produzione, in genere si modularizza un componente alla volta. Modularizza il componente, integra il modulo con il monolite e assicurati che tutto funzioni prima di lavorare sul componente successivo. Questo stato ibrido, in cui alcuni componenti sono modulari mentre altri rimangono parte del monolite, è chiamato microlite. Tuttavia, in questo tutorial, tutti i componenti dell'app vengono modularizzati contemporaneamente per fornire un esempio completo di come modularizzare un'app.
Come modularizzare il monolite
In questa sezione, imparerai come il monolite Cymbal Books è stato suddiviso in moduli separati. Sono forniti passaggi per aiutarti a comprendere il processo di modularizzazione in modo da poterlo applicare alle tue app. Tuttavia, non devi eseguire questi passaggi in questo tutorial perché il repository clonato include già la versione modulare dell'app:
- Identificare le funzioni distinte dell'app
- Crea i moduli
- Attivare la comunicazione tra i moduli
- Concedere a ogni modulo l'accesso solo ai dati di cui ha bisogno
Identificare le diverse funzioni dell'app
Il primo passaggio per modularizzare il monolite Cymbal Books consiste nell'identificare le sue funzioni principali. Nell'applicazione di esempio Cymbal Books, il monolite ha le seguenti quattro funzioni distinte:
- Pubblicazione della home page
- Visualizzazione dei dettagli del libro
- Pubblicazione delle recensioni dei libri
- Gestione delle immagini di copertina dei libri
Crea i moduli
Come hai visto nel tutorial precedente, il monolite è una singola app Flask che implementa le quattro funzioni identificate nella sezione precedente come gestori di route. Per modularizzare l'app, prendi ogni gestore di route e inseriscilo nella propria app Flask. Invece di un'app Flask con quattro gestori di route, hai quattro app Flask, ognuna con un singolo gestore di route al suo interno.
Il seguente diagramma illustra questa trasformazione da una singola app Flask a quattro app Flask separate:
Nell'app modulare, ogni app Flask viene eseguita in modo indipendente e rimane in ascolto su una porta diversa (8080, 8081, 8082, 8083), come mostrato nel diagramma. Questa configurazione è necessaria perché, quando testerai l'app modulare più avanti in questo tutorial, eseguirai tutti i moduli sulla stessa macchina. Ogni app ha bisogno di un numero di porta diverso per evitare conflitti.
Il modulo della home page ha due responsabilità: serve la home page e comunica con gli altri moduli per raccogliere i dati da visualizzare in una pagina web. Ciascuno degli altri moduli è incentrato su una singola funzione: pubblicazione di recensioni, dettagli o immagini. Questi moduli non comunicano tra loro, ma rispondono solo alle richieste del modulo della home page.
Sebbene il modulo della home page abbia un ruolo di coordinamento aggiuntivo, l'app è comunque modulare perché puoi aggiornare qualsiasi modulo senza influire sugli altri moduli. La singola applicazione Flask di grandi dimensioni è stata suddivisa in quattro parti, ognuna delle quali gestisce una parte specifica della funzionalità dell'applicazione.
Attivare la comunicazione tra i moduli
Dopo aver creato i moduli, il passaggio successivo consiste nell'assicurarsi che possano comunicare
tra loro. Nell'app Cymbal Books, questa logica di comunicazione è già
stata implementata per te. Nella cartella modular/
del codice che hai scaricato,
puoi vedere che ciascuna delle funzionalità principali dell'app, ovvero la visualizzazione della home page, i dettagli dei libri, le recensioni e le immagini, è implementata come app Flask separata.
Ciascuna di queste app definisce il proprio endpoint HTTP e i moduli comunicano inviando richieste HTTP a questi endpoint.
La modularizzazione del monolite Cymbal Books è stata semplice. Il monolite ha componenti ben definiti implementati come gestori di route e ogni gestore di route ha un endpoint ben definito. Quando questi gestori di route vengono inseriti in applicazioni Flask separate, mantengono la capacità di comunicare tramite i loro endpoint. La semplice azione di inserire i gestori di route in app Flask separate crea i moduli e consente loro di comunicare tra loro.
Un approccio comune per la comunicazione tra moduli è l'implementazione di API REST, che consentono ai moduli di inviarsi reciprocamente richieste HTTP. È così che funziona in Cymbal Books: ogni modulo definisce gli endpoint REST utilizzando gli strumenti integrati di Flask. Un altro approccio diffuso è gRPC, che consente ai moduli di chiamare direttamente le funzioni di ciascuno.
Perché la comunicazione è semplice in Cymbal Books
Ogni modulo dell'app modulare è un'applicazione Flask separata che viene eseguita all'interno di un server web. Ad esempio, il modulo della home page serve la home page, mentre il modulo dei dettagli del libro serve i dettagli del libro. La comunicazione tra i moduli è semplice perché i server web sono progettati per gestire richieste e risposte HTTP. Ogni modulo espone endpoint che altri moduli possono utilizzare per richiedere dati.
Concedere a ogni modulo l'accesso solo ai dati di cui ha bisogno
Per modularizzare correttamente il monolite, devi assicurarti che ogni modulo abbia accesso solo ai dati di cui ha bisogno. Questo principio, noto come isolamento dei dati, è un elemento fondamentale per creare un'architettura veramente modulare.
Un errore frequente che si commette durante la modularizzazione è consentire a più moduli di accedere agli stessi dati, ad esempio a un singolo database. Questo tipo di implementazione crea problemi come i seguenti:
- Accoppiamento stretto: se la struttura dei dati condivisi cambia, ad esempio se viene rinominata una tabella di database o viene aggiunta una colonna, ogni modulo che si basa su questi dati deve essere aggiornato. Una corretta modularizzazione evita questo problema.
- Problemi di tolleranza agli errori: quando più moduli utilizzano la stessa origine dati, gli errori di runtime in un modulo, ad esempio query non valide o traffico eccessivo, possono interrompere altri moduli. Un errore in una parte del sistema può propagarsi ad altre parti del sistema.
- Colli di bottiglia delle prestazioni: una singola origine dati condivisa può diventare un collo di bottiglia, il che significa che potrebbe rallentare l'intera applicazione quando più moduli tentano di interagire con essa.
Per evitare questi problemi, ogni modulo deve avere la propria origine dati.
Se Cymbal Books avesse utilizzato un database per archiviare i propri dati, dovresti replicare o partizionare il database per applicare l'isolamento dei dati e assicurarti che ogni modulo acceda solo ai dati di cui ha bisogno. La replica prevede la gestione di copie separate del database per ogni modulo, mentre il partizionamento limita l'accesso a tabelle o righe specifiche. Entrambi gli approcci impediscono ai moduli di interferire con i dati degli altri.
Il seguente diagramma confronta l'architettura dell'app per libri monolitica con l'architettura modulare dell'app per libri:
L'implementazione del monolite non segue il principio dell'isolamento dei dati
perché le funzioni del monolite accedono a una singola directory data/
.
Al contrario, l'app modulare raggiunge un certo grado di isolamento dei dati suddividendoli in directory separate e garantendo che ogni modulo interagisca solo con i dati designati:
- Il modulo dei dettagli del libro riceve i dati solo dalla directory
details_data/
. - Il modulo delle recensioni dei libri riceve i dati solo dalla directory
reviews_data/
. - Il modulo Immagini riceve i dati solo dalla directory
images/
.
In un tutorial successivo, vedrai come la containerizzazione dell'app può migliorare ulteriormente l'isolamento dei dati.
Cosa hai appena visto
Nel settore dello sviluppo software, spesso si incontrano i termini microservizi e sistemi distribuiti. Questa sezione spiega il rapporto tra questi termini e l'implementazione modulare di Cymbal Books.
Microservizi
I microservizi sono moduli autonomi che svolgono attività specifiche. Questi moduli comunicano con altri moduli tramite interfacce come gli endpoint.
Ogni modulo della versione modulare di Cymbal Books corrisponde a questa definizione e può pertanto essere definito microservizio. Quando l'app modulare viene inserita in un container in un tutorial successivo, il codice eseguito all'interno di un container può essere chiamato anche microservizio perché è lo stesso codice eseguito all'interno di un modulo.
Sistemi distribuiti
Un sistema distribuito è costituito da moduli indipendenti che comunicano su una rete per raggiungere un obiettivo comune. Questi moduli possono essere eseguiti su macchine diverse, ma funzionano insieme come un unico sistema.
Anche l'app modulare Cymbal Books rientra in questa definizione: i suoi moduli vengono eseguiti in modo indipendente e scambiano dati tramite HTTP, ma insieme funzionano come un unico sistema. Nella sezione successiva, esegui tutti i moduli su una singola macchina per semplicità, ma non è obbligatorio. Ogni modulo potrebbe essere eseguito su un server diverso, motivo per cui la versione modulare dell'app Cymbal Books può essere classificata come sistema distribuito.
Testare l'implementazione modulare
Ora che hai visto come il monolite di Cymbal Books viene trasformato in un'app modulare i cui moduli sono app Flask, puoi testare l'applicazione e vedere che ogni modulo viene eseguito in modo indipendente.
In questo tutorial, esegui i moduli sulla stessa macchina. Tuttavia, potresti eseguire ogni modulo su un server separato: poiché ogni modulo è autonomo, può comunicare con gli altri moduli tramite i relativi endpoint.
Configura l'ambiente
Segui questi passaggi per prepararti al test:
Nel terminale, vai alla directory
modular
nel repository clonato:cd modular
Assicurati che l'ambiente virtuale
book-review-env
sia attivo. Se hai bisogno di un promemoria sui passaggi di attivazione, consulta Creare e attivare un ambiente virtuale.
Avvia l'app Flask
La cartella /modular
contiene uno script bash che avvia tutte le applicazioni Flask
contemporaneamente. Ogni modulo dell'app è in ascolto su una porta univoca,
ad esempio 8080 o 8081:
- App Flask della home page (home.py): porta 8080
- App Flask con dettagli del libro (book_details.py): porta 8081
- App Flask per le recensioni di libri (book_reviews.py): porta 8082
- App Flask per le immagini (images.py): porta 8083
Ogni modulo deve essere in ascolto su un numero di porta univoco perché tutti i moduli vengono eseguiti sulla stessa macchina. Se ogni modulo si trovava su un server diverso, ognuno poteva ascoltare lo stesso numero di porta senza creare conflitti.
Esegui lo script bash con questo comando:
bash ./start_services.sh
Lo script crea un file di log separato per ogni app Flask (ad esempio,
home.py.log
, book_details.py.log
) per aiutarti a identificare eventuali problemi di avvio.
Al termine dello script, viene visualizzato questo messaggio:
All services have been started. Access the app at http://localhost:8080/
Testa ogni app Flask
Testa i moduli visitando i seguenti URL nel browser:
- Home page:
http://localhost:8080/
mostra la home page dell'applicazione modulare Cymbal Books. Questa pagina recupera i dettagli del libro, le recensioni e le immagini effettuando richieste agli altri moduli. - Dettagli del libro:
http://localhost:8081/book/1
restituisce i dettagli del libro con ID 1. Questa risposta è costituita da dati JSON che l'app formatta e visualizza in un formato più leggibile. - Recensioni di libri:
http://localhost:8082/book/1/reviews
recupera e restituisce le recensioni del libro con ID 1. Le recensioni sono in formato JSON. Il modulo della home page richiede questi dati e li integra nella pagina dei dettagli del libro. - Immagini:
http://localhost:8083/images/fungi_frontier.jpg
pubblica l'immagine della copertina del libro Fungi Frontier. Se l'URL è corretto, l'immagine dovrebbe caricarsi direttamente nel browser.
Interrompi le app Flask
Al termine del test, interrompi tutte le app Flask con questo comando:
kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)
Riepilogo
Questo tutorial ti ha mostrato come modularizzare il monolite Cymbal Books. La procedura prevede i seguenti passaggi:
- Identificazione dei componenti distinti dell'app
- Creazione dei moduli
- Garantire che ogni modulo abbia accesso solo ai dati di cui ha bisogno
Poi hai testato l'implementazione modulare sulla tua macchina locale.
Passaggi successivi
Nel tutorial successivo, Preparare l'app modulare per la containerizzazione, imparerai a preparare l'app modulare per la containerizzazione aggiornando gli endpoint in modo che utilizzino i nomi dei servizi Kubernetes anziché localhost
.