Gatling – Test de charge et cloudification

Dans le cadre du développement de l’application FastContest et de son déploiement dans le cloud d’Amazon avec Cloudify, nous avons souhaité effectuer des tests de charge automatisés afin :

  • d’évaluer la charge maximale que notre application pouvait soutenir
  • de dimensionner les machines du Cloud sur lesquelles nous déployons
  • de mettre en exergue les faiblesses de notre application
  • de jouer des scénarios définis automatiquement avec plusieurs centaines de joueurs concourants et ainsi de vérifier la bonne intégrité des données à l’issue

Nous avons choisi d’utiliser Gatling, un outil de test de charge open-source, qui permet d’écrire les scénarios de test sous forme de codes élégants et concis.

Arborescence de Gatling

Le dossier d’installation de Gatling est organisé selon l’arborescence suivante :

  • /results : Contient les résultats des benchs sous format web
  • /bin : Contient les scripts permettant de lancer Gatling
  • /target : Contient les fichiers issus de la compilation de nos scénarios + cache
  • /conf : Contient les fichiers de configuration (niveau de log…)
  • /user-files : Contient les fichiers .scala de définition des scénarios
  • /lib : jar de gatling

Des scénarios implémentés en Scala

À la différence de JMeter qui dispose d’une interface graphique pour la définition des scénarios de simulation et de ses paramètres, Gatling propose une API écrite en Scala. Contre-intuitivement, il est assez élégant et aisé de définir des scénarios en Scala plutôt que via une interface graphique, surtout qu’il n’est pas nécessaire d’être un ninja en Scala pour réaliser ses premiers scénarios. Gatling propose une multitude de fonctionnalités dont les basiques seront présentées plus loin.
La documentation complète est disponible à ce lien.
Les scénarios sont placés dans le dossier /user-files/simulations. Voici, typiquement, un scénario implémenté en Scala :

val scn = scenario("User play")
  .feed(myCustomFeeder)
  .exec(
     http("register")
      .post("/user/register")
      .param("email", "${email}")
      .param("password", "${password}")
      .param("pseudo", "${pseudo}")
      .headers(headers_1)
      .check(status.is(200)))
  .pause(0 milliseconds, 100 milliseconds)
  .repeat(10) {
    feed(csv("question_answer.csv").circular)
      .exec(
        http("answer")
         .post("/response")
         .param("questionId", "${questionId}")
         .param("answerId", "${answerId}")
         .headers(headers_1))
      .pause(0,5)
  }

Dans ce cas, Gatling va effectuer une requête post /user/register avec les paramètres email et password (défini dans un fichier séparé), et vérifiera que la réponse a bien un status 200. Enfin, après une pause de 0 à 100 ms, Gatling effectue 10 requêtes /response avec une pause de 0 à 5 sec entre chaque. Les paramètres sont fournis par un “feeder” qui permet de factoriser des variables au sein d’un fichier CSV par exemple (pour plus d’infos, suivez le lien)
Pour apprendre à écrire un scénario avec Gatling, il y a le tutorial officiel.

Exécution de bench

Pour lancer un scénario il suffit d’exécuter le script gatling.sh ou .bat selon l’environnement qui se trouve dans le dossier /bin. Gatling va compiler automatiquement les classes Scala puis vous demande de choisir le scénario à exécuter. À l’issue de la simulation, un rapport web est généré automatiquement à partir du fichier de log. Il contient toutes les métriques mises en forme de façon graphique grâce à la librairie Javascript HighChart.

Un exemple de rapport :

Cloudification

Afin d’effectuer des tests de charges proches des conditions réelles nous avons cloudifié Gatling en automatisant son installation et son exécution sur les VM d’Amazon.
Grâce à Cloudify, nous pouvons désormais lancer les tests de charge à partir d’Internet et sur autant de machine que nous voulons. Les recipes sont relativement simples puisqu’il s’agit essentiellement de télécharger et de dézipper le dossier d’installation de Gatling. Les scénarios sont uploadés avec la recipe, ils doivent donc être déplacés dans le répertoire /simulation de Gatling.
L’exécution du bench s’effectue grâce à une custom command “executeBench” dont le premier paramètre est le nom du scenario à exécuter et le second, le nom que l’on donne à cette simulation. La custom command lance alors le test de charge pour toutes les instances de Gatling sur chaque VM. Les rapports sont donc générés individuellement sur chaque VM.

Pour obtenir un rapport unique, on pourrait scripter la récupération de tous les résultats générés, leur fusion et la regénération d’un nouveau rapport global.
Le rapport est ensuite poussé sur S3 soit automatiquement, soit via une custom command (pushResult).

À travers ce use-case de Cloudify, nous montrons, une fois encore, sa simplicité et sa commodité d’utilisation en automatisant complètement la chaîne : déploiement, installation et exécution de tests de charge à partir du Cloud Amazon EC2.

Conclusion

L’un des avantages le plus important de Gatling est sans conteste sa capacité à générer des rapports graphiques de qualité à l’issue de chaque simulation. De cette façon, le testeur a immédiatement accès aux résultats de manière visuelle, sans post-traitement supplémentaire.
De plus, l’écriture des scénarios de test de façon fonctionnelle en Scala peut faciliter la lisibilité du test. Surtout grâce aux feeders qui permettent de factoriser les paramètres dans des fichiers à part.

Enfin, le lancement des tests via des simples commandes de script rend sa cloudification aisée.