TP9 : High Throughput on Woodytoys - PasRP-Theo/Admin-II GitHub Wiki

Documentation WoodyToys - Déploiement Docker Swarm

1. Nouveau service Web pour WoodyToys avec Docker Stack

1.1 Découverte du service Web

Pourquoi la directive build ne convient-elle pas dans le contexte Docker Swarm ?

La directive build permet de construire une image à partir de fichiers sources locaux. Cette approche fonctionne parfaitement en environnement de développement, mais présente des limitations majeures avec Docker Swarm :

  • Contexte de build distribué : En Swarm, les nœuds du cluster ne partagent pas le contexte de build, donc ils ne peuvent pas construire d'images localement
  • Images pré-construites requises : Swarm nécessite des images déjà construites et disponibles sur un registre (Docker Hub, registre privé, etc.)
  • Solution : Il faut remplacer build par image et publier l'image avant le déploiement

Flux de données du système

┌─────────────┐    HTTP     ┌──────────────┐    API      ┌─────────────┐
│   Client    │────────────▶│   Frontend   │────────────▶│     API     │
│     Web     │             │   (Nginx)    │             │  Backend    │
└─────────────┘             └──────────────┘             └─────────────┘
                                                                 │
                                                                 ▼
                            ┌──────────────┐             ┌─────────────┐
                            │    Cache     │◀────────────│  Base de    │
                            │   (Redis)    │    SQL      │  données    │
                            └──────────────┘             │ (Postgres)  │
                                                         └─────────────┘

Description des flux :

  1. Client Web → Frontend : Le client envoie des requêtes HTTP au frontend Nginx. Le frontend affiche l'interface utilisateur et communique avec l'API
  2. Frontend → API Backend : Le frontend envoie des requêtes à l'API pour récupérer/modifier des données. L'API traite les requêtes et renvoie des réponses (JSON)
  3. API Backend → Base de données : L'API interroge la DB Postgres pour récupérer/stocker des données (requêtes SQL)
  4. API Backend → Cache Redis : Pour optimiser les performances, l'API vérifie si les données demandées sont présentes dans le cache Redis avant d'interroger la DB

1.2 Déploiement sur Swarm

Adaptation du service

Modifications du docker-compose.yml :

  • Remplacement des directives build par image avec les références aux images publiées sur Docker Hub
  • Ajout de la directive deploy avec la configuration des replicas pour chaque service
  • Configuration des réseaux pour la communication inter-services

Script de build et push des images

#!/bin/bash

set -e

default_version="16" version=${1:-"$default_version"}

Build et tag des images

docker build -t pasrptheoo/woody_api_misc:"$version" api_misc docker tag pasrptheoo/woody_api_misc:"$version" pasrptheoo/woody_api_misc:latest

docker build -t pasrptheoo/woody_api_orders:"$version" api_orders docker tag pasrptheoo/woody_api_orders:"$version" pasrptheoo/woody_api_orders:latest

docker build -t pasrptheoo/woody_api_products:"$version" api_products docker tag pasrptheoo/woody_api_products:"$version" pasrptheoo/woody_api_products:latest

docker build -t pasrptheoo/woody_rp:"$version" reverse-proxy docker tag pasrptheoo/woody_rp:"$version" pasrptheoo/woody_rp:latest

docker build -t pasrptheoo/woody_database:"$version" database docker tag pasrptheoo/woody_database:"$version" pasrptheoo/woody_database:latest

docker build -t pasrptheoo/woody_front:"$version" front docker tag pasrptheoo/woody_front:"$version" pasrptheoo/woody_front:latest

Push des images

docker push pasrptheoo/woody_api_products:"$version" docker push pasrptheoo/woody_api_products:latest

docker push pasrptheoo/woody_api_orders:"$version" docker push pasrptheoo/woody_api_orders:latest

docker push pasrptheoo/woody_api_misc:"$version" docker push pasrptheoo/woody_api_misc:latest

docker push pasrptheoo/woody_rp:"$version" docker push pasrptheoo/woody_rp:latest

docker push pasrptheoo/woody_front:"$version" docker push pasrptheoo/woody_front:latest

docker push pasrptheoo/woody_database:"$version" docker push pasrptheoo/woody_database:latest

Commande de déploiement

docker stack deploy -c docker-compose.yml woodytoys

1.3 Observations et analyses des limitations

Analyse des performances

Problème identifié : Chargement lent dû à une image volumineuse (5.0 MB) observé via les DevTools du navigateur.

Méthode de mesure : Utilisation de la commande time wget -r pour mesurer les performances de téléchargement.

Résultats initiaux :

  • Temps total : 16s
  • Fichiers téléchargés : 2 fichiers, 4.8M
  • Débit : 307 KB/s

Campagne de mesure

Méthodologie :

  • Utilisation de time wget -r pour des mesures reproductibles
  • Tests avant et après modifications du nombre de répliques
  • Configurations testées : 1, 2, et 3 répliques pour les services API et Frontend
  • Enregistrement du temps total, nombre de fichiers et taille téléchargée

Résultats comparatifs

Configuration Temps réel Temps utilisateur Temps système Débit
1 replica 19.141s 0.032s 0.068s 307 KB/s
2 replicas 19.115s 0.026s 0.066s 307 KB/s
3 replicas 19.127s 0.029s 0.067s 307 KB/s

Analyse critique

L'augmentation du nombre de répliques ne résout pas les problèmes de performance. Les différences observées sont négligeables et restent dans la marge d'erreur des mesures.

Limitations des tests :

  • Le goulot d'étranglement principal est la taille de l'image (4.8M)
  • Les répliques n'améliorent pas le débit de téléchargement d'un fichier statique
  • Les conditions de test ne représentent pas une charge réelle avec plusieurs utilisateurs simultanés

1.4 Améliorations possibles au niveau Docker Swarm

Au-delà des répliques, plusieurs optimisations sont possibles :

Health Checks pour l'API

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:5000/api/ping"]
  interval: 30s
  timeout: 10s
  retries: 3
  • Vérification automatique du bon fonctionnement de l'API
  • Redémarrage automatique en cas de dysfonctionnement
  • Amélioration de la disponibilité du service

Contraintes de placement pour la base de données

deploy:
  placement:
    constraints:
      - node.labels.storage == ssd
      - node.role == manager
  • Assure que la DB est déployée sur un nœud avec des ressources adéquates
  • Améliore la stabilité et les performances de stockage

2. Mise en place d'un cache Redis

2.1 Configuration du service Redis

Ajout dans docker-compose.yml

redis:
  image: redis:latest
  networks:
    woody_net:
      aliases:
        - redis
  deploy:
    replicas: 3

2.2 Adaptation du code backend Flask

from flask import Flask, request
from flask_cors import CORS
import redis
import woody

app = Flask('my_api') cors = CORS(app)

r = redis.Redis(host='redis', port=6379, db=0)

@app.get('/api/ping') def ping(): return 'ping'

2.3 Mesures de performances avec cache

Résultats comparatifs

Sans cache (première requête) :

real    0m18.151s
user    0m0.001s
sys     0m0.010s

Avec cache (requête suivante) :

real    0m3.090s
user    0m0.011s
sys     0m0.000s

Analyse des performances

Amélioration spectaculaire : Le temps de réponse a diminué de 83% (de 18.151s à 3.090s) pour les requêtes répétitives.

Explication : Les lectures répétées sur les mêmes données n'ont plus besoin d'interroger la base PostgreSQL, mais sont servies directement depuis la mémoire avec Redis, ce qui est beaucoup plus rapide.

3. CDN (Content Delivery Network)

3.1 Mise en œuvre

Note : La mise en place d'un CDN n'a pas été réalisée dans le cadre de ce projet pour des raisons budgétaires (refus d'utiliser une carte bancaire pour ce cours).

3.2 Bénéfices théoriques d'un CDN

Avantages attendus

  • Réduction du temps de chargement : Distribution géographique des ressources
  • Décharge du serveur frontend : Les ressources statiques sont servies par le CDN
  • Meilleure réactivité de l'application : Latence réduite grâce à la proximité géographique
  • Scalabilité améliorée : Gestion automatique des pics de trafic

Conclusion

L'utilisation d'un CDN est une solution efficace pour améliorer les performances des ressources statiques, complétant les autres optimisations mises en place (répliques et cache Redis).

4. Optimisation de la base de données

4.1 Solution recommandée : Réplication Master-Slave

Description

Configuration d'une base de données principale (Master) qui gère toutes les opérations d'écriture, et une ou plusieurs bases de données secondaires (Slaves) qui sont des copies synchronisées du Master et qui gèrent les opérations de lecture.

Avantages

  • Répartition de charge : Séparation des opérations de lecture et d'écriture
  • Amélioration des performances : Les requêtes de lecture sont distribuées sur plusieurs serveurs
  • Haute disponibilité : Redondance en cas de panne du serveur principal
  • Scalabilité horizontale : Possibilité d'ajouter des slaves selon les besoins

Inconvénients

  • Complexité de configuration : Mise en place et maintenance plus complexes
  • Latence de synchronisation : Délai possible entre l'écriture et la disponibilité en lecture sur les slaves
  • Coût infrastructure : Nécessite des ressources supplémentaires

Particularités

  • Cohérence éventuelle : Les données peuvent être temporairement incohérentes entre Master et Slaves
  • Gestion des pannes : Nécessite une stratégie de basculement (failover) en cas de panne du Master
⚠️ **GitHub.com Fallback** ⚠️