Loading

ESIR 2020 MicroServices

Benoît Chanclou

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

Micro

services

Qui suis-je ?

Benoît Chanclou

Le complément

de NodeJS

Base de données

NoSQL

Unitaires,

d'intégration,

de charge

Micro-

Service

Pourquoi les
micro-services ?

Cheminement

  • Historique
  • Parallélisation de services
  • Du macro au micro

Historique

Loi de Moore

On arrive aux limites

La puissance de calcul

depuis 10 ans

  • les fréquences stagnent
  • la puissance d'un cœur n'augmente presque plus

La puissance augmente

car

le nombre de cœurs augmente

=>

Nécessité de paralléliser

Néanmois

Parallélisation

  • tous les algorithmes ne sont pas parallélisables
    Sinon on utiliserait que des processeurs de cartes graphiques
  • algorithmes adapté au calcul intensif
    cas particuliers du calcul numérique
  • complexe à mettre en œuvre
    Multi-thread, dead lock, accès concurrents, mutex, ...

Gérer de nombreuses requêtes

Requêtes simples, multiples & indépendantes

  • Simple :
    Pas de processus complexe
  • Multiples & indépendantes :
    Processus parallèlisables

A quel niveau gérer 

Processus multi threads

  • c'est complexe à programmer
  • coûteux en ressources (switch de contexte)

=> réponse la programmation réactive (aka asynchrone)

Plusieurs processus

  • les OS sont faits pour cela

Montée en charge

Plus de requêtes 

=>

Plus de processus

Quels outils

  • Des OS qui gérent
    • les processeurs multi-cœurs 
    • le multi-processus
  • Des frameworks réactifs (asynchrones et monothreads)
  • Des bases de données
    • multi-instances
    • ultra performantes

Gérer

la complexité

Qu'est ce qu'un monolithe ?

(aka le macro-service)

Un service

  • gros
  • complexe
  • plein de fonctions
  • d'un seul bloc

Le monolithe

Au début

  • Petit et rapide
  • Facile à mettre en oeuvre
  • Tout est au même endroit

Le monolithe

Avec le temps

  • Gros et lent
  • Difficulté à maîtriser la complexité
  • Accumulation de dette technique
  • Maintenance de plus en plus coûteuse

Le coût d'un monolithe

  • Coût exponentiel
  • Régulièrement "on efface tout et on recommence"

coût / fonction

temps

Le coût d'un monolithe

  • Moyens exponentiels Moyens constants
  • Recommencer => tunnel
  • Concurrence des petits

coût cumulé

temps

richesse fonctionnelle

tunnel

développement d'une nouvelle version

release de la version

coût cumulé

  • Moyens exponentiels

Le phénix

  • Régulièrement "on efface tout et on recommence"

causes

  • coût exponentiel
  • technologies obsolète
  • problème de recrutement
  • nouvelle technologie
  • concurrence

 

Microservice

Le microservice

  • Un monolithe qui ne grandit pas
  • Dette technique raisonnable
  • Un coût de maintenance raisonnable
  • Le coût cumulé tend à stagner

coût cumulés

temps

Architecture microservice

  • Des boîtes noires qui échangent des messages
  • Chaque service ne connait son voisin que via son interface API

coûts cumulés

temps

Ce qu'il ne faut pas faire

Les dangers

Formaliser les règles de conception

Danger #1 : Complexité

Composants micro-service

  • simplicité de chaque composant
  • complexité entre composants

=> formaliser les règles de communication

du code spaghetti au plat de spaghetti

Danger #1 : Complexité

Définir des normes pour les protocoles

  • formats des données
  • format des échanges
    synchrone, asynchrone (callback), offline

Danger #2 : Pannes

Augmentation du nombre de composants

  • Augmentation du nombre de pannes possibles
    • composant qui ne répond pas
    • panne réseau
    • ...

Danger #2 : Pannes

Définir des normes pour le fonctionnement

  • service minimum
  • résilience aux pannes
  • redéploiement automatique

Rappel : Performance

Ordre de grandeur du temps d'accès 

  • Registres / instruction : ~1ns
  • Mémoire : ~10ns
  • Accès SSD : ~10µs
  • Base de données : ~1ms
  • Appel API: ~100ms

Un appel d'API c'est extrêmement lent

Danger #3 : Performances

Augmenter le nombre d'appels API

  • Augmenter le temps de latence
  • Augmenter le temps de réponse

Danger #3 : Performances

Définir des normes d'utilisation

  • éviter les appels en cascade
  • éviter les appels inutiles

Danger #4 : Déploiement/ops

Augmentation du nombre de composants

  • Augmentation du nombre de déploiements
  • Augmentation des logs

Danger #4 : Déploiement/ops

Définir des solutions

  • Industrialisation du déploiement
    • déploiement automatique à partir de git
    • auto scaling
  • Surveillance des logs
    • ​alertes automatiques
    • monitoring

Les contraintes et avantages

Pour que les dangers

deviennent des

risques acceptables

Les points clés d'un microservice

  • Élastique
  • Résilient
  • Composable
  • Minimal
  • Complet

Les points clés

Élastique

  • ​il peut y avoir une ou plusieurs instances
  • permet la montée en charge

Les points clés

Résilient

  • ​ne doit pas planter si un autre est indisponible
  • lors d'une interruption dû à une mise à jour
  • lorsque la base est momentanément indisponible

Les points clés

Composable

  • seule l'API définit le service
  • pas de couplage
  • éviter les services de conversion de format

Les points clés

Minimal

  • ​responsabilité unique
  • pas de fonctionnalités inutiles

Les points clés

Complet

  • toutes les fonctionnalités nécessaires
  • il doit être autonome
  • possède sa propre base de données

Quelques analogies avec la POO

SOLID

  • Simple responsibility principle
  • Open/close principle
  • Liskov substitution principle
  • Interface segregation principle
  • Dependency inversion principle

Corollaires

Stateless

L'élasticité implique que toute requête soit

  • stateless
  • self content

Autorisation

le système est ouvert

  • tout est accessible
    => utilisation d'un contrôle d'accès
    => être authentifier

Autorisation

le système doit être performant

ne pas dépendre d'un service d'authentification


=> via token self content

 

Utilisation de JWT

Droits d'accès

  • le service définit et gère
    • ses propres rôles
    • ses propres droits

Configuration

  • le service définit et gère sa propre configuration

Découverte du service

  • ce n'est pas WSDL SOAP
  • néanmoins des standards apparaissent
    • OpenAPI (swagger) permet de spécifier l'API
    • JWT permet de gérer l'authentification
    • Docker permet de déployer
    • ...

Format d'échange

  • utilisation de normes pour le format des données
    • existantes
    • ou à créer
  • protocole RESTful pour le CRUD des ressources
    • HATEOAS

Webhooks

  • ils sont pour les services
    ce que sont les messages pour les objets
  • évitent le couplage

Vie des services

  • les services peuvent évoluer
  • se scinder si deux rôles
  • ou fusionner si couplage

Principaux types

Typologie des services

Différentes types de services ayant chacun leur rôle

  • référentiels
  • fonctionnels
  • intermédiateurs
  • orchestrateurs/chorégraphes

Référentiel

Rôle

  • Fournir une API CRUD sur des entités
  • Gérer les droits d'accès aux entités
  • Stocker les entités
  • Dédoublonner les entités
  • Gérer l'historique des entités
  • Valider les données des entités

Remarque

Valider une donnée ≠ les champs sont définis

 

  • ce n'est pas imposer des champs non nul
  • c'est vérifier leur format, valider leur valeur

 

Rendre obligatoire un champs est

du domaine métier

pas du domaine du référentiel

Exemples

Applifarm

  • Tiers, Animaux, Contrats, Formulaires,...

Tactilia

  • Tiers, Animations, Formulaires, Tablettes,...

 

Le référentiel Tiers est un must-have

cf. RGPD

Fonction

Rôle

  • Réaliser une ou des fonctions
  • Gère les droits d'accès aux fonctions

Exemples

  • Envoyer un SMS
    appeler l'API du brocker de SMS
  • Fusionner des données
    données + modèle => pdf
  • Effectuer un virement
    appeler l'API de la banque
  • ...

Intermédiateur

Rôle

  • S'insérer entre deux services aux formats incompatibles
  • Convertir des données d'un format vers un autres

Exemples

  • conversion d'un format de tiers
    • au format adullact
    • au format VCard
  • ...

Orchestrateur

Rôles

  • Composer une fonction complexe en appelant les autres services
  • Réaliser le séquencement entre les services

Exemples

  • Des fonctions métier complexes
    Remontée et traitement de données
  • ...

Remarques sur
les types
et la conception

Typologie des services

Différentes types de services

  • référentiels
  • fonctions
  • intermédiateur
  • orchestre/chorégraphe
  • ...

 chacun a son rôle

  • si plusieurs rôles dans un même service 

Choses communes

La plupart des services ont en commun

  • l'exposition des informations et status
  • le contrôle d'accès
  • les webhooks
  • le multi-tenant & configurations
  • la gestion des ressources

Multi-tenant & Configuration

Multi-tenant

  • partager un même service entre
    • plusieurs locataires
    • plusieurs utilisations
  • tenant client

Configuration

Plusieurs parties :

  • paramètres globaux du service 
  • paramètres associés à chaque tenant

Mise à jour de

configuration

  • A froid
    Par fichier de configuration
    nécessite un redémarrage
  • A chaud
    Par API
    peut se faire à chaud

Configuration par API

plusieurs sous-parties

  • paramètres globaux du service accessibles à l'administrateur
  • associés à chaque tenant
    • paramètres accessibles à l'administrateur (privés)
    • paramètres accessibles au manager (publics)

Informations

& Status

Informations

  • liens de découverte
  • liste des rôles
  • version
  • Swagger/OpenAPI
  • license

Status

  • état du service
  • états des dépendances

Contrôle d'accès

Distinguer les rôles

Rôles Groupes

Groupe

Le groupe dont on fait parti, c'est lié à :

  • l'organigramme
  • la hiérarchie
  • les unités
  • ...

exemples :

  • marketing, stagiaires, permanents, développeur, rh,...

Un utilisateur peut faire parti de plusieurs groupes

Rôle

Le rôle que l'on a vis-à-vis du service, dépend de ce qu'on a le droit de faire :

  • administrateur : gère l'ensemble du service
  • manager : gère un tenant du service
  • utilisateur : utilise le service

Les rôles peuvent être déclinés en sous-rôles pour plus de finesse

  • rédacteur, contrôleur,...

Exemple

On a un utilisateur chez un intégrateur de services

  • il a accès à trois plateformes/tenants
    • test/* : celle de test pour vendre
    • prod/client : celle de son client qu'il est en train d'intégrer
    • prod/lui-même : celle qu'il utilise pour gérer ses projets
  • ses accès sont respectivement :
    • administrateur : il doit pouvoir faire ce qu'il veut
    • manager : il doit pouvoir modifier le tenant de son client
    • utilisateur : il est simple utilisateur de son propre tenant

​Pourtant c'est le même utilisateur faisant parti des mêmes groupes

Group/Role mapping

  • Pour connaître les droits d'un utilisateur il faut déterminer ces rôles à partir de ses groupes
  • C'est le rôle du dictionnaire groupe/rôle qui à chaque groupe associée des rôles
  • Ce dictionnaire peut être spécifique à chaque tenant

tenant

group/role

groups

roles

requête

utilisateur

Le problème de l'initalisation

  • global/pas de tenant => il faut qu'un administrateur initialise le groupRoleMapping général pour l'administrateur => 💀
    => il faut un compte initial dans la config
    supprimé par la suite
     
  • un tenant est créé => le groupRoleMapping de ce tenant est vide => le manager n'a pas accès et ne peut pas mettre le mapping à jour => 💀
    => l'administrateur doit ajouter un groupe pour le manager, ensuite le manager peut gérer le mapping de son tenant

 

Attention aux droits

💀

le manager ne doit pas pouvoir ajouter le rôle administrateur dans le mapping de son tenant

sinon il peut augmenter ses propres droits

Basic auth

username + password

  • ne contient pas d'authentification intrinsèque
    => il faut authentifier l'utilisateur avec son identifiant et son mot de passe
  • ne contient pas de payload
    => il faut recherche les groupes associés à l'utilisateur

=> gérer une liste interne contenant les utilisateurs autorisés et définir pour chaque utilisateur la liste des groupes dont il fait parti (ou faire appel à un service tiers)

 

Utile pour

  • les tests
  • l'initialisation (temporairement)

JWT

Token self content avec authentification & payload

  • on sait que l'utilisateur a été authentifié par l'émetteur du token
  •  self content peut donc contenir toute l'information nécessaire
    • groupes par tenant
    • id de l'utilisateur

Droits positif/négatif

  • droit positif 
    tout le monde a le droit sauf ...
  • droit négatif
    personne n'a le droit sauf ...

Toujours utiliser un droit de même type

Ne jamais mixer les deux types sur une même ressource

Webhooks

Webhooks

  • ce sont les messages du service 
  • permettent chaîner les services
  • pas de norme, mais des standards et des bonnes pratiques apparaissent

Exemple

A la création d'une tâche on veut

  • faire des statistiques sur la tâche 
  • envoyer un sms à la personne responsable

Exemple

référentiel tâches

POST tâche

POST sms

data wharehouse

POST tâche

Numéro de téléphone !?

envoi de sms

Exemple

référentiel tâches

POST tâche

formatage sms

POST tâche

data wharehouse

POST tâche

envoi de sms

POST sms

référentiel tiers

Webhook

définit par

  • un déclencheur
    • une opération
      • création, mise à jour, suppression
    • ​​​une cible
      • une ressource ou un ​type de ressources
  • une action : l'appel d'un service
    • ​opération : GET, POST,...
    • une url
    • un corps
      • ​brut, filtré, reformaté,...

Création d'un webhook

un webhook est défini

  • au niveau du service ou du tenant
  • statiquement ou dynamiquement
    • dans la configuration
    • par un appel à une API
  • avec ou sans durée de vie

Exemple de configuration

module tiers MGDIS

"webhooks": [
  {
    "topic": "POST+*/tiers",
    "callback": "/document-collect/stnazaire/root/tiers?cmisaction=createFolder&propertyId[0]=cmis:name&propertyValue[0]={reference}&propertyId[1]=cmis:objectTypeId&propertyValue[1]=cmis:folder&succinct=true",
    "method": "POST",
    "options": {
      "withoutBody": true
    }
  },
  {
    "topic": "POST+*/tiers",
    "callback": "/request/api/stnazaire/collections/tiers/{reference}",
    "method": "PUT",
    "headers": {
      "Authorization": "Basic YWRtaW46QzdOYVdWMzlwM1M4R0hFd2RTTjNIZ1lwVzFXMGVtS1E="
    }
  },
  {
    "topic": "POST+*/tiers",
    "callback": "https://wwx2.mairie-saintnazaire.fr/BlueAccess/application/referentiel_association_TEST/modules/webhook/index.php?reftiers={reference}",
    "method": "PUT"
  },
]

Conseils d'implémentation

  • Limiter les données
  • Gérer la quantité
  • Gérer les erreurs
  • Sécuriser les requêtes

Serveur

  • Répondre rapidement
  • Répondre correctement
  • Sécuriser les requêtes

Client

Limiter les données

  • Les données transmises ne doivent pas être trop volumineuses
  • Si trop grosse (une vidéo par exemple) fournir l'url d'accès à la ressource au lieu de la ressource elle même

Serveur

Gérer la quantité

  • Si beaucoup d'appels à chaque seconde
    • Limiter le nombre d'appels par seconde
    • Regrouper les événements par lots

Serveur

Gérer les erreurs

  • Mettre un timeout pour arrêter un appel durant trop  longtemps
  • Réessayer si pas de réponse ou une erreur
  • Mettre en place une stratégie de pause exponentielle entre les tentatives
  • Si pas de réponse, mettre en blacklist
  • Si un événement pas délivré le réorienter en lettre morte (dead letter queue)
  • Être capable de rejouer des événements

Serveur

Sécuriser les requêtes

  • Signer les requêtes avec un secret
  • Identifier les requêtes de manière unique
  • Permettre l'utilisation d'authentification
    (Authorization JWT)
  • Pouvoir faire les requêtes en https

Serveur

Sécuriser les requêtes

  • Vérifier la signature si les données sont signées
  • Faire une whitelist pour les adresses ip des appelants
  • Mettre une authentification robuste
    (Authorization JWT)
  • Pouvoir faire les requêtes en https

Client

Répondre rapidement

  • Si traitement long
    • Accuser réception avec un ack 
    • Différer le traitement en asynchrone (via une queue par exemple)

Client

Répondre correctement

  • Répondre avec 2xx
  • Si l'événement est reçu plusieurs fois le traitement doit être idempotent 

Client

Ressources/objets

Les schémas

Ils sont obligatoires pour :

  • la validation de l'API
    • définition (OpenAPI/swagger)
    • requête
    • réponse
  • la gestion du format de la persistance

Persistance

Information importante

  • L'objet manipulé par
    • l'ihm (reçu par le navigateur via l'API)
    • le serveur (pour préparer sa réponse)
    • la base de données (pour les stocker)

NE SONT PAS (forcément/souvent) LES MÊMES

Deux façons de faire

  • Snapshot

  • Incrémentale

Snapshot

On ne garde que le dernier état de la ressource

  • simple
  • la ressource est  accessible immédiatement
  • pas d'historique
  • permet la recherche par champs

Incrémentale

On stocke toutes les modifications réalisées sur la ressource

  • complet : qui, quoi, quand
  • besoin de reconstituer la ressource
  • permet de retracer l'historique
  • ne permet pas la recherche

On peut combiner

  • La sauvegarde incrémentale sert de référence
    garanti d'exaustivité
  • Les snapshot sert de cache
    garanti d'accès rapide

Référentiel

Un référentiel doit  gérer l'historique des ressources qu'il gère

=>

Utilisation de la sauvegarde incrémentale obligatoire

Fonctions & orchestre

Fonctions

  • Simples (pas d'état)
    • intermédiateurs
  • Complexes (avec état)
    • fonctionnalités métier
    • orchestration

Simples

Intermédiateurs

  • pas de stockage d'information
    • fonction pure
    • idempotence
  • donc service simplifié
    • facilement remplaçable
    • authentification simplifiée (voir inutile)
    • utilisation d'EIP => Apache Camel
    • container obligatoire

Complexes

Métier ou orchestrateur

  • éventuellement du stockage d'information
    • pas fonction pure
    • pas d'idempotence
  • donc service plus classique
    • authentification complète
      (mais rôles souvent moins nombreux)
    • pour les orchestrateur => EIP / BPM
      (Apache Camel / Bonita)
    • pour les autres => comme un service référentiel

Apache Camel

Basé sur les Entreprise Integration Pattern
(C'est à l'intégration ce que sont les Design Patterns à la POO)

Migration

Du monolithe

aux services

en trois étapes

  • factoriser/modulariser
  • créer des api
  • faire des services 

Découpage

première étape

  • factoriser/modulariser le code existant
  • limiter les dépendances

API

deuxième étape

  • créer des api
  • faire des tests unitaires dessus
  • utiliser les API

Tests

Migration

troisième étape

  • faire des services 
  • extraire le code 

Tests

D'une base à une autre

  • dissocier les bases de données en trois étapes
  • la troisième vous étonnera

Dissocier lecture et écriture

première étape

  • utiliser l'api pour l'écriture

Dissocier les données

deuxième étape

  • récrire le service
  • utiliser une autre base

Environnement

Déploiement

Containers rules the world

  • pour les containers
    • Docker s'impose 
  • pour la composition de containers
    • Docker Compose
  • pour le cluster
    • Docker Swarm ↘
    • Kubernetes (k8s) ↗

Atelier logiciel

  • Automatiser du développement au déploiement
  • Utiliser les outils nécessaires
    • organisation : redmine, jira, trello,...
    • automatisation : jenkins
      • qualité : sonarqube, linters,...
      • tests unitaires
      • tests d'intégration
    • bug tracker : mantis, redmine, jira,...

Log

Monitorer

  • Sans log impossible de suivre le fonctionnement, l'état de santé des nombreux containers
  • Outiller les logs : ELK (ElasticSearch Logstash Kibana)

Exemple

Cas d'école

  • Des tiers
  • Des documents
  • Des tâches

Cas d'école

  • Des tiers
    • physique ou moraux
    • format adullact (administrations publiques)
  • Des documents
    • existe déjà
    • la norme CMIS (Alfresco, MS Sharepoint, IBM FileNet,...)
  • Des tâches

Conclusion

Prendre la solution adaptée

Made with Slides.com