Les tests de charge avec JMeter 1/5

JMeter logo

Les tests de charge sont un sujet complexe et JMeter l’est aussi. Il y a moultes articles qui exposent la difficulté à réaliser ces tests et qui orientent le lecteur vers des prestations d’expertise. Ce n’est pas nécessairement un mauvais choix tellement l’investissement sur l’outil JMeter et la réalisation de tests est laborieuse. Je ne vais pas revenir sur ce sujet qui a été décrit à foison, je vais juste vous montrer comment faire fonctionner JMeter en 2021. Car là aussi, comme c’est un outil qui a vécu, il a une vingtaine d’années, voire survécu, contrairement à pas mal d’autres concurrents, il y a beaucoup de documentations obsolètes.

J’avais fait quelques tests avec la version 2.13 de JMeter qui est fournie dans la distribution Debian Buster, mais certains élèves de ma classe, avaient installé la dernière version sous Windows, JMeter 5.4.1, et comme ils étaient un peu perdus, je me suis lancé à installer cette version pour les aider. Finalement, c’est cette version que je vais détailler ci-dessous, car les différences avec les versions précédentes sont minimes et les scénarios fonctionnent aussi bien sur les deux versions. Par contre, dans la version 5.4, il y a un outil de reporting bien pratique que j’utiliserai dans les rapports de test de charge.

Pour créer un scénario, il faut passer par le proxy fourni par JMeter. En effet, au début du Web, on pouvait créer ses requêtes HTTP à la main. Aujourd’hui, vue la complexité des échanges avec un serveur Web, il est nécessaire de photographier les échanges, c’est le rôle du proxy qui se place entre votre navigateur et le site Web que vous voulez tester et qui va générer toutes les requêtes pour vous !

Pour savoir comment mettre en place le proxy dans JMeter, il faut regarder le paragraphe « Create Test Plan from Template » de la documentation : https://jmeter.apache.org/usermanual/get-started.html ou mieux le tutorial « Recording Tests« . On s’aperçoit que le fichier PDF d’aide de la template « Recording » date de 2013. Ce n’est pas très récent, néanmoins, il permet de guider l’utilisateur pour faire les enregistrements.

Note sur les templates Recording
Il y a deux templates fournies dans JMeter 5.4.1 :

  1. Recording
  2. Recording with Think Time

Le Think Time enregistre les durées de votre scénario. C’est à dire le temps qui s’écoule entre chaque clic. Lorsqu’on rejoue le scénario, JMeter va respecter les temps d’attente avec un léger aléa de + ou – 100ms. Si vous passez 15 minutes à enregistrer votre scénario de 5 pages, JMeter va créer un scénario de 5 pages qui va durer 15 minutes. C’est le moyen de reproduire un véritable parcours utilisateur. Bien que ce soit plaisant intellectuellement de reproduire la réalité, cette technique va ralentir les tests et ne va pas apporter nécessairement de bénéfices par rapport à un test avec des durées réduites.

Personnellement j’utilise la template « Recording », qui enregistre toutes les requêtes les unes après les autres et j’ajoute les aléas temporels ensuite.

Quelle différence ?

Si mon parcours de 5 pages dure 15 minutes. Pour arriver à un débit de 1 page à la seconde, il faudra que lance 180 threads en parallèle. En effet, 15 minutes font 900 secondes, mon scénario visite 1 page toutes les 180 secondes. Pour avoir un équivalent d’une page à la seconde, il me faut lancer 180 threads. Et avec des aléas de 100ms (aléa par défaut de l’Uniform Random Timer), mes 180 threads vont faire à peu près les mêmes requêtes à la seconde près pendant pas mal de minutes. Donc le temps de chauffe de mon test de charge va prendre des heures si je veux réussir à avoir un comportement de 180 threads aléatoires !!!

Et ça c’est un problème pratique important. En effet, si jamais mon script fait des erreurs, je ne le saurai qu’après des heures d’attente une fois le test terminé. Si jamais mon scénario n’est pas complet et qu’il faut rajouter une étape, là encore, il me faudra attendre des heures. L’infrastructure cible, l’injecteur et les outils de métrologie seront indisponibles pendant des heures. Bref, simuler la réalité est une fausse bonne idée car on va devoir attendre des jours avant d’avoir des résultats significatifs ! Et l’une des contraintes des tests de charge c’est le temps qu’ils nécessitent avant de pouvoir produire du sens ! Il faut parfois lancer une dizaine de tests avant d’avoir corrigé tous les problèmes du scénario, mais aussi sur l’application ou sur le paramétrage des composants du serveur et savoir ce qu’on cherche à montrer.

Etape 1 : mise au point du scénario statique

Donc on démarre sur la template « Recording » qui va créer un scénario où toutes les requêtes se trouveront l’une derrière l’autre. On verra ensuite comment « humaniser » le scénario.

On lance JMeter, en ligne de commande, c’est jmeter ou jmeter.bat dans le répertoire bin, qui affiche l’écran suivant :

Pour mettre en place un enregistrement, il faut aller dans File → Templates… et sélectionner Recording qui affiche alors l’écran suivant :

Après avoir cliqué sur Create, il faut saisir les paramètres globaux du scénario

et il ne reste plus qu’à retoucher les paramètres de l’enregistrement.

Dans l’onglet Test Plan Creation, on choisit
pour Grouping : Do not group samplers
pour Naming scheme : le format proposé dans lequel on supprime le nom.

Dans l’onglet Requests Filtering, on définit l’URL à inclure :
.*alain.arditi.fr.* signifie qu’on prend toutes les URLs qui pointent sur le site. Si on ne définit pas d’URL dans les inclusions, l’enregistrement ne produira aucun scénario. Il est donc impératif de définir les URLs à inclure.

Il faut également parfois retoucher les URLs qu’on ne veut pas enregistrer. Par exemple, les images sont exclues par défaut, car elle n’apportent souvent peu d’éléments au tests. Dans notre cas, on exclut les fichiers ayant pour extension webp qui sont des images.

On peut ensuite lancer l’enregistrement avec le bouton Start ! Dès ce moment, on a une popup qui apparait pour arrêter l’enregistrement.

Ici, on utilise Firefox pour créer le scénario en utilisant le proxy JMeter sur le port 8888 (valeur par défaut de JMeter). On peut surfer sur le site, comme ci dessous, tous les échanges sont enregistrés.

Une fois qu’on a stoppé l’enregistrement du scénario, on retrouve tout les échanges entre le navigateur et le site dans l’item « View Result Tree ».

Les erreurs sont marquées en rouge. Il y a des erreurs sur le protocole HTTPS, qui n’ont pas d’impact sur l’enregistrement. On voit également qu’il y a deux fois la page 2-4, car j’ai cliqué 2 fois sur la page et on voit aussi deux fois la page 3-4 avec 2 URLs différentes dont la deuxième est une redirection de la première. Ca veut dire que le lien vers la page 3-4 qui se trouve dans la page 2-4 n’est pas le lien définitif de la page 3-4. C’est lié au fait que l’URL de la page 3-4 a changé après la création de la page 2-4. WordPress, plutôt que modifier le contenu des pages, crée des redirections pour que la page soit toujours accessible. Pour éviter cette redirection, il faut corriger la page 2-4. Voilà un point qu’on ne risquait pas de voir en cliquant sur les liens.

JMeter permet de décortiquer les échanges entre le navigateur Web et le site. Nous verrons dans une partie ultérieure que les scénarios dynamiques nécessitent la compréhension plus approfondie des échanges.

Maintenant on va s’intéresser au scénario créé par le Recorder. Il n’est pas nécessairement identique à ce qu’a vu le Recorder. Ce sont les filtres d’inclusion et d’exclusion d’URLs qui vont définir ce qu’on garde dans le scénario, qu’on voit quand on déploie l’item Thread Group / Recording Controller.

Sur le panneau de gauche, on retrouve le scénario construit par le Recorder

Maintenant, on peut rejouer le scénario en cliquant sur le bouton vert On voit dans l’item « View Result Tree » les réponses aux requêtes du scénario. On note que la requête 099 se décompose en 099 –

099 – /2021/02/16/booster-son-wordpress-avec-varnish-3-4/-0
099 – /2021/02/16/booster-son-wordpress-avec-varnish-3-4/-1

qui est en fait une requête sur /2021/02/13/booster-son-wordpress-avec-varnish-3-4/

Alors, à ce stade rien n’empêche d’effacer son scénario et de refaire un enregistrement après avoir corrigé le lien sur le site. Il faut cliquer sur l’item Recording Controller et cliquer sur le bouton Clear all the recorded samples pour effacer les enregistrements.

On peut également effacer les résultats des View Results Tree en cliquant sur les 2 balais

Le nouveau scénario ne contient plus le lien /2021/02/16/booster-son-wordpress-avec-varnish-3-4/ et la redirection

On peut lancer le scénario pour vérifier qu’il n’y a pas d’erreur.

Ici on voit qu’il n’y a pas d’erreur, toutes les réponses sont vertes avec des codes de retour 200
On peut également s’assurer qu’on est bien sur les bonnes pages en regardant la réponse du serveur : Response data
Qu’on peut afficher en HTML grâce à la petite combo en rouge sur la copie d’écran. Par contre le mode HTML est gourmand en ressources

On peut relancer les enregistrements en repartant de zéro pour finaliser la mise au point du scénario. On peut aussi ajouter un nouvel enregistrement au scénario existant, et compléter petit à petit, en réactivant le proxy à chaque fois. Ensuite, on peut déplacer les items du Thread Plan si on veut les ordonner différemment, les dupliquer, les supprimer, etc….

Il ne reste plus qu’à ajouter des timers avec des aléas avant de commencer à tester le site. Ces aléas permettent d’éviter que tous les threads fassent des requêtes au même moment. Il ne s’agit pas de délais humains, mais d’aléas de 100ms autour d’une valeur de 100ms. Ce qui produit des délais de 0 à 200ms.

Addition d’aléas temporels

On est prêt à tester notre scénario un peu plus à fond.

On ajoute un « Summary Report » qui nous permettra d’apprécier le comportement du site avant de lancer les tests
On passe à 5 threads pour voir la réaction du site
Après avoir nettoyé les résultats avec le bouton Balais, on lance le test avec le bouton Start en vert, et on obtient les résultats. Ici, 5 threads, une fois.

Le Summary Report permet de voir ce qui se passe lorsqu’on lance quelques thread. Il s’agit de contrôler le taux d’erreur et de vérifier que les résultats sont cohérents avec les estimations. Là on voit que la première requête a un temps de réponse beaucoup plus grand que les autres. Ce délai est du au temps de connexion du thread au serveur Web. C’est la création de la socket et la mise en place du chiffrement SSL. Pour les URLs suivantes, le temps de connexion est nul. On peut voir le détail des temps de connexions dans le panneau de droite dans « Sampler result » :

Par contre, si on lance 2 boucles, la deuxième fois, le temps de connexion est nul. Ce qui signifie que si on lance les scénarios plusieurs fois, JMeter réutilise les connexions. On pourrait dire que ce mode n’est pas très réaliste, car la création d’une connexion peut s’avérer couteuse du coté du serveur. On peut modifier le comportement par défaut en décochant l’option du Thread Group « Same user on each iteration ». Comme ça, chaque thread va créer une connexion au début du scénario, comme le ferait un utilisateur réel.

A ce stade on est prêt à passer aux tests de charge, c’est à dire à lancer JMeter en ligne de commande sur des durées significatives.

Les explications se trouvent dans l’article suivant :

Site officiel de JMeter : https://jmeter.apache.org/