TP: Service Web Rest ET Tests de performance (Synchronous programming:
Platform threads vs. Virtual threads)
Rappel :
Fig 1 : Platform Thread
Fig. 2 : Virtual threads
1/12
Activité 1 : contexte de programmation synchrone
Dans cette activité, nous souhaitons réaliser une étude benchmark dans le contexte de la
programmation synchrone pour comparer la performance des threads classiques (Platform threads)
avec les threads virtuels (Virtual threads). Pour illustrer cette étude, cette activité pratique consiste à
développer une API CRUD basée sur un service web REST pour la gestion des produits d’une
boutique virtuelle en utilisant le framework Spring Boot. Cette API va subir par la suite des tests de
performance à l’aide de l’outil Apache Jmeter et Apache Benchmark dans le cas des threads classique
et le cas des threads virtuelles.
N.B : Le dossier Tools comporte les différents outils nécessaires pour réaliser le TP
Travail à réaliser :
Etape 1 : Créer un nouveau projet Spring Boot à l’aide d’IntelliJ IDEA comme suit :
2/12
Etape 2 : Choisir la version du Spring Boot (3.2.x) et ajouter les dépendances comme suit :
Etape 3 : Après la création du projet, ajouter dans le fichier [Link] la dépendance suivante :
<dependency>
<groupId>[Link]</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
The Apache Commons Lang 3 library is a popular, full-featured package of utility classes, aimed at extending the
functionality of the Java [Link] library’s repertoire is pretty rich, ranging from string, array and number manipulation,
3/12
reflection and concurrency, to the implementations of several ordered data structures, like pairs and triples (generically
known as tuples).
Etape 4 : Créer l’API CRUD pour gérer les produits de la boutique virtuelle
a) Créer l’entité Product comme suit :
- package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Entity
@Getter
@Setter
public class Product {
………………………… }
b) Créer l’interface ProductRepository
package [Link];
import [Link];
………………………………………………………………………………………………………………………………………………………………………
c) Créer la classe ProductsService :
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Service
public class ProductsService {
@Autowired
ProductRepository productRepository;
public List<Product> getProducts() throws InterruptedException {
return ……………………………………………….;
}
public String bulkSaveProduct() throws InterruptedException {
for(int i=0; i< 1000; i++) {
Product product = new Product();
[Link]([Link](5));
[Link]([Link](10,1000));
[Link](1L);
saveOrUpdate(product);
}
return "finished";
}
4/12
public Product getProductsById(Long id)
{
return ……………………………………….
}
public void saveOrUpdate(Product product)
{
……………………………………………………………………..
}
//deleting a specific record by using the method deleteById() of
CrudRepository
public void delete(long id)
{
……………………………………………………….. }
//updating a record
public void update(Product product, long productid)
{
………………………………………………………………………………………..
}
d) Créer la classe Contrôleur
package [Link];
import [Link];
import [Link].*;
import [Link];
@RestController
public class Controller {
@Autowired
ProductsService productsservice;
//creating a get mapping that retrieves all the books detail from
the database
@GetMapping("/products")
private List<Product> getAllProducts() throws InterruptedException
{
…………………………………………………………. }
//creating a get mapping that retrieves the detail of a specific
product
@GetMapping("/products/{productid}")
private Product getProduct(@PathVariable("productid") long id) {
……………………………………………………………………………….. }
//creating a delete mapping that deletes a specified product
@DeleteMapping("/products/{productid}")
private void deleteProduct(@PathVariable("productid") int id) {
……………………………………………………………….
}
//creating post mapping that post the product detail in the
database
@PostMapping("/products")
5/12
private long saveProduct(@RequestBody Product product) {
……………………………………………………………………
…………………………………………………………………………………………
}
//creating put mapping that updates the product detail
@PutMapping("/products/{productid}")
private Product update(@RequestBody Product product,
@PathVariable("productid") long id) {
………………………………………………..
………………………………………………………………………………….. }
//creating post mapping that save 1000 products detail in the
database
@PostMapping("/bulksave")
public String BulkProduct() throws InterruptedException {
return ………………………………………………………………………………………..;
}
}
e) Lancer l’installation de MySQL puis créer un compte avec un mot de passe.
f) Créer une base de données avec le compte déjà créé.
g) Dans le fichier [Link] ajouter la configuration mysql suivante :
[Link]-auto=update
[Link]=jdbc:mysql://localhost:3306/nom_de_votre_BD
[Link]=nom_utistaeur
[Link]=votre_password
[Link]-class-name=[Link]
[Link]-sql: true
h) Lancer l’exécution de l’application, puis utiliser l’outil Postman pour ajouter 1000
produits en lançant une seule requête de type POST avec l’URI suivant :
localhost:8080/bulksave
i) Lancer une requête de type GET avec l’URI suivant : localhost:8080/products pour
vérifier l’existence de 1000 produits dans la table product de la base de données.
Activité 2 : l’utilisation de l’outil de test de performance « Apache Benchmark »
Apache Benchmark est un outil de benchmark HTTP permettant de mesurer la performance d'un serveur
Web, en particulier le nombre de requête qu'il peut servir par seconde.
Travail à réaliser
a) Télécharger le serveur Apache HTTP Server (version httpd-2.4.62-240904-win64-VS17)
depuis le site officiel ou une source fiable, puis extraire l’archive sur votre machine.
b) Ouvrir le dossier « httpd-2.4.62-240904-win64-VS17», puis accéder au sous-dossier bin où se
trouve l’outil ab.
c) Ajouter le chemin vers ab dans la variable d’environnement système PATH.
d) Dans le terminal, lancer l’outil de test en tapant ab pour vérifier avant de lancer des tests.
6/12
Cas 1 : Threads classique
Test 1 (1000 concurrent requests) :
Dans l’invite de commande ou terminal taper :
ab -n 20000 -c 1000 [Link]
-n requests : Number of requests to perform
-c concurrency : Number of multiple requests to make (concurrent requests)
Ensuite, remplir le tableau suivant :
platform threads
Time taken Requests per Time per Failed requests Transfer rate Ko/sec émis
for tests second request
Cas 2 : Threads virtuels
Pour activer les threads virtuels Java dans Spring Boot en ajoutant cette configuration dans le fichier «
[Link] » :
[Link]=true
Remarque : Cette configuration nécessite JDK 21 ou supérieur et Spring Boot 3.2 ou supérieur.
Refaire le test pour le cas des threads virtuels puis remplir le tableau suivant :
virtual threads
Time taken Requests per Time per Failed requests Transfer rate Ko/sec émis
for tests second request
Test 2 (2000 concurrent requests) :
Dans l’invite de commande ou terminal taper :
ab -n 20000 -c 2000 [Link]
Comme pour le test précédent, lancer le test2 pour les deux cas (Platform threads et virtual threads)
puis remplir les tableaux suivants :
- Désactiver Virtual threads
[Link]=false
7/12
platform threads
Time taken Requests per Time per Failed requests Transfer rate
for tests second request
- Réactiver Virtual threads
[Link]=false
virtual threads
Time taken Requests per Time per Failed requests Transfer rate
for tests second request
Question : Que peut-on déduire après l’analyse des résultats obtenus ?
En activant les Virtual Threads dans Spring Boot et en utilisant le driver MySQL Connector/J version 9.0.0,
refaire le test puis remplir le tableau suivant :
Test 1 (1000 concurrent requests) :
virtual threads + MySQL Connector/J version 9.0.0
Time taken Requests per Time per Failed requests Transfer rate
for tests second request
Test 2 (2000 concurrent requests) :
virtual threads + MySQL Connector/J version 9.0.0
Time taken Requests per Time per Failed requests Transfer rate
for tests second request
Question : Que peut-on déduire cette fois?
Activité 3 : l’utilisation de l’outil de test de performance « Apache Jmeter»
JMeter est un outil open source gratuit utilisé pour analyser et mesurer les performances des
applications, des différents services logiciels et des sites Web. Entièrement écrit en Java, JMeter
8/12
peut être utilisé pour effectuer des tests de performance, de charge et fonctionnels de nombreuses
applications Web et protocoles de serveur différents.
Apache JMeter peut simuler de lourdes charges sur un serveur en créant simultanément plusieurs
utilisateurs virtuels, également appelés utilisateurs simultanés. JMeter peut également être utilisé
pour tester des applications Web et FTP, des API SOAP et REST, ainsi que des protocoles de
messagerie tels que SMTP, POP3, IMAP et bien plus encore.
Travail à réaliser
a) Télécharger apache-jmeter.
b) Ouvrir le dossier « apache-jmeter », puis accéder au sous-dossier bin puis lancer le jar
exécutable de « ApacheJMeter»
c) Après avoir lancé Jmeter, suivez les étapes suivantes pour lancer un plan de test qui va
simuler la concurrence entre utilisateurs pour consommer la ressource suivante :
localhost:8080/products
Cas 1 : Threads classiques
i. Créer un groupe d’unité (un groupe de threads représente un groupe d'utilisateurs virtuels effectuant
un ensemble d'opérations): clic droit sur le Plan de test puis le remplir par les valeurs comme
suit :
ii. Créer une requête http de test lié au groupe déjà crée d’unité comme suit :
9/12
iii. Ajouter ensuite les récepteurs de résultats de la requête http : Arbre de résultats ;
Graphique évolution temps de réponse ; graphique de résultats ; graphique agrégé;
Tableau de résultats
Désactiver les threads virtuels Java dans Spring Boot en ajoutant cette configuration dans le fichier
« [Link] » :
[Link]=false
iv. Démarrer le test puis remplir le tableau suivant à la fin du test :
platform threads
Durée Débit moy Temps de % Erreur
de réponse moy
montée
groupe d'utilisateurs virtuels en
charge
(Ramp-Up
Period)
1000 3
secondes
2000 3
secondes
5000 3
secondes
10000 3
secondes
10/12
Cas 2 : Threads virtuels
Pour activer les threads virtuels Java dans Spring Boot en ajoutant cette configuration dans le fichier «
[Link] » :
[Link]=true
Remarque : Cette configuration nécessite JDK 21 ou supérieur et Spring Boot 3.2 ou supérieur.
Refaire le test pour le cas des threads virtuels puis remplir le tableau suivant :
virtual threads
groupe d'utilisateurs virtuels Durée Débit moy Temps de % Erreur
de réponse moy
montée
en
charge
200 3
secondes
500 3
secondes
1000 3
secondes
5000 3
secondes
10000 3
secondes
Question : Que peut-on déduire après l’analyse des résultats obtenus ?
En activant les Virtual Threads dans Spring Boot et en utilisant le driver MySQL Connector/J version 9.0.0,
refaire le test puis remplir le tableau suivant :
virtual threads + MySQL Connector/J version 9.0.0
groupe d'utilisateurs virtuels Durée Débit moy Temps de % Erreur
de réponse moy
montée
en
charge
200 3
secondes
500 3
secondes
1000 3
secondes
5000 3
secondes
10000 3
secondes
11/12
Question : Que peut-on déduire cette fois ?
Activité 4 : Génération des Graphiques de Performance
À partir des données du tableau rempli de l’activité précédente, analyser et visualiser les
performances du service REST.
Travail demandé
Les étudiants doivent :
a) Vérifier et organiser les données
S’assurer que les résultats du tableau sont complets :
o nombre d’utilisateurs
o débit moyen (requests/sec)
o temps de réponse moyen
o taux d’erreur
b) Construire un fichier de données exploitable
Créer un fichier CSV ou Excel structuré à partir du tableau :
Platform Threads
Virtual Threads
Virtual Threads + MySQL Connector/J 9.0.0
c) Générer les graphiques automatiquement
Utiliser Python pour produire :
Graphe 1 : Temps de réponse vs nombre d’utilisateurs
Graphe 2 : Débit moyen vs nombre d’utilisateurs
Graphe 3 : Taux d’erreur vs nombre d’utilisateurs
d) Comparer les performances
Analyser les résultats obtenus en répondant aux questions suivantes :
Quelle configuration offre la meilleure scalabilité ?
À partir de quel nombre d’utilisateurs observe-t-on une saturation ?
Quel est l’impact des Virtual Threads sur les performances ?
MySQL Connector/J 9.0.0 apporte-t-il une amélioration significative ?
12/12