ARCHITECTURE

Cédric BRASSEUR

Mis à jour le 19/03/2025

Cédric BRASSEUR

  • Ancien étudiant de l'Exia.cesi
  • 4 ans consultant chez Amaris, placé chez Euro Information Dev
  • Auto-entrepreneur depuis début 2020 (Création de sites web, applications mobiles & formateur)

Et vous ?

  • Nom, prénom
  • Etudes réalisées 
  • Connaissances sur les microservices
  • Autres infos appréciées

Plan du cours

  • Partie théorique
    • La notion de microservices, qu'est-ce que c'est ? 
    • Comparaison avec un architecture monolithique
    • Quand utiliser les microservices ?
    • Est-il possible de passer d'une architecture monolithique vers une architecture microservices ? 
    • Le load balancer et le message broker
    • Comment séparer ses services ?

 

  • Partie pratique
    • Rappels sur la création d'une API
    • Mise en place de swagger
    • Créer un second microservice
    • Introduction à la conteneurisation de nos services
    • Ajout de RabbitMQ et MassTransit
    • Création d'un service Common
    • Utilisation des services depuis un frontend

Microservices

Objectifs de la formation

  • Comprendre les différences entre microservices et monolithe

  • Savoir quand choisir l'architecture microservices 

  • Réaliser des microservices simples et les faire interagir avec RabbitMQ

  • Mise en place pratique d'un exemple simple sous forme de tutoriel à suivre pas à pas

Qu'est-ce que l'architecture microservices ?

Le concept de microservices

Le terme "Microservices" fait référence à une architecture logicielle qui est souvent mise en opposition au monolithique.

Les principales informations à comprendre : 

  • On décompose notre projet en plusieurs services
  • On rend les services indépendants (la plupart du temps)
  • Chaque service est réalisé sous forme d'API

Monolithique

  • Application en un bloc
  • Déploiement en un bloc
  • Scalabilité limitée car appliquée à toute l'application
  • Une seule stack (techno)
  • Difficile à maintenir si le projet grandit 
  • Plus rapide au démarrage
  • Un bug impacte le projet entier
  • Redéployer = tout redéployer

Microservices

  • Application divisée
  • Les services sont déployés indépendamment 
  • Scalabilité par service
  • Une stack par service (plus simple en cas de profils différents dans l'équipe)
  • Simple par service, gestion globale un peu plus complexe
  • Plus flexible sur le long terme
  • Plus complexe au démarrage
  • Un bug sur un service n'impacte pas tout le projet
  • Redéployer = déploiement par service

Comparaison avec monolithique

💪

  • Scalabilité, possible de scale un seul service si nécessaire
     
  • Flexibilité
     
  • Simplicité des services
     
  • Déploiement indépendants
     
  • Résilience (une panne n'impacte pas le projet entier)
     
  • Adapté au cloud computing

👎

  • Complexité au démarrage accrue
     
  • Monitoring plus complexe
     
  • Gestion des données et dashboarding plus complexe, les données étant souvent sur plusieurs bases

Avantages / inconvénients

Application à grande échelle

Les raisons principales du choix de l'architecture microservices sont les suivantes :

Equipe de développement hétérogène

Déploiement fréquents

Scalabilité et résilience

Projet évolutif à maintenir sur le long terme

Quand choisir les microservices ?

Peut-on passer de monolithique à microservices ?

Mais pourquoi ?

Plus d'informations...

Nous allons aborder quelques concepts plus techniques liés aux microservices et nous allons les détailler plus tard, au fur et à mesure dans la suite de la formation.

  • Une base par microservice (en général)
  • Les services sont indépendants (en général)
  • A vous de définir la portée de chacun de vos services, il n'y a pas de règle prédéfinie
  • On essaye quand même de créer des services avec des choses qui ont du sens ensemble
  • Idéalement, chacun de vos service doit être conteneurisé
  • Deux jours ne seront sûrement pas suffisant pour voir tout ce qu'il faut connaître sur l'architecture microservices...

Quelques définitions...

Voici quelques définitions techniques que nous allons éclaircir plus tard. Ces notions sont primordiales pour la mise en place d'une architecture microservices

  • Service : Un service est une API indépendante qui gère une partie de votre projet (exemple, les commandes, ou les produits)
  • Load balancer (ou gateway) : Point central appelé par vos clients, qui dirige les requêtes aux services nécessaires (Ocelot)
  • Message broker : Elément de synchronisation des données entre vos services via des messages (RabbitMQ)
  • Bus : Permet de définir qui envoie les messages et qui les consomme. Un peu comme un système de boite mail. (MassTransit)

Schéma général

Petit schéma pour avoir un visuel de tout ça ensemble...

Comme il y a de nombreuses étapes de mise en place pour réaliser une architecture microservices, nous allons procéder par étape et via des workshop très guidé que je vous ai mis en place :

  • Etape 1 : Mise en place d'une API (Service)
  • Etape 2 : Ajout d'un repository (couche base de données avec MongoDB
  • Etape 2.5 (optionnelle mais... simplifie le travail) : Mise en place d'un package avec le code commun
  • Etape 3 : Mise en place d'une seconde API (Service)
  • Etape 3.5 : Mise en place d'une seconde API en utilisant le code commun de l'étape 2.5
  • Etape 4 : Mise en place de RabbitMQ et MassTransit pour gérer les interactions des services en les laissant indépendants
  • Etape 5 : Mise en place d'un front simple pour exploiter nos services

Comment allons-nous procéder ?

Partie 1 : Créer une API en .Net (version Controller)

Une API, c'est quoi ?

L'API (Application Programming Interface) est un élément de votre projet extrêmement utilisé dans de nombreux contextes.

 

Elle permet (en général) de faire le lien entre deux éléments, par exemple :

  • Le lien entre votre front et votre back, le front appelle le back en passant par l'API
  • Le lien vers d'autres API, par exemple, l'API du gouvernement pour avoir des adresses ou recevoir la météo

 

Un exemple simple d'API, qui retourne juste une blague Chuck Norris :
https://api.chucknorris.io/jokes/random

Une API, c'est quoi ?

Vous l'avez remarqué si vous avez cliqué sur le lien de la slide précédente, le format de retour d'une API est très généralement du JSON.

{
  "categories": [],
  "created_at": "2020-01-05 13:42:24.696555",
  "icon_url": "https://api.chucknorris.io/img/avatar/chuck-norris.png",
  "id": "kR5RQ_S7QwWbcmF18s9upA",
  "updated_at": "2020-01-05 13:42:24.696555",
  "url": "https://api.chucknorris.io/jokes/kR5RQ_S7QwWbcmF18s9upA",
  "value": "Chuck Norris invented airplanes because he was tired of being 
	the only person that could fly."
}

En plus de ce json, l'appel à une API (donc à une URL, en http / https) retourne un code retour pour connaître le type de reponse de l'API. On le verra un poil plus tard ça.

HEAD

PATCH

DELETE

POST

OPTIONS

Modification d'un contenu (complet)

Comme GET mais pour le header (méta)

Mise à jour de contenu (partiel)

Ajout de contenu

Suppression de contenu

Retourne les ressources disponibles

Les requêtes - REST

Il existe plusieurs types de requêtes pour une API, chacune ayant un objectif précis. Dont 5 sont les plus fréquentes (en gras : GET, PUT, UPDATE, POST, DELETE)

PUT

GET

Récupération d'un contenu

Lors de la requête, on va donc avoir également un type de requête associé à la demande

Les requêtes - REST

Les statut code de retour (Code status), les plus fréquents, car il en existe beaucoup d'autres....

Code Nom Description Cas d'utilisation courants
200 OK Requête réussie Récupération d'une ressource (GET)
201 Created Ressource créée avec succès Création d'une ressource (POST)
204 No Content Requête réussie, mais aucune réponse Suppression d'une ressource (DELETE)
400 Bad Request Requête mal formulée ou invalide Données manquantes ou incorrectes dans une requête
401 Unauthorized Authentification requise Jeton d'authentification manquant ou invalide
404 Not Found Ressource non trouvée Identifiant de ressource inexistant
500 Internal Server Error Erreur interne du serveur Exception ou bug inattendu côté serveur

Merci ChatGPT pour ce joli tableau !

Les requêtes - REST

Schéma (simplifié) du fonctionnement d'une API :

Les DTOs

Un DTO (Data Transfer Object) est un objet de transfert de données, son objectif est de définir la structure des éléments entrants et sortants d'une API

Les records

On peut utiliser une classe classique pour nos DTOs, mais en .Net, les records offrent certains avantages et une simplicité d'écriture.

Les avantages

  • Syntaxe plus courte et simple
  • Immutable (utile pour les DTOs)
  • Egalité réalisée sur la structure et non par référence
  • Copie facile avec with
  • Sérialisation en JSON simplifiée (et même automatisée en .Net)
public record ItemDto(Guid Id, string Name, string Description, decimal Price);
public record CreateItemDto([Required] string Name, [Required] string Description, [Range(0,100)] decimal Price);
public record UpdateItemDto([Required] string Name, [Required] string Description, [Range(0, 100)] decimal Price);

Exemple de record

Les controllers

Un contrôleur est une classe qui va définir les différentes routes de notre API, c'est à dire les requêtes qui peuvent être réalisés par un client.

	[ApiController]
    [Route("items")]
    public class ItemsController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<ItemDto> Get()
        {
            return items;
        }

        [HttpGet("{id}")]
        public ActionResult<ItemDto> GetById(Guid id)
        {
            var item = items.Where(item => item.Id == id).FirstOrDefault();

            if (item == null)
            {
                return NotFound();
            }

            return item;
        }

        [HttpPost]
        public ActionResult<ItemDto> Create(CreateItemDto createItemDto)
        {
            var item = new ItemDto(Guid.NewGuid(), createItemDto.Name, createItemDto.Description, createItemDto.Price);

            items.Add(item);

            return CreatedAtAction(nameof(GetById), new { id = item.Id }, item);
        }
        
        //...
	}

Exemple de controller

Les extensions

On remarquera rapidement qu'il sera nécessaire de convertir un élément (Entity, donc côté base de données) en DTO, pour simplifier celà, on utilise les extensions en .Net.

Ici, ça nous permettra de transformer une entité en DTO

	public static class ItemsExtension
    {
        public static ItemDto AsDto(this Item item)
        {
            return new ItemDto(item.Id, item.Name, item.Description, item.Price);
        }
    }
    
    // La méthode AsDto est maintenant appelable sur n'importe quel objet de type Item

Exemple d'extension

La "documentation" de votre API - Swagger

Explications sur Swagger, son utilité et son utilisation (live)

Exploiter son API - Postman

Explications sur Postman, son utilité et son utilisation (live)

Les interfaces - REST

Utilisation de Postman

Postman est un outil de requêtage REST très pratique. 

Conseillé sous Windows

& Mac

Il permet de faire tout type de requêtes, je vous conseille de paramétrer pour chaque requête l'authentification basique avec votre compte CouchDB.

Création d'une API

Je vais vous faire suivre un workshop très guidé afin de mettre en place une première API en .Net en utilisant les notions que l'on a vu au préalable.

Exercice - Step 1

Step 1

Envoyer Workshop Step 1

Partie 2 : Ajouter le Repository Pattern

Un repository, c'est quoi ?

Le repository pattern est une façon bien complexe de définir un principe très simple : On va simplement mettre nos classes et éléments d'accès aux données dans un dossier et le séparer des autres éléments. Autrement dit, on va éviter de mélanger nos éléments d'accès aux données à nos controller.

 

L'avantage est que ça simplifie grandement le changement de base de données si un jour on souhaite en changer.

 

En général, on couple cette notion à l'injection de dépendances, que l'on verra un peu après dans cette partie.

Un repository, c'est quoi ?

Schéma dans l'API

Utilisation de MongoDB

MongoDB est une base de données NoSQL orientée Documents.

Chaque document est en json.

 

On utilise souvent MongoDB lorsque l'on réalise des microservices car c'est scalable et fait pour simplifier la scalabilité (horizontale)

Installation de MongoDB

Nous allons démarrer un conteneur MongoDB avec Docker

 

Les commandes à réaliser sont :

- Récupérer l'image mongo

         docker pull mongo

- Start mongo container (seule commande obligatoire pour notre cas) :

         docker run -d --name mongodb -p 27017:27017 -v localmongovolume:/data/db mongo

- Arriver dans le terminal de commande du conteneur :

         docker exec -it mongodb bash

- Démarrer mongo en invite de commande (dans docker) :

         mongosh   

 

**Vous êtes connecté sur mongo sur docker !**

Via Docker

Petite démo MongoDB

Juste pour vous montrer un peu comment ça marche avant l'exercice, je vais vous montrer comment on peut utiliser MongoDB à travers les différentes méthodes proposées.

 

De même, nous allons installer une extension dans VSCode pour pouvoir simplement parcourir nos base de données MongoDB

La chaîne de connexion est :

Documentation !!!

Documentation des commandes

Documentation !!!

Documentation !!!

mongodb://{HOST}:{PORT}
mongodb://localhost:27017 (de manière générale en local)

MongoDB en .Net

Pour utiliser MongoDB avec .Net, il nous faut ajouter le package Nuget MongoDB.Driver

Ensuite, nous pouvons facilement exploiter les classes MongoDB pour les classes MongoDB pour réaliser notre CRUD avec notre base de données en MongoDB (orienté document)

Je vais vous montrer un exemple de code et vous aurez le workshop guidé en fin de tutoriel pour pratiquer et comprendre comment l'utiliser

L'injection de dépendance

Un principe de la POO est à connaître pour réaliser proprement nos liens entre nos controllers et nos repositories

 

L'injection de dépendances

 

 

L'injection de dépendance

Vous l'avez sûrement compris dans la slide précédente, mais l'injection de dépendance permet d'éviter de se lier à une implémentation concrète d'une classe en plus de permettre de délier les éléments et éviter les dépendances directes. Ceci rendant le code plus modulaire et évolutif.

 

En .Net, on peut même paramétrer directement l'injection de dépendance dans nos Settings de départ (fichier Program.cs) afin de pouvoir définir comment l'injection de dépendance doit être gérée.

Nous allons voir un exemple ensemble et vous allez également pouvoir pratiquer avec le workshop guidé

Ajouter le repository pattern et l'injection de dépendances

Je vais vous faire suivre un workshop très guidé afin de mettre en place le repository pattern avec MongoDB et appliquer l'injection de dépendances

Exercice - Step 2

Step 2

Envoyer Workshop Step 2

Partie 3 : Factoriser le code en code réutilisable et créer un second service

Rendre notre code générique

Le but de cette étape est de rendre notre code plus générique afin d'éviter de dupliquer du code qui peut être factorisé.

 

Le principe ici va être de retravailler sur :

  • Notre entité et la rendre générique
  • Notre repository et le rendre générique
  • Utiliser des extensions pour rendre notre injection de dépendance dans le Program.cs plus générique

 

Ensuite, on va créer une librairie de classe pour pouvoir utiliser cette librairie directement dans nos services

Rendre notre code générique

Voici un petit schéma pour comprendre pourquoi on ne fait pas un service générique, mais un package que l'on va importer avec  Nuget.

Rendre notre entité générique

Ici, c'est simple, on va simplement extraire une interface de notre entité, l'appeler IEntity et forcer l'implémentation d'un Guid Id. C'est tout ce dont on a obligatoirement besoin.

public interface IEntity
{
    Guid Id { get; set; }
}

// Notre entité concrète ne change pas, elle implémente juste cette interface
public class Item : IEntity
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
}

Rendre notre repository générique

Ici, on va utiliser la généricité pour notre Repository, l'objectif est de lui permettre de gérer toute Entity héritant de IEntity.

On commence par créer une interface.

public interface IRepository<T> where T : IEntity
{
    Task CreateAsync(T entity);
    Task DeleteOneById(Guid id);
    Task<IReadOnlyCollection<T>> GetAllAsync();
    Task<T> GetByIdAsync(Guid id);
    Task UpdateAsync(T entity);
}

Ensuite, on va appliquer la généricité à notre Repository actuel (slide suivante)

Rendre notre repository générique

Le but étant de rendre les méthodes classiques d'accès aux données génériques en fonction du type générique.

public class MongoRepository<T> : IRepository<T> where T : IEntity
{
    private readonly IMongoCollection<T> _dbCollection;
    private readonly FilterDefinitionBuilder<T> _filterBuilder = Builders<T>.Filter;

    public MongoRepository(IMongoDatabase mongoDatabase, string collectionName)
    {
        _dbCollection = mongoDatabase.GetCollection<T>(collectionName);
    }

    public async Task<IReadOnlyCollection<T>> GetAllAsync()
    {
        return await _dbCollection.Find(_filterBuilder.Empty).ToListAsync();
    }

    public async Task<T> GetByIdAsync(Guid id)
    {
        FilterDefinition<T> filter = _filterBuilder.Eq(entity => entity.Id, id);
        return await _dbCollection.Find(filter).FirstOrDefaultAsync();
    }

    public async Task CreateAsync(T entity)
    {
        ArgumentNullException.ThrowIfNull(entity);

        await _dbCollection.InsertOneAsync(entity);
    }

    public async Task UpdateAsync(T entity)
    {
        ArgumentNullException.ThrowIfNull(entity);

        FilterDefinition<T> filter = _filterBuilder.Eq(existingEntity => existingEntity.Id, entity.Id);

        await _dbCollection.ReplaceOneAsync(filter, entity);
    }

    public async Task DeleteOneById(Guid id)
    {
        FilterDefinition<T> filter = _filterBuilder.Eq(entity => entity.Id, id);

        await _dbCollection.DeleteOneAsync(filter);
    }
}

Attention, maintenant on va passer le collectionName via le constructeur et mettre en place l'injection de dépendances pour la base de données

Utiliser le générique dans notre controller

Il ne reste plus qu'à modifier notre utilisation du repository dans notre controller

private readonly IRepository<Item> _itemsRepository;

public ItemsController(IRepository<Item> itemsRepository)
{
    _itemsRepository = itemsRepository;
}

Rendre notre configuration générique

On va appliquer le même principe pour ce qui est de notre configuration via notre Program.cs en utilisant les extensions

public static class ServiceExtension
{
    public static IServiceCollection AddMongo(this IServiceCollection services)
    {
        BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
        BsonSerializer.RegisterSerializer(new DecimalSerializer(BsonType.String));

        services.AddSingleton(serviceProvider =>
        {
            var configuration = serviceProvider.GetService<IConfiguration>();
            var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
            var mongoDbSettings = configuration.GetSection(nameof(MongoDBSettings)).Get<MongoDBSettings>();
            var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
            return mongoClient.GetDatabase(serviceSettings.Name);
        });

        return services;
    }

    public static IServiceCollection AddMongoRespository<T>(this IServiceCollection services, string collectionName) 
        where T : IEntity
    {

        services.AddSingleton<IRepository<T>>(serviceProvider =>
        {
            var database = serviceProvider.GetService<IMongoDatabase>();
            return new MongoRepository<T>(database, collectionName);
        });

        return services;
    }
}

Rendre notre configuration générique

Utiliser l'extension dans notre Program.cs

using Play.Catalog.Service.Entities;
using Play.Catalog.Service.Extensions;
using Play.Catalog.Service.Settings;

var builder = WebApplication.CreateBuilder(args);
var serviceSettings = builder.Configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();

// On utilise les extensions que l'on a créer pour simplifier notre appel
builder.Services
    .AddMongo()
    .AddMongoRespository<Item>("items");
// Fin de la modification, rien d'autre n'a changé !

builder.Services.AddControllers(options =>
{
    options.SuppressAsyncSuffixInActionNames = false;
});

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.MapControllers();

app.Run();

Création d'un package Common

Pour utiliser cette partie générique dans nos services, on va créer une librairie de classe afin de pouvoir la versionner et l'utiliser dans nos services.

dotnet new classlib -n Play.Common

On déplace les éléments génériques (IEntity, IRepository, ServiceExtensions, MongoDBSettings).


Puis on créer un package (classlib) que l'on pourra importer avec Nuget dans nos services

dotnet pack -o ../../../packages/

Il ne reste plus qu'à importer le package Nuget, supprimer les doublons restant dans notre service et utiliser les éléments du package Common !

Utilisation de docker-compose

Comme on l'a dit, souvent, nos services vont avoir chacun leur propre base de données, on va donc faire en sorte d'utiliser docker-compose afin de pouvoir démarrer nos différentes bases.

services:
  mongoDbServiceCatalog:
    image: mongo
    container_name: mongoDbServiceCatalog
    ports:
      - "27017:27017"
    volumes:
      - mongoDbDataCatalog:/data/db
    
  mongoDbServiceInventory:
    image: mongo
    container_name: mongoDbServiceInventory
    ports:
      - "27018:27017"
    volumes:
      - mongoDbDataInventory:/data/db

volumes:
  mongoDbDataCatalog:
  mongoDbDataInventory:

Créer notre second service

Avec le package Common que l'on a mis en place, créer un second service est maintenant un jeu d'enfant !


Vous allez pouvoir pratiquer avec la partie suivante, j'ai essayé de la rendre guidée tout de même.

Utiliser la généricité pour éviter de se répéter

Je vais vous faire suivre un workshop très guidé afin de mettre en place la généricité avant de créer votre second service

Exercice - Step 2.5

Step 2.5

Envoyer Workshop Step 2.5

Créer notre second service

Je vais vous faire suivre un workshop très guidé afin de créer un second service avec le package Common que l'on a créé

Exercice - Step 3

Step 3

Envoyer Workshop Step 3

Partie 4 : Mise en place et compréhension de patterns associés au Microservices

Faire communiquer nos services

Il existe deux moyens principaux pour faire communiquer nos services, chacun avec leurs avantages et inconvénients, mais on va en appliquer qu'un seul car c'est le plus fréquent.

Synchrone

  • ✅ Simple
  • ✅ Réponse immédiate
  • ✅ Monitoring simplifié
  • ❌ Couplage des services
  • ❌ Scalabilité plus difficile
  • ❌ Déploiement plus difficile
  • ❌ Latence accrue
  • ❌ SLA difficile à respecter
  • ❌ Patterns à appliquer
  • ❌ Gestion d'erreurs complexe

Asynchrone

  • ✅ Découplage fort
  • ✅ Scalabilité simple / efficace
  • ✅ Meilleures performances
  • ✅ Résilience accrue
  • ✅ Gestion simple de la charge
  • ✅ Peu de patterns
  • ✅ Légère latence possible
  • ❌ Notions DevOps nécessaires

Schéma synchrone

Petit schéma synchrone...

Les services communiquent entre eux et ça nécessite de mettre en place différentes stratégies en cas d'échecs & ça augmente la latence de réponse des services

Patterns asynchrone à implémenter...

Différents patterns / techniques sont à connaître et implémenter dans le cas de communication synchrone entre les services

  • Timeouts intentionnels : On doit définir une durée maximale d'attente avant d'avoir une réponse, sinon le client peut attendre indéfiniment en plus de surcharger le service.
  • Exponential backoff technique : On définie une valeur exponentielle d'attente entre les retries (Ex : 2, 4, 8, 16s, ...)
  • Circuit breaker pattern : Avec les différentes tentatives successives et le nombre d'appels, le service pourrait très rapidement être surchargé, on applique donc une réponse négative directe si le service est en surcharge afin d'éviter de le surcharger d'avantage

En résumé... Communication synchrone

On ne va pas faire ça !

Ce n'est pas forcément une mauvaise idée, mais ça n'est pas la façon la plus courante de faire fonctionner nos services ensemble...

Schéma asynchrone

On repart sur le schéma de départ pour la communication asynchrone

Les services communiquent entre eux via le message broker qui est là pour faire tampon et s'assurer que les services consomment les messages dès que possible

Communication entre nos services (asynchrone)

Je vais vous faire suivre un workshop très guidé afin d'appliquer la communication asynchrone entre nos services. Il y a beaucoup de choses à comprendre et apprendre dans cette partie très technique, mais nous en aurons vu une majeure partie ensemble à l'oral en présentation.

Exercice - Step 4

Step 4

Envoyer Workshop Step 4

Partie 5 : Le frontend et nos microservices

Les CORS

Vous devez déjà connaître, mais les CORS sont un souci récurrent pour les développeurs, quelques notions :

  • CORS: Cross Origin Request Sharing, on peut définir des éléments qui sont passés par la requête HTTP (souvent fait directement par le navigateur ou le client http)
  • SOP: Same Origin Policy, principe visant à n'accepter que les requêtes de la même origine, c'est à dire {protocol}://{host}:{port} (ce couple des trois éléments). Ce principe est appliqué par le navigateur.
  • Front et CORS : On peut facilement bypasser les CORS, donc c'est pas une protection suffisante.

Les CORS schéma

Petit schéma...

Les CORS schéma (paramétré dans l'API)

Petit schéma...

La gateway, ses intérêts

Pour l'instant on a mis de côté la gateway, mais elle apporte de nombreux avantages non négligeables :

  • CORS: Le front passe uniquement par la gateway et c'est la gateway qui connait les url des services
  • Sécurité : L'aspect précédent apporte une sécurité pour le projet, car les clients ne peuvent pas communiquer directement avec les services + Protection contre différentes attaques...
  • Anti DDOS : La gateway est le seul endroit à configurer pour éviter le DDOS
  • Gestion des rôles et permissions : La gateway peut faire office de proxy de connexion également

Schéma sans gateway

Petit schéma sans gateway et je vous explique les inconvénients, surtout au niveau des CORS

Schéma avec gateway

Petit schéma sans gateway et je vous explique les avantages

Créer notre second service

Ajoutons un front que je vous envoie et paramétrons les CORS (pour l'instant sans gateway)

Exercice - Step 5

Step 5

Envoyer Workshop Step 5

Partie 6 : Ajouter un nouveau service sans être guidé

A vous de jouer !

Créez un service complet de recommandation d'items à un utilisateur.

Un peu comme ce qui est fait par notre service inventaire, je vous demande de créer un service de recommandation.

Les recommandations sont faites pour un utilisateur (guid généré par postman). Une recommandation a un id, l'id des items recommandés + le nom et le prix de l'item provenant du service Catalog

Créer un troisième service avec communication asynchrone

Architecture Microservices

By Cėdric Brasseur

Architecture Microservices

Formation architecture microservices - introduction

  • 101