Gatling vs JMeter vs The Grinder: Comparaison des outils de test de charge

1. Introduction

Choisir le bon outil pour le travail peut être intimidant. Dans ce didacticiel, nous allons simplifier cela en comparant trois outils de test de charge d'application Web - Apache JMeter, Gatling et The Grinder - à une API REST simple.

2. Outils de test de charge

Tout d'abord, passons en revue rapidement quelques informations générales sur chacun.

2.1. Gatling

Gatling est un outil de test de charge qui crée des scripts de test dans Scala. L'enregistreur de Gatling génère les scripts de test Scala, une fonctionnalité clé pour Gatling. Consultez notre tutoriel d'introduction à Gatling pour plus d'informations.

2.2. JMeter

JMeter est un outil de test de charge par Apache. Il fournit une belle interface graphique que nous utilisons pour la configuration. Une fonction unique appelée contrôleurs logiques offre une grande flexibilité pour configurer des tests dans l'interface graphique.

Visitez notre tutoriel d'introduction à JMeter pour des captures d'écran et plus d'explications.

2.3. Le moulin

Et notre dernier outil, The Grinder, fournit un moteur de script plus basé sur la programmation que les deux autres et utilise Jython. Cependant, The Grinder 3 dispose d'une fonctionnalité d'enregistrement de scripts.

Le Grinder diffère également des deux autres outils en permettant des processus de console et d'agent. Cette fonctionnalité offre la possibilité d'un processus d'agent afin que les tests de charge puissent évoluer sur plusieurs serveurs. Il est spécifiquement annoncé comme un outil de test de charge conçu pour que les développeurs trouvent les blocages et les ralentissements.

3. Configuration du scénario de test

Ensuite, pour notre test, nous avons besoin d'une API. Notre fonctionnalité API comprend:

  • ajouter / mettre à jour un enregistrement de récompenses
  • afficher un / tous les enregistrements de récompenses
  • lier une transaction à un enregistrement de récompenses client
  • afficher les transactions pour un enregistrement de récompenses client

Notre scénario:

Un magasin organise une vente à l'échelle nationale avec des clients nouveaux et récurrents qui ont besoin de comptes de récompenses client pour réaliser des économies. L'API de récompenses vérifie le compte de récompenses client à l'aide de l'identifiant client . Si aucun compte de récompenses n'existe, ajoutez-le, puis associez-le à la transaction.

Après cela, nous interrogeons les transactions.

3.1. Notre API REST

Voyons brièvement l'API en affichant certains des stubs de méthode:

@PostMapping(path="/rewards/add") public @ResponseBody RewardsAccount addRewardsAcount(@RequestBody RewardsAccount body) @GetMapping(path="/rewards/find/{customerId}") public @ResponseBody Optional findCustomer(@PathVariable Integer customerId) @PostMapping(path="/transactions/add") public @ResponseBody Transaction addTransaction(@RequestBody Transaction transaction) @GetMapping(path="/transactions/findAll/{rewardId}") public @ResponseBody Iterable findTransactions(@PathVariable Integer rewardId) 

Notez certaines relations telles que la recherche de transactions par identifiant de récompense et l'obtention du compte de récompenses par identifiant client . Ces relations imposent une certaine logique et une certaine analyse des réponses pour la création de notre scénario de test.

L'application testée utilise également une base de données en mémoire H2 pour la persistance.

Heureusement, nos outils le gèrent tous assez bien, certains mieux que d'autres.

3.2. Notre plan de test

Ensuite, nous avons besoin de scripts de test.

Pour obtenir une comparaison équitable, nous effectuerons les mêmes étapes d'automatisation pour chaque outil:

  1. Générer des identifiants de compte client aléatoires
  2. Publier une transaction
  3. Analyser la réponse pour l'ID client aléatoire et l'ID de transaction
  4. Requête pour un identifiant de compte de récompenses client avec l'identifiant client
  5. Analyser la réponse pour l'ID de compte de récompenses
  6. Si aucun identifiant de compte Rewards n'existe, ajoutez-en un avec un message
  7. Publiez la même transaction initiale avec l'identifiant de récompenses mis à jour en utilisant l'identifiant de transaction
  8. Requête pour toutes les transactions par identifiant de compte de récompenses

Examinons de plus près l'étape 4 pour chaque outil. Et assurez-vous de consulter l'exemple pour les trois scripts terminés.

3.3. Gatling

Pour Gatling, la familiarité avec Scala ajoute une aubaine pour les développeurs puisque l'API Gatling est robuste et contient de nombreuses fonctionnalités.

L'API de Gatling adopte une approche DSL constructeur, comme nous pouvons le voir à son étape 4:

.exec(http("get_reward") .get("/rewards/find/${custId}") .check(jsonPath("$.id").saveAs("rwdId"))) 

Il convient de noter en particulier la prise en charge par Gatling du chemin JSON lorsque nous devons lire et vérifier une réponse HTTP. Ici, nous allons récupérer l'identifiant de récompense et l'enregistrer dans l'état interne de Gatling.

En outre, le langage d'expression de Gatling facilite les chaînes de corps de requête dynamiques :

.body(StringBody( """{ "customerRewardsId":"${rwdId}", "customerId":"${custId}", "transactionDate":"${txtDate}" }""")).asJson) 

Enfin notre configuration pour cette comparaison. Les 1000 exécutions définies comme une répétition de l'ensemble du scénario, la méthode atOnceUsers définit les threads / utilisateurs:

val scn = scenario("RewardsScenario") .repeat(1000) { ... } setUp( scn.inject(atOnceUsers(100)) ).protocols(httpProtocol)

L'ensemble du script Scala est visible dans notre référentiel Github.

3.4. JMeter

JMeter génère un fichier XML après la configuration de l'interface graphique. Le fichier contient des objets spécifiques à JMeter avec des propriétés définies et leurs valeurs, par exemple:

Vérifiez les attributs de testname , ils peuvent être étiquetés lorsque nous les reconnaissons correspondant aux étapes logiques ci-dessus. La possibilité d'ajouter des enfants, des variables et des étapes de dépendance donne à JMeter la flexibilité offerte par les scripts. De plus, nous définissons même la portée de nos variables!

Notre configuration pour les exécutions et les utilisateurs dans JMeter utilise ThreadGroups :

100

View the entire jmx file as a reference. While possible, writing tests in XML as .jmx files do not make sense with a full-featured GUI.

3.5. The Grinder

Without the functional programming of Scala and GUI, our Jython script for The Grinder looks pretty basic. Add some system Java classes, and we have a lot fewer lines of code.

customerId = str(random.nextInt()); result = request1.POST("//localhost:8080/transactions/add", "{"'"customerRewardsId"'":null,"'"customerId"'":"+ customerId + ","'"transactionDate"'":null}") txnId = parseJsonString(result.getText(), "id")

However, fewer lines of test setup code are balanced by the need for more string maintenance code such as parsing JSON strings. Also, the HTTPRequest API is slim on functionality.

With The Grinder, we define threads, processes, and runs values in an external properties file:

grinder.threads = 100 grinder.processes = 1 grinder.runs = 1000

Our full Jython script for The Grinder will look like this.

4. Test Runs

4.1. Test Execution

All three tools recommend using the command line for large load tests.

To run the tests, we'll use Gatling open-source version 3.4.0 as a standalone tool, JMeter 5.3 and The Grinder version 3.

Gatling requires only that we have JAVA_HOME and GATLING_HOME set. To execute Gatling we use:

./gatling.sh

in the GATLING_HOME/bin directory.

JMeter needs a parameter to disable the GUI for the test as prompted when starting the GUI for configuration:

./jmeter.sh -n -t TestPlan.jmx -l log.jtl

Like Gatling, The Grinder requires that we set JAVA_HOME and GRINDERPATH. However, it needs a couple more properties, too:

export CLASSPATH=/home/lore/Documents/grinder-3/lib/grinder.jar:$CLASSPATH export GRINDERPROPERTIES=/home/lore/Documents/grinder-3/examples/grinder.properties

As mentioned above, we provide a grinder.properties file for additional configuration such as threads, runs, processes, and console hosts.

Finally, we bootstrap the console and agents with:

java -classpath $CLASSPATH net.grinder.Console
java -classpath $CLASSPATH net.grinder.Grinder $GRINDERPROPERTIES

4.2. Test Results

Each of the tests ran 1000 runs with 100 users/threads. Let's unpack some of the highlights:

Successful Requests Errors Total Test Time (s) Average Response Time (ms) Mean Throughput
Gatling 500000 Requests 0 218s 42 2283 req/s
JMeter 499997 Requests 0 237s 46 2101 req/s
The Grinder 499997 Requests 0 221s 43 2280 req/s

The results show the 3 tools have similar speed, with Gatling slightly edging out the other 2, based on the mean throughput.

Each tool also provides additional information in a friendlier user interface.

Gatling will generate an HTML report at the end of the run, which contains multiple graphs and statistics, for the total run as well as for each request. Here's a snippet of the test result report:

When using JMeter, we can open the GUI after the test run and generate an HTML report based on the log file where we saved the results:

The JMeter HTML report also contains a breakdown of the statistics per request.

Finally, The Grinder Console records statistics for each agent and run:

While The Grinder is high-speed, it comes at the cost of additional development time and less diversity of output data.

5. Summary

Now it's time to take an overall look at each of the load testing tools.

Gatling JMeter The Grinder
Project and Community 9 9 6
Performance 9 8 9
Scriptability/API 7 9 8
UI 9 8 6
Reports 9 7 6
Integration 7 9 7
Summary 8.3 8.3 7

Gatling:

  • Solid, polished load testing tool that outputs beautiful reports with Scala scripting
  • Open Source and Enterprise support levels for the product

JMeter:

  • Robust API (through GUI) for test script development with no coding required
  • Prise en charge d'Apache Foundation et excellente intégration avec Maven

Le broyeur:

  • Outil de test de charge de performance rapide pour les développeurs utilisant Jython
  • L'évolutivité entre serveurs offre encore plus de potentiel pour les tests de grande envergure

En termes simples, si la vitesse et l'évolutivité sont nécessaires, utilisez The Grinder.

Si de superbes graphiques interactifs permettent de montrer un gain de performances pour plaider en faveur d'un changement, utilisez Gatling.

JMeter est l'outil pour la logique métier compliquée ou une couche d'intégration avec de nombreux types de messages. Dans le cadre de l'Apache Software Foundation, JMeter fournit un produit mature et une large communauté.

6. Conclusion

En conclusion, nous voyons que les outils ont des fonctionnalités comparables dans certains domaines et brillent dans d'autres. Le bon outil pour le bon travail est la sagesse familière qui fonctionne dans le développement de logiciels.

Enfin, l'API et les scripts peuvent être trouvés sur Github.