Parcours de formation : Transformer un monolithe en application GKE – Modulariser le monolithe

Il s'agit du deuxième tutoriel d'un parcours de formation qui vous explique comment modulariser et conteneuriser une application monolithique.

Le parcours de formation comprend les tutoriels suivants :

  1. Présentation
  2. Comprendre le monolithe
  3. Modulariser le monolithe (ce tutoriel)
  4. Préparer l'application modulaire à la conteneurisation
  5. Conteneuriser l'application modulaire
  6. Déployer l'application dans un cluster GKE

Dans le tutoriel précédent, Comprendre le monolithe, vous avez découvert une application monolithique appelée Cymbal Books. Vous avez exécuté le monolithe sur votre ordinateur local et appris que différentes parties du monolithe communiquent entre elles via leurs points de terminaison.

Dans ce tutoriel, vous allez découvrir comment diviser le monolithe en modules pour le préparer à la conteneurisation. Vous n'avez pas besoin d'effectuer vous-même les étapes de modularisation, car le code a déjà été mis à jour pour vous. Votre tâche consiste à suivre le tutoriel et à explorer la version modulaire de l'application dans le dépôt pour voir en quoi elle diffère du monolithe d'origine.

Coûts

Vous pouvez suivre ce tutoriel sans frais. Toutefois, les étapes du dernier tutoriel de cette série entraînent des frais sur votre Google Cloud compte. Les coûts commencent lorsque vous activez GKE et déployez l'application Cymbal Books dans un cluster GKE. Ces coûts incluent les frais par cluster pour GKE, comme indiqué sur la page Tarifs, et les frais d'exécution des VM Compute Engine.

Pour éviter des frais inutiles, assurez-vous de désactiver GKE ou de supprimer le projet une fois ce tutoriel terminé.

Avant de commencer

Avant de commencer ce tutoriel, assurez-vous d'avoir suivi le premier tutoriel, Comprendre le monolithe. Dans ce tutoriel, vous allez exécuter la version modulaire de Cymbal Books sur votre ordinateur local. Pour ce faire, vous devez déjà avoir configuré votre environnement. Si vous avez déjà suivi le premier tutoriel, vous avez cloné un dépôt GitHub. Les trois versions de l'application Cymbal Books se trouvent dans ce dépôt, dans les dossiers suivants :

  • monolith/
  • modular/
  • containerized/

Vérifiez que ces dossiers se trouvent sur votre ordinateur avant de continuer. Assurez-vous également que l'environnement virtuel book-review-env est actif. Si vous avez besoin de vous rappeler comment l'activer, consultez Créer et activer un environnement virtuel dans le premier tutoriel. L'activation de l'environnement garantit que la version modulaire de l'application dispose de tout ce dont elle a besoin pour s'exécuter.

Qu'est-ce que la modularisation ?

Dans ce tutoriel, vous allez apprendre à modulariser l'application monolithique afin de la préparer à la conteneurisation. La modularisation est le processus de transformation d'un monolithe en une application modulaire. Comme vous l'avez appris dans le tutoriel précédent, la caractéristique distinctive d'un monolithe est que ses composants ne peuvent pas s'exécuter ni évoluer indépendamment. Une application modulaire est différente : sa fonctionnalité est divisée en modules qui peuvent s'exécuter et évoluer indépendamment.

Bien que la modularisation et la conteneurisation soient souvent effectuées ensemble, elles sont traitées comme des étapes distinctes dans cette série de tutoriels pour vous aider à comprendre clairement chaque concept. Ce tutoriel explique comment modulariser un monolithe, et un tutoriel ultérieur explique comment conteneuriser l'application modulaire.

Modularisation incrémentielle

Dans les environnements de production, vous modularisez généralement un composant à la fois. Vous modularisez le composant, intégrez le module au monolithe et vous assurez que tout fonctionne avant de travailler sur le composant suivant. Cet état hybride, dans lequel certains composants sont modularisés tandis que d'autres restent partie intégrante du monolithe, est appelé microlithe. Toutefois, dans ce tutoriel, tous les composants de l'application sont modularisés en même temps pour fournir un exemple complet de la façon de modulariser une application.

Modulariser le monolithe

Dans cette section, vous allez découvrir comment le monolithe Cymbal Books a été divisé en modules distincts. Des étapes sont fournies pour vous aider à comprendre le processus de modularisation afin que vous puissiez l'appliquer à vos propres applications. Toutefois, vous n'avez pas besoin d'effectuer ces étapes dans ce tutoriel, car le dépôt cloné inclut déjà la version modulaire de l'application :

  1. Identifier les fonctions distinctes de l'application
  2. Créer les modules
  3. Activer la communication entre les modules
  4. N'autoriser chaque module à accéder qu'aux données dont il a besoin

Identifier les fonctions distinctes de l'application

La première étape de la modularisation du monolithe Cymbal Books consiste à identifier ses fonctions principales. Dans l'exemple d'application Cymbal Books, le monolithe comporte les quatre fonctions distinctes suivantes :

  • Diffuser la page d'accueil
  • Diffuser les informations sur les livres
  • Diffuser les avis sur les livres
  • Diffuser les images de couverture des livres

Créer les modules

Comme vous l'avez vu dans le tutoriel précédent, le monolithe est une application Flask unique qui implémente les quatre fonctions, identifiées dans la section précédente, en tant que gestionnaires de routes. Pour modulariser l'application, vous prenez chaque gestionnaire de routes et le placez dans sa propre application Flask. Au lieu d'une application Flask avec quatre gestionnaires de routes, vous disposez de quatre applications Flask, chacune contenant un seul gestionnaire de routes.

Le schéma suivant illustre cette transformation d'une application Flask unique en quatre applications Flask distinctes :

Transformation du monolithe en application modulaire

Dans l'application modulaire, chaque application Flask s'exécute indépendamment et écoute sur un port différent (8080, 8081, 8082, 8083), comme illustré dans le schéma. Cette configuration est nécessaire, car lorsque vous testez l'application modulaire plus loin dans ce tutoriel, vous exécutez tous les modules sur la même machine. Chaque application a besoin d'un numéro de port différent pour éviter les conflits.

Le module de la page d'accueil a deux responsabilités : il diffuse la page d'accueil et communique avec les autres modules pour collecter les données à afficher sur une page Web. Chacun des autres modules est axé sur une seule fonction : diffuser des avis, des informations ou des images. Ces modules ne communiquent pas entre eux. Ils ne répondent qu'aux requêtes du module de la page d'accueil.

Bien que le module de la page d'accueil ait un rôle de coordination supplémentaire, l'application reste véritablement modulaire, car vous pouvez mettre à jour n'importe quel module sans affecter les autres. La grande application Flask unique a été divisée en quatre parties, chacune gérant une partie spécifique des fonctionnalités de l'application.

Activer la communication entre les modules

Après avoir créé les modules, l'étape suivante consiste à s'assurer qu'ils peuvent communiquer entre eux. Dans l'application Cymbal Books, cette logique de communication a déjà été implémentée pour vous. Dans le dossier modular/ du code que vous avez téléchargé, vous pouvez voir que chacune des principales fonctionnalités de l'application (diffusion de la page d'accueil, des informations sur les livres, des avis et des images) est implémentée en tant qu'application Flask distincte. Chacune de ces applications définit son propre point de terminaison HTTP, et les modules communiquent en envoyant des requêtes HTTP à ces points de terminaison.

La modularisation du monolithe Cymbal Books a été simple. Le monolithe comporte des composants bien définis qui sont implémentés en tant que gestionnaires de routes, et chaque gestionnaire de routes possède un point de terminaison bien défini. Lorsque ces gestionnaires de routes sont placés dans des applications Flask distinctes, ils conservent leur capacité à communiquer via leurs points de terminaison. Le simple fait de placer les gestionnaires de routes dans des applications Flask distinctes crée les modules et leur permet de communiquer entre eux.

Une approche courante pour la communication inter-modules consiste à implémenter des API REST, qui permettent aux modules de s'envoyer des requêtes HTTP. C'est ainsi que cela fonctionne dans Cymbal Books : chaque module définit des points de terminaison REST à l'aide des outils intégrés de Flask. Une autre approche courante est gRPC, qui permet aux modules d'appeler directement les fonctions des autres.

Pourquoi la communication est simple dans Cymbal Books

Chaque module de l'application modulaire est une application Flask distincte qui s'exécute dans un serveur Web. Par exemple, le module de la page d'accueil diffuse la page d'accueil, et le module d'informations sur les livres diffuse les informations sur les livres. La communication entre les modules est simple, car les serveurs Web sont conçus pour gérer les requêtes et les réponses HTTP. Chaque module expose des points de terminaison que les autres modules peuvent utiliser pour demander des données.

N'autoriser chaque module à accéder qu'aux données dont il a besoin

Pour modulariser correctement le monolithe, vous devez vous assurer que chaque module n'a accès qu'aux données dont il a besoin. Ce principe, appelé isolation des données, est un élément essentiel de la création d'une architecture véritablement modulaire.

Une erreur fréquente lors de la modularisation consiste à autoriser plusieurs modules à accéder aux mêmes données, par exemple à une seule base de données. Ce type d'implémentation crée des problèmes tels que les suivants :

  • Couplage étroit : si la structure des données partagées change (par exemple, si une table de base de données est renommée ou si une colonne est ajoutée), chaque module qui s'appuie sur ces données doit être mis à jour. Une modularisation appropriée évite ce problème.
  • Problèmes de tolérance aux pannes : lorsque plusieurs modules utilisent la même source de données, les échecs d'exécution dans un module (par exemple, des requêtes non valides ou un trafic excessif) peuvent perturber d'autres modules. Une défaillance dans une partie du système peut entraîner des défaillances dans d'autres parties du système.
  • Goulots d'étranglement des performances : une source de données unique et partagée peut devenir un goulot d'étranglement, ce qui signifie qu'elle peut ralentir l'ensemble de l'application lorsque plusieurs modules tentent d'interagir avec elle.

Pour éviter ces problèmes, chaque module doit avoir sa propre source de données.

Si Cymbal Books avait utilisé une base de données pour stocker ses données, vous devriez répliquer ou partitionner la base de données pour appliquer l'isolation des données et vous assurer que chaque module n'accède qu'aux données dont il a besoin. La réplication implique la maintenance de copies distinctes de la base de données pour chaque module, tandis que le partitionnement limite l'accès à des tables ou des lignes spécifiques. Les deux approches empêchent les modules d'interférer avec les données des autres.

Le schéma suivant compare l'architecture de l'application de livre monolithique à l'architecture modulaire de l'application de livre :

Diagramme montrant comment les versions monolithique et modulaire de l'application gèrent les données

L'implémentation du monolithe ne suit pas le principe d'isolation des données, car les fonctions du monolithe accèdent à un seul répertoire data/.

En revanche, l'application modulaire atteint un certain degré d'isolation des données en divisant les données en répertoires distincts et en s'assurant que chaque module n'interagit qu'avec les données qui lui sont attribuées :

  • Le module d'informations sur les livres n'obtient des données que du répertoire details_data/.
  • Le module d'avis sur les livres n'obtient des données que du répertoire reviews_data/.
  • Le module d'images n'obtient des données que du répertoire images/.

Dans un tutoriel ultérieur, vous verrez comment la conteneurisation de l'application peut améliorer l'isolation des données.

Ce que vous venez de voir

Dans le secteur du développement de logiciels, vous rencontrez souvent les termes microservices et systèmes distribués. Cette section explique comment ces termes sont liés à l'implémentation modulaire de Cymbal Books.

Microservices

Les microservices sont des modules autonomes qui effectuent des tâches spécifiques. Ces modules communiquent avec d'autres modules via des interfaces telles que des points de terminaison.

Chaque module de la version modulaire de Cymbal Books correspond à cette définition et peut donc être appelé microservice. Lorsque l'application modulaire est conteneurisée dans un tutoriel ultérieur, le code qui s'exécute dans un conteneur peut également être appelé microservice, car il s'agit du même code qui s'exécute dans un module.

Systèmes distribués

Un système distribué est constitué de modules indépendants qui communiquent sur un réseau pour atteindre un objectif commun. Ces modules peuvent s'exécuter sur différentes machines, mais ils fonctionnent ensemble comme un seul système.

L'application modulaire Cymbal Books correspond également à cette définition : ses modules s'exécutent indépendamment et échangent des données via HTTP, mais ensemble, ils fonctionnent comme un seul système. Dans la section suivante, vous allez exécuter tous les modules sur une seule machine par souci de simplicité, mais ce n'est pas obligatoire. Chaque module peut tout aussi bien s'exécuter sur un serveur différent, c'est pourquoi la version modulaire de l'application Cymbal Books peut être classée comme un système distribué.

Tester l'implémentation modulaire

Maintenant que vous avez vu comment le monolithe Cymbal Books est transformé en une application modulaire dont les modules sont des applications Flask, vous pouvez tester l'application et voir que chaque module s'exécute indépendamment.

Dans ce tutoriel, vous allez exécuter les modules sur la même machine. Toutefois, vous pouvez également exécuter chaque module sur un serveur distinct : comme chaque module est autonome, il peut communiquer avec les autres modules via leurs points de terminaison.

Configurer votre environnement

Procédez comme suit pour vous préparer aux tests :

  1. Dans votre terminal, accédez au répertoire modular du dépôt cloné :

    cd modular
    
  2. Assurez-vous que l'environnement virtuel book-review-env est actif. Si vous avez besoin de vous rappeler les étapes d'activation, consultez Créer et activer un environnement virtuel.

Démarrer l'application Flask

Le dossier /modular contient un script bash qui démarre toutes les applications Flask simultanément. Chaque module de l'application écoute sur un port unique, tel que 8080 ou 8081 :

  • Application Flask de la page d'accueil (home.py) : port 8080
  • Application Flask d'informations sur les livres (book_details.py) : port 8081
  • Application Flask d'avis sur les livres (book_reviews.py) : port 8082
  • Application Flask d'images (images.py) : port 8083

Chaque module doit écouter sur un numéro de port unique, car ils s'exécutent tous sur la même machine. Si chaque module se trouvait sur un serveur différent, chacun pourrait écouter sur le même numéro de port sans créer de conflits de ports.

Exécutez le script bash avec la commande suivante :

bash ./start_services.sh

Le script crée un fichier journal distinct pour chaque application Flask (par exemple, home.py.log, book_details.py.log) afin de vous aider à identifier les problèmes de démarrage. Une fois le script terminé, le message suivant s'affiche :

All services have been started. Access the app at http://localhost:8080/

Tester chaque application Flask

Testez les modules en accédant aux URL suivantes dans votre navigateur :

  • Page d'accueil : http://localhost:8080/ affiche la page d'accueil de l'application Cymbal Books modularisée. Cette page récupère les informations sur les livres, les avis et les images en envoyant des requêtes aux autres modules.
  • Informations sur les livres : http://localhost:8081/book/1 renvoie les informations sur le livre dont l'ID est 1. Cette réponse est constituée de données JSON que l'application met ensuite en forme et affiche de manière plus lisible.
  • Avis sur les livres : http://localhost:8082/book/1/reviews récupère et renvoie les avis sur le livre dont l'ID est 1. Les avis sont au format JSON. Le module de la page d'accueil demande ces données et les intègre à la page d'informations sur les livres.
  • Images: http://localhost:8083/images/fungi_frontier.jpg diffuse l'image de couverture du livre Fungi Frontier. Si l'URL est correcte, l'image doit se charger directement dans votre navigateur.

Arrêter les applications Flask

Une fois les tests terminés, arrêtez toutes les applications Flask avec la commande suivante :

kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)

Résumé

Ce tutoriel vous a montré comment modulariser le monolithe Cymbal Books. Le processus comprend les étapes suivantes :

  1. Identifier les composants distincts de l'application
  2. Créer les modules
  3. S'assurer que chaque module n'a accès qu'aux données dont il a besoin

Vous avez ensuite testé l'implémentation modulaire sur votre ordinateur local.

Étape suivante

Dans le tutoriel suivant, Préparer l'application modulaire à la conteneurisation, vous allez apprendre à préparer l'application modulaire à la conteneurisation en mettant à jour les points de terminaison pour utiliser des noms de service Kubernetes au lieu de localhost.