ws conseil

Back to the blog

Architecture en microservices

April 28th, 2019Logiciel SaaSWilliam

Je suis un grand fan des architectures microservices !

Habituellement, chaque module est développé comme un service spécifique et indépendant accessible via une API REST. L'avantage d'une telle implémentation est qu'elle est facilement évolutive et que le système peut utiliser un équilibreur de charge pour accéder à différentes instances d'un service hautement sollicité.

Le principal problème du protocole REST est sa synchronicité. Si un service est lent ou ne répond pas pour une raison quelconque, le système se bloque ou certaines requêtes comme PUT ou POST sont difficiles à rejouer.

Il est préférable d'utiliser un bus de messages pour la communication entre les services afin d'éviter ce problème. Dans ce cas, les communications sont beaucoup plus faciles du côté du service, ils envoient des messages au bus et consomment les messages du bus, ils n'ont pas besoin de savoir où les instances des autres services fonctionnent. L'équilibreur de charge n'est plus utile car le système peut démarrer à tout moment de nouvelles instances d'un service qui consommera automatiquement les messages du bus.

L'utilisation d'un bus de messages implique une application asynchrone complète. Elle présente de nombreux avantages mais a également un impact sur le développement de l'application. Le débogage d'un Microservice est un défi, et la granularité des fonctionnalités du service est également très difficile à ajuster.

De plus, une architecture Microservice nécessite une surveillance constante pour détecter tout dysfonctionnement de service et gérer le cycle de vie des services.

Exemple de Microservice

Dans cette configuration, chaque Microservice expose une API et est connecté au bus de messagerie. Il peut accéder directement à la base de données pour lire le fichier de configuration si nécessaire. Des services dédiés seront utilisés pour lire ou stocker les données des documents, en fonction de la configuration de chaque client.

Objectifs stratégiques

Les objectifs stratégiques signifient où nous voulons aller avec l'application. Il s'agit d'une conception de haut niveau qui ne devrait pas changer tant que l'application n'aura pas été livrée. Dans la conception d'une architecture Microservice, il est nécessaire de commencer par cette vision globale pour définir les étapes suivantes, jusqu'au niveau le plus bas et le plus détaillé et technique.

Dans notre cas, les objectifs sont les suivants :

  • Permettre un haut niveau de personnalisation
    • Dans la représentation des données
    • Dans les interfaces
    • Dans la définition du workflow
  • Soutenir l'ensemble de l'activité du laboratoire
    • Ouvert à toutes les entreprises de laboratoire, pas seulement à l'industrie de la construction
    • Prise en charge de toutes les normes de l'industrie
  • Évolutif et déployable localement
    • Plus d'un utilisateur et laboratoire sur le même serveur
    • Instance locale pour la sécurité et la confidentialité des données
  • Support d'affichage multiple
    • Ordinateur de bureau, mobile, interface interne et externe comme site web client, intégration tierce partie.

A partir de ces objectifs, nous pouvons définir quelques principes architecturaux

Principes architecturaux

Les principes sont des règles que nous établissons afin d'aligner ce que nous faisons sur nos objectifs stratégiques et qui peuvent changer si nécessaire.

Voilà ce que nous avons :

  • Définition de données sans schéma
    • Rendre la définition des données libre de tout modèle existant et codé en dur.
  • Interfaces cohérentes
    • Les mises en page sont standardisées dans leur représentation et leur conception, même si le contenu est différent. Il n'y a pas de place pour le design fantaisiste.
  • Éliminer la complexité accidentelle
    • Se débarrasser énergiquement des processus, des systèmes et des intégrations complexes inutiles et se concentrer sur la complexité essentielle.
    • Réaliser des modules simples en travaillant ensemble et en se concentrant sur le couplage lâche et la grande cohésion de ces modules.
  • Les services de soutien sont traités comme des ressources rattachées
    • Les accès à la base de données sont des ressources jointes, accessibles via une URL ou un autre localisateur/credentials stockés dans le service de configuration.
    • Chaque service de soutien distinct est une ressource. L'application traite ces bases de données comme des ressources attachées, ce qui indique leur couplage lâche avec le déploiement auquel elles sont attachées.
  • Exécuter l'application comme un ou plusieurs processus sans état
    • Les process sont stateless et ne partagent rien. Toutes les données qui doivent persister doivent être stockées dans un service de sauvegarde dynamique, généralement une base de données.
    • L'espace mémoire ou le système de fichiers du processus peut être utilisé comme un bref cache de transaction unique. Par exemple, télécharger un gros fichier, l'utiliser et stocker les résultats de l'opération dans la base de données. L'application ne suppose jamais que quoi que ce soit en mémoire cache ou sur disque sera disponible sur une demande ou un travail futur.
  • Stocker la configuration dans l'environnement
    • La configuration d'une application est tout ce qui est susceptible de varier entre les déploiements (staging, production, environnements de développement, etc.). Cela inclut :
      • Gestion des ressources vers la base de données, Memcached, et autres services de sauvegarde
      • Identifiants pour les services externes tels que Amazon S3 ou Twitter
      • Valeurs par déploiement telles que le nom d'hôte canonique pour le déploiement.
      • Séparation stricte de la configuration du code. La configuration varie considérablement d'un déploiement à l'autre, ce qui n'est pas le cas du code.
    • L'application stocke la configuration dans des variables d'environnement (souvent raccourcies en env vars ou env). Les Env vars sont faciles à changer d'un déploiement à l'autre sans changer de code. Contrairement aux fichiers de configuration, il y a peu de chance qu'ils soient vérifiés accidentellement dans le code repo.

A partir de ces principes, nous définirons quelques pratiques, qui sont plus une description de leur mise en œuvre.

Pratiques

C'est par les pratiques que nous nous assurons que nos principes sont respectés. Il s'agit d'un ensemble de directives détaillées et pratiques pour l'exécution des tâches. Ils seront souvent spécifiques à une technologie et d'un niveau suffisamment bas pour que n'importe quel développeur puisse les comprendre.

Voici quelques pratiques qui sous-tendent nos principes, mais d'autres viendront à mesure que nous avancerons dans le processus de description.

  • Base de données NoSQL
  • API standard REST/HTTP API ou supérieure GraphQL
  • Pas de bases de données d'intégration
  • Petits services indépendants
  • 80% de couverture de code
  • Utiliser un docker en forme de conteneur pour le déploiement