Réaliser des tests de charge JMeter sur des serveurs AWS
JMeter est un outil de tests de performance basé sur Java qui peut donner un peu de fil à retordre à l’utilisateur qui veut obtenir le meilleur de l’outil. Notre objectif était d’atteindre le point de défaillance dans le test de charge d’une application sur des serveurs AWS. Nous avons dû relever quelques défis pour y parvenir avec JMeter.
Nous avons utilisé JMeter pour effectuer des tests de performance pour l’un de nos clients, en visant 400 utilisateurs simultanément. Nous avons rencontré quelques difficultés au départ, que nous avons surmontées en optimisant le code, en utilisant le bon type de samplers et leurs propriétés, le bon type de groupes de threads pour atteindre le niveau de simultanéité souhaité, et bien sûr, en utilisant les listeners uniquement pour le débogage, et non pour les tests de charge réels.
D’autres difficultés sont apparues lorsque le nombre d’utilisateurs a été porté à 1 000 simultanés, car JMeter n’arrivait pas à gérer un volume aussi important. Par exemple, il a commencé à faiblir tout en imposant la même charge aux serveurs AWS, et les résultats des tests de charge indiquaient plutôt des erreurs de JMeter que des défaillances réelles des serveurs. De sérieux changements de configuration ont été nécessaires pour porter la capacité de JMeter à un niveau où il pourrait générer sans faiblir la charge souhaitée et faire tomber les serveurs AWS.
Voici nos meilleurs trucs pour faire en sorte que JMeter soit en mesure de mettre à genoux des serveurs AWS :
Distribuer les tests
Le test distribué est votre première et meilleure arme pour générer suffisamment de charge afin d’amener à son point de rupture un serveur AWS autodimensionnable et parfaitement équilibré en charge. L’utilisation de JMeter en local limite le nombre d’utilisateurs simultanés qui peuvent agir sur un système donné à un moment donné : vous êtes entièrement dépendant du processeur et de la mémoire du système sur lequel le test de charge est effectué.
En utilisant le mode maître-esclave, l’exécution du test sur deux serveurs ou plus répartit la charge sur les systèmes, ce qui permet de dimensionner JMeter à la taille et à l’espace de toutes les machines maître-esclave combinées. La distribution des machines permet non seulement de répartir la charge pour générer un nombre énorme de threads chaque seconde, mais aussi de distribuer les fichiers CSV de données de test et les énormes fichiers de résultats pour encore plus de puissance. La communauté en ligne atteste de l’exécution de 250 à 500 threads simultanés par serveur. Vous pouvez ajouter des machines au système distribué en fonction du besoin global de génération de charge.
Augmenter les ports de connexion TCP
Une machine Windows standard n’établit des connexions TCP/IP sortantes que par les ports 1024-5000, et il faut jusqu’à 4 minutes pour les recycler. L’exécution de tests de charge nécessite un grand nombre de connexions en peu de temps, saturant rapidement cette plage de ports. Lorsque nous avons tenté de cibler 400 utilisateurs simultanés pour tester en charge les services AWS, la machine JMeter qui tourne sur Windows n’a même pas pu atteindre cette cible de simultanéité.
Pour augmenter le nombre maximum de ports éphémères, suivez ces étapes :
- Sur chaque JVM, lancez l’éditeur de registre.
- Localisez la sous-clé suivante dans le registre, puis cliquez sur Parameters :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters. - Faites un clic droit sur Parameters.
- Créez une nouvelle valeur DWORD avec le nom MaxUserPort.
- Faites un clic droit sur MaxUserPort.
- Entrez 65534 pour le champ Value Data.
- Sous le bouton radio de sélection pour la Base, sélectionnez le bouton radio Decimal.
- Cliquez sur OK. Fermez le registre.
- Relancez chaque agent de charge JMeter.
Augmenter la mémoire heap
Après avoir augmenté le nombre de connexions TCP utilisant des ports, nous avons amené JMeter au niveau de simultanéité souhaité. Mais assez vite, les machines JMeter ont commencé à produire des erreurs “Out of memory”. Il était essentiel d’effectuer des tests de charge en utilisant le mode GUI, car une intervention manuelle était nécessaire pour démarrer et arrêter plusieurs groupes de threads pendant que l’application changeait sans cesse d’état, passant d’inactive à active, puis à fermée. Même si seul Aggregate Listener a été utilisé avec le moins de configuration possible pour économiser de l’espace, nous avons continué à obtenir des erreurs provoquées par des problèmes de mémoire.
La JVM peut être réglée finement pour augmenter la mémoire vive allouée. Lorsqu’un programme Java comme JMeter nécessite une quantité de mémoire importante, la RAM est généralement réaffectée.
JMeter utilise jusqu’à 512 Mo de RAM par défaut, comme indiqué dans les scripts de lancement jmeter.sh ou jmeter.bat. Nous avons augmenté la taille du heap à 4 Go :
set HEAP=-Xms1024m -Xmx4096m -XX:MaxMetaspaceSize=1024m
Cependant, relancer JMeter après avoir augmenté la taille du heap produisait l’erreur suivante :
Invalid initial heap size: -Xms4g
The specified size exceeds the maximum representable size.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
errorlevel=1
Pour régler cette erreur, nous avons dû mettre à jour Java (JDK en particulier) et JMeter avec les dernières versions. En effet, le dernier JDK contient un compilateur optimisé serveur qui améliore l’exécution du code Java, donc celle de JMeter. Après avoir téléchargé et installé la dernière version du JDK, nous avons redémarré le serveur JMeter, et voilà, plus aucune erreur JVM n’a surgi.
Nous avons ainsi pu effectuer avec succès les tests de charge avec 1 000 utilisateurs simultanés, avec même des pics jusqu’à 3 000.