Cet article montre les avantages de compiler et d’exécuter une application Java avec Quarkus.
En guise d’introduction sur ce qu’est Quarkus, vous pouvez lire le précédent article de blog écrit par Yann Albou.
Pour tirer le meilleur parti de votre application dans le Cloud, et en particulier dans des conteneurs et sur Kubernetes, il faut concevoir votre application pour ce nouveau monde. Comment les frameworks peuvent-ils aider à atteindre des niveaux élevés de productivité et d’efficacité ?
Les frameworks Java peuvent certainement y contribuer, que ce soit Spring Boot ou Quarkus, que nous comparons dans cet article à l’aide de la même application d’exemple.
Le code utilisé est disponible sur GitHub, vous y trouverez trois sous-répertoires :
- employee-sb : version Spring Boot
- employee-quarkus : version Quarkus
- comparisons : outils pour comparer l’application sur les deux plateformes
L’application d’exemple est un simple CRUD sur une entité racine “Persons”, connectée à une base de données Postgres. Nous utilisons Hibernate ORM pour les deux applications, ainsi que le framework Panache dans le cas de Quarkus.
Il existe deux façons de compiler une application Java avec le framework Quarkus :
- JVM standard / classique
- GraalVM (pour la génération de code natif)
Pour obtenir une surface d’exposition minimaliste en termes de sécurité, nous utiliserons scratch comme point de départ de notre image Docker, afin de n’y inclure que le binaire de notre application.
Configuration de l’environnement
Pour éviter une configuration complexe avec GraalVM, vous pouvez utiliser un build Docker multistage, qui permet de construire le binaire GraalVM sans l’installer localement.
Le build Docker multistage se compose de trois étapes (voir Dockerfile.scratch.native) :
- récupérer les dépendances jar dans la première étape, pour éviter de perdre du temps dans les étapes suivantes
- construire le binaire natif (certaines astuces sont nécessaires lors de l’utilisation d’une image scratch ou alpine, détaillées dans les commentaires du Dockerfile)
- enfin, copier le binaire dans notre image scratch
Dans les deux sous-répertoires employee-sb et employee-quarkus, vous trouverez un script build-mvn-docker qui construit les images pour vous, puis les tague avec le nom qui sera utilisé par les outils de comparaison.
Le matériel utilisé pour les comparaisons est un MacBook Pro équipé de Docker Desktop pour exécuter les conteneurs.
Les ressources dédiées à la machine virtuelle Docker sont :
- 8 Go de RAM + 1 Go de swap.
- 8 CPU.
Benchmark
Afin de comparer les différentes approches, nous examinons 3 métriques clés :
- le temps de démarrage
- la taille des artefacts générés et de l’image docker
- l’utilisation mémoire
Temps de démarrage
Spring Boot : temps de démarrage d’environ 10 secondes
- Classique
- Moins efficace que Quarkus
Quarkus JVM : temps de démarrage d’environ 2 à 3 secondes
- Build simple, sans -Dnative (ou -Pnative, au choix)
- Moins efficace qu’un build natif
- Plus efficace qu’une stack classique
Quarkus native : temps de démarrage inférieur à 0,1 seconde, comme montré ci-dessus
- Très efficace
- Le temps de compilation est lent puisqu’on utilise GraalVM, mais c’est le prix à payer pour obtenir de très bonnes performances à l’exécution. Notez que si vous utilisez un build multistage, votre temps de build sera plus lent que dans la “méthode GraalVM standard”.
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| Temps de démarrage | ~10s | ~3s | <0.1s |
| Temps de build | ~18s | ~20s | ~4m avec GraalVM local ~6m avec le multistaging |
Taille des fichiers JAR
| Spring Boot | Quarkus |
|---|
| 58.9M | 30Mo |
Si vous analysez le fichier jar généré par Quarkus, vous constatez qu’aucune lib (fichier JAR) n’est incluse : chaque classe nécessaire à l’exécution est extraite de sa librairie d’origine et incluse directement dans le jar généré. Ensuite, Quarkus ne conserve que les classes strictement nécessaires, ce qui donne un package aussi léger.
Par exemple, j’ai utilisé io.quarkus.hibernate.orm.panache.PanacheEntity de la dépendance maven Quarkus-Panache, mais pas io.quarkus.panache.common.Page, et vous ne trouverez donc pas cette classe Page dans le package final.
Taille des images Docker
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| 237M | 213M | 68.2M |
Comme il faut embarquer la JVM dans l’image Docker quarkus-jvm, sa taille est trois fois plus lourde que l’image docker native.
Comme la méthode native n’a pas besoin d’embarquer de JVM dans l’image docker, elle est beaucoup plus légère. Et la taille compte, car une image plus légère a un impact en termes de :
- stockage : vous aurez besoin de moins d’espace dans vos dépôts et sur votre machine de développement locale
- bande passante : plus l’image est légère, plus elle sera rapide à télécharger
- sécurité : la surface exposée aux attaques est plus petite, compte tenu du nombre de paquets
Exécution
Vous pouvez utiliser un simple fichier docker-compose pour exécuter les trois modes en parallèle (rappelez-vous que mes ressources dédiées pour Docker sont 8 Go de RAM et 8 CPU, vous pourrez observer des écarts dans les résultats de comparaison selon votre configuration).
RAM :
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| 386.5M | 205.7M | 15.96M |
CPU :
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| 0.38% | 0.32% | 0.02% |
On constate que, lorsque l’application est en “mode silencieux”, Quarkus consomme moins de mémoire et de CPU en mode JVM que Spring Boot, et c’est encore bien meilleur en mode natif (environ 10 fois moins de consommation CPU, et presque 20 fois moins de mémoire).
Scalabilité multi-instances sous charge
Dans un environnement conteneurisé, à des fins multi-tenant, il faut pouvoir scaler (à la hausse ou à la baisse) rapidement un service, si la charge devient trop importante pour que le service puisse répondre rapidement. Si l’application devient non réactive ou indisponible à cause du nombre de connexions, cela a forcément un impact pour les utilisateurs finaux…
Imaginons que notre application plante régulièrement à cause d’une fuite mémoire ou de tout autre problème : l’orchestrateur (Swarm, Kubernetes, etc.) redémarrera la réplique.
À titre de démonstration, nous le faisons simplement avec watch et docker-compose restart :
1
| watch -n 60 "docker-compose restart employee-qk-native employee-qk-jvm employee-sb"
|
Nous appelons ensuite chaque conteneur toutes les secondes pendant 100 secondes, pour vérifier qu’il est bien opérationnel :
1
2
3
| for i in {1..100}; do wget -t 1 localhost:8092/hello -a sb.log ;sleep 1; done
for i in {1..100}; do wget -t 1 localhost:8082/hello -a qk_native.log ;sleep 1; done
for i in {1..100}; do wget -t 1 localhost:8081/hello -a qk_jvm.log ;sleep 1; done
|
Nombre d’échecs :
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| 19 | 7 | 0 |
Augmentons le rythme, en redémarrant toutes les 10 secondes. Ceci est uniquement à des fins de démonstration (j’espère que cela ne vous arrivera jamais en conditions réelles).
Nombre d’échecs :
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| 99 | 37 | 1 |
En utilisant docker stats, on constate que :
- Spring Boot utilise parfois plus de 400% (4 cœurs) de CPU au redémarrage
- Quarkus en JVM plafonne l’utilisation CPU à environ 200% (2 cœurs)
- Quarkus native ne dépasse jamais 1%
Comme on peut le voir, la probabilité que vos utilisateurs soient impactés tend vers 0 lorsqu’on utilise Quarkus en mode natif. Et si vous n’êtes pas à l’aise avec la compilation native, utiliser Quarkus en mode JVM reste malgré tout meilleur que Spring Boot.
Nombre maximal de conteneurs concurrents
Pour cette section, vous pouvez utiliser les sous-dossiers de docker-compose, un par mode d’application.
Voici ce à quoi on peut s’attendre avec 8 Go de RAM pour docker :
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| Une instance | ~390M | ~210M | ~20M |
| # de conteneurs pour 8Go de RAM | 8000/390 =~ 20 | 8000/210 =~ 38 | 8000/20 = 400 |
Pour l’initialisation de Swarm, nous utilisons la commande suivante, afin d’obtenir davantage d’adresses IP (par défaut, swarm ne fournit un réseau qu’avec “256” adresses disponibles) :
1
| docker swarm init --default-addr-pool=10.0.0.0/8 --default-addr-pool-mask-length 16
|
Spring boot
1
| cd docker-compose-only-quarkus-jvm && docker stack deploy quarkus-jvm -c docker-compose.yaml
|
En utilisant swarm, avec 10 répliques, l’application spring boot met 30 secondes à démarrer.
1
| cd docker-compose-only-quarkus-jvm && docker stack deploy quarkus-jvm -c docker-compose.yaml
|
1
2
3
4
5
6
7
8
9
10
11
12
| squale@MacBookPro docker-compose-only-sb % docker service logs employee-sb_employee-sb\
| grep "Started EmployeeApplication" | sed 's/.*\(Started EmployeeApplication.*\).JVM.*/\1/'
Started EmployeeApplication in 29.753 seconds
Started EmployeeApplication in 29.307 seconds
Started EmployeeApplication in 30.299 seconds
Started EmployeeApplication in 30.078 seconds
Started EmployeeApplication in 30.516 seconds
Started EmployeeApplication in 29.641 seconds
Started EmployeeApplication in 29.327 seconds
Started EmployeeApplication in 29.259 seconds
Started EmployeeApplication in 29.304 seconds
Started EmployeeApplication in 28.946 seconds
|
Essayons maintenant avec 20 répliques, en utilisant :
1
| docker service scale employee-sb_employee-sb=0 && docker service scale employee-sb_employee-sb=20
|
Il arrive parfois que l’on dépasse les 400 Mo de RAM au démarrage, ce qui provoque du swapping.
Avec seulement 20 répliques, le temps de démarrage augmente considérablement pour la plupart d’entre elles, ce qu’on ne souhaite évidemment pas voir en environnement de production…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| Started EmployeeApplication in 47.961 seconds
Started EmployeeApplication in 118.761 seconds
Started EmployeeApplication in 39.776 seconds
Started EmployeeApplication in 119.987 seconds
Started EmployeeApplication in 47.934 seconds
Started EmployeeApplication in 80.795 seconds
Started EmployeeApplication in 118.837 seconds
Started EmployeeApplication in 47.437 seconds
Started EmployeeApplication in 115.916 seconds
Started EmployeeApplication in 22.231 seconds
Started EmployeeApplication in 114.372 seconds
Started EmployeeApplication in 123.038 seconds
Started EmployeeApplication in 123.981 seconds
Started EmployeeApplication in 41.729 seconds
Started EmployeeApplication in 57.515 seconds
Started EmployeeApplication in 48.277 seconds
Started EmployeeApplication in 13.333 seconds
Started EmployeeApplication in 121.364 seconds
|
Quarkus-JVM
10 répliques :
1
2
3
4
5
6
7
8
9
10
11
12
| squale@MacBookPro docker-compose-only-quarkus-jvm % docker service logs employee-quarkus-jvm_employee-qk-jvm --since=7m | grep \
started | sed 's/\(.* INFO\).*\(started in .*\)Listening.*/\1 \2/'
employee-quarkus-jvm_employee-qk-jvm.4.c2u7wtsja1qb@docker-desktop | 2020-12-12 15:27:01,502 INFO started in 7.241s.
employee-quarkus-jvm_employee-qk-jvm.6.h2recpnyzlvu@docker-desktop | 2020-12-12 15:27:01,412 INFO started in 7.247s.
employee-quarkus-jvm_employee-qk-jvm.5.ymnsww2n022p@docker-desktop | 2020-12-12 15:26:59,485 INFO started in 6.489s.
employee-quarkus-jvm_employee-qk-jvm.7.hf6awiitarjc@docker-desktop | 2020-12-12 15:27:00,797 INFO started in 7.289s.
employee-quarkus-jvm_employee-qk-jvm.10.o3vh4d1nftgu@docker-desktop | 2020-12-12 15:27:01,530 INFO started in 7.286s.
employee-quarkus-jvm_employee-qk-jvm.1.z0ww963hunpx@docker-desktop | 2020-12-12 15:27:01,339 INFO started in 7.122s.
employee-quarkus-jvm_employee-qk-jvm.9.0j0h3yrvsvgg@docker-desktop | 2020-12-12 15:27:01,466 INFO started in 7.176s.
employee-quarkus-jvm_employee-qk-jvm.3.jyz20e437j45@docker-desktop | 2020-12-12 15:27:01,379 INFO started in 7.326s.
employee-quarkus-jvm_employee-qk-jvm.2.aly4vnfo11wx@docker-desktop | 2020-12-12 15:27:01,321 INFO started in 7.008s.
employee-quarkus-jvm_employee-qk-jvm.8.m562xpxqxqtt@docker-desktop | 2020-12-12 15:27:01,072 INFO started in 7.343s.
|
C’est vraiment mieux (30 secondes en mode Spring Boot contre seulement 7 secondes ici).
En montant à 35 répliques, on observe un temps de démarrage maximal de 25 secondes (contre 120 pour Spring Boot avec 20 répliques) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| squale@MacBookPro docker-compose-only-quarkus-jvm % docker service logs quarkus-jvm_employee-qk-jvm --since=7m \
| grep started \
| sed 's/\(.* INFO\).*\(started in .*\)Listening.*/\1 \2/'
quarkus-jvm_employee-qk-jvm.1.semdukuhnvu6@docker-desktop | 2020-12-14 18:33:10,695 INFO started in 25.324s.
quarkus-jvm_employee-qk-jvm.15.p95ubjzlx8vi@docker-desktop | 2020-12-14 18:33:10,787 INFO started in 24.647s.
quarkus-jvm_employee-qk-jvm.2.0htc1q0jxj9u@docker-desktop | 2020-12-14 18:33:10,718 INFO started in 24.730s.
quarkus-jvm_employee-qk-jvm.3.pzlmns267b5f@docker-desktop | 2020-12-14 18:32:56,025 INFO started in 17.017s.
quarkus-jvm_employee-qk-jvm.28.a4zziyewdf8p@docker-desktop | 2020-12-14 18:33:10,775 INFO started in 24.381s.
quarkus-jvm_employee-qk-jvm.18.unxeyk19uhwg@docker-desktop | 2020-12-14 18:33:10,373 INFO started in 24.689s.
quarkus-jvm_employee-qk-jvm.11.njexuc0ayi83@docker-desktop | 2020-12-14 18:33:10,741 INFO started in 24.647s.
quarkus-jvm_employee-qk-jvm.31.eu171iagolpm@docker-desktop | 2020-12-14 18:33:09,157 INFO started in 24.411s.
quarkus-jvm_employee-qk-jvm.25.n0yasczo1cq1@docker-desktop | 2020-12-14 18:33:10,780 INFO started in 25.022s.
quarkus-jvm_employee-qk-jvm.30.nertg4g44o34@docker-desktop | 2020-12-14 18:33:02,995 INFO started in 22.477s.
quarkus-jvm_employee-qk-jvm.16.aonlyw9qr3nu@docker-desktop | 2020-12-14 18:33:05,927 INFO started in 23.977s.
quarkus-jvm_employee-qk-jvm.6.9l69o023p2wc@docker-desktop | 2020-12-14 18:33:10,667 INFO started in 24.485s.
quarkus-jvm_employee-qk-jvm.12.tfn5xpxafnsd@docker-desktop | 2020-12-14 18:32:44,853 INFO started in 7.269s.
quarkus-jvm_employee-qk-jvm.5.8ersi5p4ff9x@docker-desktop | 2020-12-14 18:33:06,275 INFO started in 23.666s.
quarkus-jvm_employee-qk-jvm.26.ool02pyq151r@docker-desktop | 2020-12-14 18:33:07,140 INFO started in 24.131s.
quarkus-jvm_employee-qk-jvm.27.5gtmbaoib1m1@docker-desktop | 2020-12-14 18:33:10,587 INFO started in 24.580s.
quarkus-jvm_employee-qk-jvm.10.simx2umzdwin@docker-desktop | 2020-12-14 18:33:10,772 INFO started in 25.046s.
quarkus-jvm_employee-qk-jvm.4.xkfaq80a0h92@docker-desktop | 2020-12-14 18:33:10,697 INFO started in 25.105s.
quarkus-jvm_employee-qk-jvm.32.r0h1pm75lfrk@docker-desktop | 2020-12-14 18:33:10,253 INFO started in 24.399s.
quarkus-jvm_employee-qk-jvm.22.v4axe5ceexzt@docker-desktop | 2020-12-14 18:32:53,473 INFO started in 14.764s.
quarkus-jvm_employee-qk-jvm.29.mbzx60idg59u@docker-desktop | 2020-12-14 18:33:06,211 INFO started in 23.889s.
quarkus-jvm_employee-qk-jvm.7.q7qlvt0f4big@docker-desktop | 2020-12-14 18:32:56,848 INFO started in 17.181s.
quarkus-jvm_employee-qk-jvm.8.qmkyu94fascp@docker-desktop | 2020-12-14 18:33:10,739 INFO started in 24.828s.
quarkus-jvm_employee-qk-jvm.23.1qaf0z9751gp@docker-desktop | 2020-12-14 18:32:50,664 INFO started in 12.271s.
quarkus-jvm_employee-qk-jvm.19.ljbf0zmeyfnc@docker-desktop | 2020-12-14 18:33:10,466 INFO started in 24.283s.
quarkus-jvm_employee-qk-jvm.20.w3h66vb0rb0v@docker-desktop | 2020-12-14 18:33:04,855 INFO started in 23.851s.
quarkus-jvm_employee-qk-jvm.9.mfhbv2ebb9rn@docker-desktop | 2020-12-14 18:33:09,142 INFO started in 25.281s.
quarkus-jvm_employee-qk-jvm.34.5zvaark9wtab@docker-desktop | 2020-12-14 18:33:10,673 INFO started in 24.607s.
quarkus-jvm_employee-qk-jvm.17.tfhjnjo4cmva@docker-desktop | 2020-12-14 18:33:06,129 INFO started in 22.958s.
quarkus-jvm_employee-qk-jvm.14.0aq8y160osfz@docker-desktop | 2020-12-14 18:33:09,203 INFO started in 23.630s.
quarkus-jvm_employee-qk-jvm.13.67atlnv9bujo@docker-desktop | 2020-12-14 18:32:44,632 INFO started in 7.028s.
quarkus-jvm_employee-qk-jvm.21.sxrmf38njw35@docker-desktop | 2020-12-14 18:32:48,207 INFO started in 9.868s.
quarkus-jvm_employee-qk-jvm.33.mc9lu3cc3por@docker-desktop | 2020-12-14 18:33:10,105 INFO started in 23.876s.
quarkus-jvm_employee-qk-jvm.35.ewxoosq9xmi8@docker-desktop | 2020-12-14 18:33:08,267 INFO started in 23.841s.
quarkus-jvm_employee-qk-jvm.24.rtr487q4qvvr@docker-desktop | 2020-12-14 18:33:10,171 INFO started in 24.311s.
|
Quarkus-native
1
| cd docker-compose-only-quarkus-scratch && docker stack deploy quarkus-jvm -c docker-compose.yaml
|
10 répliques :
1
2
3
4
5
6
7
8
9
10
11
12
13
| docker service logs employee-native_employee-qk-native --since=3m \
| grep started \
| sed 's/\(.* INFO\).*\(started in .*\)Listening.*/\1 \2/'
employee-native_employee-qk-native.10.x6uri8a5ik3p@docker-desktop | 2020-12-12 14:23:15,134 INFO started in 0.124s.
employee-native_employee-qk-native.3.vy64wrk62ldf@docker-desktop | 2020-12-12 14:23:15,335 INFO started in 0.086s.
employee-native_employee-qk-native.1.ndjkdv71chzw@docker-desktop | 2020-12-12 14:23:14,519 INFO started in 0.108s.
employee-native_employee-qk-native.4.wrs5co0h9mc9@docker-desktop | 2020-12-12 14:23:15,463 INFO started in 0.113s.
employee-native_employee-qk-native.7.nh77c0xuf2ef@docker-desktop | 2020-12-12 14:23:15,014 INFO started in 0.135s.
employee-native_employee-qk-native.9.6zxednmeg1uo@docker-desktop | 2020-12-12 14:23:15,485 INFO started in 0.113s.
employee-native_employee-qk-native.6.99gz13gk1tm3@docker-desktop | 2020-12-12 14:23:15,498 INFO started in 0.085s.
employee-native_employee-qk-native.8.kmiaz9awwpya@docker-desktop | 2020-12-12 14:23:15,615 INFO started in 0.072s.
employee-native_employee-qk-native.2.ymcu092stu7d@docker-desktop | 2020-12-12 14:23:15,504 INFO started in 0.091s.
employee-native_employee-qk-native.5.5y4z5cm27s1q@docker-desktop | 2020-12-12 14:23:15,152 INFO started in 0.111s.
|
Le temps de démarrage maximal est inférieur à 0,2 seconde pour n’importe quelle réplique, c’est excellent !
30 répliques :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| squale@MacBookPro ~ % docker service logs employee-native_employee-qk-native --since=3m | grep \
started | sed 's/\(.* INFO\).*\(started in .*\)Listening.*/\1 \2/'
employee-native_employee-qk-native.1.uh0k4gjec32g@docker-desktop | 2020-12-12 14:20:14,190 INFO started in 0.097s.
employee-native_employee-qk-native.28.k2tzlzr6obg8@docker-desktop | 2020-12-12 14:20:12,589 INFO started in 0.106s.
employee-native_employee-qk-native.24.w6ixdaf0soy1@docker-desktop | 2020-12-12 14:20:11,942 INFO started in 0.169s.
employee-native_employee-qk-native.12.mrfw14vy9f2d@docker-desktop | 2020-12-12 14:20:12,801 INFO started in 0.129s.
employee-native_employee-qk-native.6.p9dq23gridy5@docker-desktop | 2020-12-12 14:20:13,836 INFO started in 0.079s.
employee-native_employee-qk-native.15.hln4kdktrcew@docker-desktop | 2020-12-12 14:20:12,456 INFO started in 0.111s.
employee-native_employee-qk-native.11.wcswliizzt1e@docker-desktop | 2020-12-12 14:20:14,169 INFO started in 0.130s.
employee-native_employee-qk-native.9.jyk39uuaxwsn@docker-desktop | 2020-12-12 14:20:13,668 INFO started in 0.127s.
employee-native_employee-qk-native.4.qag8g796ktxo@docker-desktop | 2020-12-12 14:20:14,190 INFO started in 0.086s.
employee-native_employee-qk-native.13.rcnlwzheks70@docker-desktop | 2020-12-12 14:20:11,468 INFO started in 0.099s.
employee-native_employee-qk-native.21.rphxcs9erl25@docker-desktop | 2020-12-12 14:20:13,093 INFO started in 0.124s.
employee-native_employee-qk-native.14.j9mbc7iro4qk@docker-desktop | 2020-12-12 14:20:13,697 INFO started in 0.101s.
employee-native_employee-qk-native.5.f8949dvikrd0@docker-desktop | 2020-12-12 14:20:14,171 INFO started in 0.105s.
employee-native_employee-qk-native.30.nqrxu4vuem00@docker-desktop | 2020-12-12 14:20:10,600 INFO started in 0.406s.
employee-native_employee-qk-native.29.wfrccji8r9u0@docker-desktop | 2020-12-12 14:20:11,170 INFO started in 0.123s.
employee-native_employee-qk-native.22.ygzx8z6c3tyu@docker-desktop | 2020-12-12 14:20:13,483 INFO started in 0.141s.
employee-native_employee-qk-native.3.kjkshiogn528@docker-desktop | 2020-12-12 14:20:12,695 INFO started in 0.128s.
employee-native_employee-qk-native.20.m6j4cngji78d@docker-desktop | 2020-12-12 14:20:13,818 INFO started in 0.106s.
employee-native_employee-qk-native.18.2o39jw9nxo8h@docker-desktop | 2020-12-12 14:20:14,032 INFO started in 0.110s.
employee-native_employee-qk-native.26.1kbc8i6fv52e@docker-desktop | 2020-12-12 14:20:11,985 INFO started in 0.142s.
employee-native_employee-qk-native.19.v08077shjpws@docker-desktop | 2020-12-12 14:20:13,146 INFO started in 0.173s.
employee-native_employee-qk-native.23.o7xsdu1pf4ha@docker-desktop | 2020-12-12 14:20:14,360 INFO started in 0.087s.
employee-native_employee-qk-native.8.dt5nbq2refcw@docker-desktop | 2020-12-12 14:20:14,334 INFO started in 0.092s.
employee-native_employee-qk-native.10.k797kqpr34y2@docker-desktop | 2020-12-12 14:20:11,859 INFO started in 0.151s.
employee-native_employee-qk-native.17.q33zg6huphiv@docker-desktop | 2020-12-12 14:20:10,853 INFO started in 0.086s.
employee-native_employee-qk-native.25.m9z80na4spus@docker-desktop | 2020-12-12 14:20:13,703 INFO started in 0.147s.
employee-native_employee-qk-native.16.r83i31t10ged@docker-desktop | 2020-12-12 14:20:14,359 INFO started in 0.076s.
employee-native_employee-qk-native.7.4gxm5w00o2rp@docker-desktop | 2020-12-12 14:20:12,792 INFO started in 0.164s.
employee-native_employee-qk-native.27.koxsb6g3w22v@docker-desktop | 2020-12-12 14:20:11,123 INFO started in 0.125s.
employee-native_employee-qk-native.2.97nl6oqe33bm@docker-desktop | 2020-12-12 14:20:12,473 INFO started in 0.112s.
|
Le temps de démarrage maximal est inférieur à 0,3 seconde pour n’importe quel conteneur, c’est également très bon !
Essayons d’être plus agressifs, en montant à 100 répliques !
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
| squale@MacBookPro ~ % docker service logs employee-native_employee-qk-native --since=7m \
| grep started \
| sed 's/\(.* INFO\).*\(started in .*\)Listening.*/\1 \2/'
employee-native_employee-qk-native.10.w82xak0n70pr@docker-desktop | 2020-12-12 14:31:23,642 INFO started in 0.198s.
employee-native_employee-qk-native.16.zfib4ejsy8pm@docker-desktop | 2020-12-12 14:31:26,888 INFO started in 0.179s.
employee-native_employee-qk-native.68.siydkpctmf7k@docker-desktop | 2020-12-12 14:31:20,236 INFO started in 0.156s.
employee-native_employee-qk-native.43.ljykwae0jdu6@docker-desktop | 2020-12-12 14:31:23,503 INFO started in 0.146s.
employee-native_employee-qk-native.62.al69lczqhtuv@docker-desktop | 2020-12-12 14:31:21,796 INFO started in 0.143s.
employee-native_employee-qk-native.48.wbqn1b1swogy@docker-desktop | 2020-12-12 14:31:15,929 INFO started in 0.095s.
employee-native_employee-qk-native.77.obbdg1eren75@docker-desktop | 2020-12-12 14:31:21,551 INFO started in 0.159s.
employee-native_employee-qk-native.78.nfkcsvq9eq5m@docker-desktop | 2020-12-12 14:31:27,648 INFO started in 0.155s.
employee-native_employee-qk-native.99.r28281n6dj83@docker-desktop | 2020-12-12 14:31:24,327 INFO started in 0.086s.
employee-native_employee-qk-native.76.jkpd36g8xv5h@docker-desktop | 2020-12-12 14:31:27,675 INFO started in 0.126s.
employee-native_employee-qk-native.51.w4ftxlzzdocm@docker-desktop | 2020-12-12 14:31:29,148 INFO started in 0.094s.
employee-native_employee-qk-native.81.m2ldpuutosl3@docker-desktop | 2020-12-12 14:31:17,850 INFO started in 0.110s.
employee-native_employee-qk-native.27.s1iz7jctl9gw@docker-desktop | 2020-12-12 14:31:20,710 INFO started in 0.117s.
employee-native_employee-qk-native.1.02pcvk5k3od3@docker-desktop | 2020-12-12 14:31:25,671 INFO started in 0.121s.
employee-native_employee-qk-native.29.zhle156a06tm@docker-desktop | 2020-12-12 14:31:23,638 INFO started in 0.150s.
employee-native_employee-qk-native.82.2pu8hpx7597h@docker-desktop | 2020-12-12 14:31:26,945 INFO started in 0.150s.
employee-native_employee-qk-native.11.kpdlmz5k7t6o@docker-desktop | 2020-12-12 14:31:24,908 INFO started in 0.115s.
employee-native_employee-qk-native.38.wzq968v6t2c3@docker-desktop | 2020-12-12 14:31:21,679 INFO started in 0.157s.
employee-native_employee-qk-native.41.2p5f1uo9qcea@docker-desktop | 2020-12-12 14:31:18,878 INFO started in 0.089s.
employee-native_employee-qk-native.56.h6z7j21zcmwv@docker-desktop | 2020-12-12 14:31:25,721 INFO started in 0.117s.
employee-native_employee-qk-native.45.ozs3tf95afeo@docker-desktop | 2020-12-12 14:31:29,151 INFO started in 0.080s.
employee-native_employee-qk-native.59.57taqxdv0log@docker-desktop | 2020-12-12 14:31:23,944 INFO started in 0.105s.
employee-native_employee-qk-native.20.2ycww39s6anw@docker-desktop | 2020-12-12 14:31:24,717 INFO started in 0.086s.
employee-native_employee-qk-native.80.2qr73f5xldtq@docker-desktop | 2020-12-12 14:31:27,657 INFO started in 0.113s.
employee-native_employee-qk-native.89.liiqqw8aax65@docker-desktop | 2020-12-12 14:31:17,547 INFO started in 0.096s.
employee-native_employee-qk-native.92.z2b8afaq4xfz@docker-desktop | 2020-12-12 14:31:22,691 INFO started in 0.209s.
employee-native_employee-qk-native.25.5qnspf8k8puu@docker-desktop | 2020-12-12 14:31:18,257 INFO started in 0.107s.
employee-native_employee-qk-native.73.a99oqhk9x3fa@docker-desktop | 2020-12-12 14:31:28,367 INFO started in 0.099s.
employee-native_employee-qk-native.47.rkat97ote5yr@docker-desktop | 2020-12-12 14:31:26,935 INFO started in 0.149s.
employee-native_employee-qk-native.6.0gvox8v5phba@docker-desktop | 2020-12-12 14:31:28,678 INFO started in 0.109s.
employee-native_employee-qk-native.83.o8zcyqy2f959@docker-desktop | 2020-12-12 14:31:26,906 INFO started in 0.210s.
employee-native_employee-qk-native.52.uogvu3xeage8@docker-desktop | 2020-12-12 14:31:21,282 INFO started in 0.138s.
employee-native_employee-qk-native.39.twa36dgqpso1@docker-desktop | 2020-12-12 14:31:21,228 INFO started in 0.128s.
employee-native_employee-qk-native.33.w5ledywf2b4c@docker-desktop | 2020-12-12 14:31:23,622 INFO started in 0.227s.
employee-native_employee-qk-native.40.7zodvmc36n5w@docker-desktop | 2020-12-12 14:31:19,714 INFO started in 0.077s.
employee-native_employee-qk-native.18.71oldf7t7eda@docker-desktop | 2020-12-12 14:31:23,532 INFO started in 0.169s.
employee-native_employee-qk-native.9.z8omrepehsul@docker-desktop | 2020-12-12 14:31:28,047 INFO started in 0.124s.
employee-native_employee-qk-native.24.l6aj846xvsjo@docker-desktop | 2020-12-12 14:31:28,785 INFO started in 0.095s.
employee-native_employee-qk-native.31.q0dy28vjqdav@docker-desktop | 2020-12-12 14:31:24,959 INFO started in 0.095s.
employee-native_employee-qk-native.8.5psoe7cnlu8l@docker-desktop | 2020-12-12 14:31:22,673 INFO started in 0.177s.
employee-native_employee-qk-native.64.pgljdiqvgpwc@docker-desktop | 2020-12-12 14:31:21,292 INFO started in 0.139s.
employee-native_employee-qk-native.58.2gcrmszzywjx@docker-desktop | 2020-12-12 14:31:17,858 INFO started in 0.124s.
employee-native_employee-qk-native.85.n50lutqb2z3t@docker-desktop | 2020-12-12 14:31:22,690 INFO started in 0.141s.
employee-native_employee-qk-native.94.za6ipeko10zq@docker-desktop | 2020-12-12 14:31:28,370 INFO started in 0.089s.
employee-native_employee-qk-native.55.vrfwqk9ebegn@docker-desktop | 2020-12-12 14:31:23,123 INFO started in 0.104s.
employee-native_employee-qk-native.7.vazz21hf8je0@docker-desktop | 2020-12-12 14:31:25,689 INFO started in 0.139s.
employee-native_employee-qk-native.17.71t01cp3wmm5@docker-desktop | 2020-12-12 14:31:18,234 INFO started in 0.124s.
employee-native_employee-qk-native.54.dm5bbnz0xgts@docker-desktop | 2020-12-12 14:31:19,340 INFO started in 0.126s.
employee-native_employee-qk-native.65.leyto2rjvh99@docker-desktop | 2020-12-12 14:31:19,324 INFO started in 0.129s.
employee-native_employee-qk-native.66.z5e5x3birtvi@docker-desktop | 2020-12-12 14:31:24,995 INFO started in 0.103s.
employee-native_employee-qk-native.37.gduhx5awz8gi@docker-desktop | 2020-12-12 14:31:29,147 INFO started in 0.086s.
employee-native_employee-qk-native.96.8cemovtvtew2@docker-desktop | 2020-12-12 14:31:24,169 INFO started in 0.104s.
employee-native_employee-qk-native.84.lttvfs7ytj4l@docker-desktop | 2020-12-12 14:31:21,161 INFO started in 0.152s.
employee-native_employee-qk-native.13.hr98xg83onn5@docker-desktop | 2020-12-12 14:31:24,171 INFO started in 0.109s.
employee-native_employee-qk-native.91.yz7n96nf6afr@docker-desktop | 2020-12-12 14:31:22,609 INFO started in 0.127s.
employee-native_employee-qk-native.32.bkaf4t65vdf0@docker-desktop | 2020-12-12 14:31:19,364 INFO started in 0.103s.
employee-native_employee-qk-native.67.ua3dscx1mi4c@docker-desktop | 2020-12-12 14:31:19,395 INFO started in 0.106s.
employee-native_employee-qk-native.60.g080pa4izn56@docker-desktop | 2020-12-12 14:31:21,583 INFO started in 0.187s.
employee-native_employee-qk-native.90.ytpi97tyxdwf@docker-desktop | 2020-12-12 14:31:27,975 INFO started in 0.102s.
employee-native_employee-qk-native.3.x9abreunoglt@docker-desktop | 2020-12-12 14:31:22,029 INFO started in 0.116s.
employee-native_employee-qk-native.63.wondy8ebmdk9@docker-desktop | 2020-12-12 14:31:23,073 INFO started in 0.118s.
employee-native_employee-qk-native.34.q7umcgrxjcul@docker-desktop | 2020-12-12 14:31:24,291 INFO started in 0.097s.
employee-native_employee-qk-native.75.iuer9kpp74o3@docker-desktop | 2020-12-12 14:31:17,908 INFO started in 0.127s.
employee-native_employee-qk-native.42.lmgskaj136ne@docker-desktop | 2020-12-12 14:31:26,107 INFO started in 0.152s.
employee-native_employee-qk-native.70.spyoy11st17e@docker-desktop | 2020-12-12 14:31:16,387 INFO started in 0.091s.
employee-native_employee-qk-native.22.w7g1f6njmjqq@docker-desktop | 2020-12-12 14:31:28,723 INFO started in 0.116s.
employee-native_employee-qk-native.72.xbewp76qqzs1@docker-desktop | 2020-12-12 14:31:21,436 INFO started in 0.155s.
employee-native_employee-qk-native.23.q1ko0fnm9ngi@docker-desktop | 2020-12-12 14:31:28,352 INFO started in 0.093s.
employee-native_employee-qk-native.71.6gkqbup60a2s@docker-desktop | 2020-12-12 14:31:23,627 INFO started in 0.168s.
employee-native_employee-qk-native.19.i6h2gd11h9i1@docker-desktop | 2020-12-12 14:31:21,607 INFO started in 0.219s.
employee-native_employee-qk-native.57.rsqna0ylvm5z@docker-desktop | 2020-12-12 14:31:17,884 INFO started in 0.100s.
employee-native_employee-qk-native.98.phf06msa3o09@docker-desktop | 2020-12-12 14:31:16,127 INFO started in 0.102s.
employee-native_employee-qk-native.12.so6fttuhl8x4@docker-desktop | 2020-12-12 14:31:18,787 INFO started in 0.112s.
employee-native_employee-qk-native.79.e7uwa2rtscbp@docker-desktop | 2020-12-12 14:31:26,871 INFO started in 0.140s.
employee-native_employee-qk-native.5.q9w4rrfp7v4d@docker-desktop | 2020-12-12 14:31:26,122 INFO started in 0.163s.
employee-native_employee-qk-native.95.yrut4opw5jze@docker-desktop | 2020-12-12 14:31:18,874 INFO started in 0.096s.
employee-native_employee-qk-native.35.odm5yf8xrdmg@docker-desktop | 2020-12-12 14:31:22,493 INFO started in 0.148s.
employee-native_employee-qk-native.30.mymcaml3ooac@docker-desktop | 2020-12-12 14:31:17,311 INFO started in 0.100s.
employee-native_employee-qk-native.36.smom7fzlomsp@docker-desktop | 2020-12-12 14:31:12,154 INFO started in 0.092s.
employee-native_employee-qk-native.44.pzwaxa97bu0n@docker-desktop | 2020-12-12 14:31:16,461 INFO started in 0.092s.
employee-native_employee-qk-native.97.cb92uw1698s4@docker-desktop | 2020-12-12 14:31:27,194 INFO started in 0.087s.
employee-native_employee-qk-native.53.r9rsqm2u1n74@docker-desktop | 2020-12-12 14:31:23,174 INFO started in 0.093s.
employee-native_employee-qk-native.86.f8oa7orsx1i9@docker-desktop | 2020-12-12 14:31:19,563 INFO started in 0.078s.
employee-native_employee-qk-native.61.q3fji0j07h7p@docker-desktop | 2020-12-12 14:31:25,958 INFO started in 0.117s.
employee-native_employee-qk-native.50.iwll43m5e7t9@docker-desktop | 2020-12-12 14:31:22,926 INFO started in 0.116s.
employee-native_employee-qk-native.74.cwi99uo73jyy@docker-desktop | 2020-12-12 14:31:21,232 INFO started in 0.173s.
employee-native_employee-qk-native.87.u8gk4iuporyu@docker-desktop | 2020-12-12 14:31:24,564 INFO started in 0.089s.
employee-native_employee-qk-native.28.f483520q35hw@docker-desktop | 2020-12-12 14:31:27,137 INFO started in 0.101s.
employee-native_employee-qk-native.69.o2s62t9mdmak@docker-desktop | 2020-12-12 14:31:22,756 INFO started in 0.127s.
employee-native_employee-qk-native.21.3ngz0qvjy6la@docker-desktop | 2020-12-12 14:31:21,389 INFO started in 0.150s.
employee-native_employee-qk-native.88.4atenqd63p98@docker-desktop | 2020-12-12 14:31:27,454 INFO started in 0.122s.
employee-native_employee-qk-native.46.sa2t94aetij6@docker-desktop | 2020-12-12 14:31:26,861 INFO started in 0.202s.
employee-native_employee-qk-native.4.ugz8tf692vx2@docker-desktop | 2020-12-12 14:31:20,657 INFO started in 0.105s.
employee-native_employee-qk-native.26.rlyb5mfheq0t@docker-desktop | 2020-12-12 14:31:23,914 INFO started in 0.116s.
employee-native_employee-qk-native.49.ckjnax4t7q4p@docker-desktop | 2020-12-12 14:31:23,318 INFO started in 0.112s.
employee-native_employee-qk-native.93.t7kwea02kz6k@docker-desktop | 2020-12-12 14:31:25,945 INFO started in 0.121s.
employee-native_employee-qk-native.15.mrhvtjc98ue7@docker-desktop | 2020-12-12 14:31:18,870 INFO started in 0.108s.
employee-native_employee-qk-native.2.p86v577pwvb9@docker-desktop | 2020-12-12 14:31:23,467 INFO started in 0.186s.
employee-native_employee-qk-native.14.3dd6lp3q2pq8@docker-desktop | 2020-12-12 14:31:17,649 INFO started in 0.081s.
employee-native_employee-qk-native.100.aspbsvgc3ocw@docker-desktop | 2020-12-12 14:31:23,318 INFO started in 0.113s.
|
Le temps de démarrage reste inférieur à 1 seconde (< 0,5 pour le maximum) : cela s’intègre parfaitement dans un monde de conteneurs !
Au-delà de 300 conteneurs, Swarm rencontre des problèmes (probablement liés au réseau, on peut toujours pointer du doigt le réseau) qui le rendent totalement non réactif, nous avons donc limité la montée en charge à 300 conteneurs.
Je ne montre pas les logs pour ce cas, ils sont similaires aux précédents et il y a trop de lignes.
En montant notre service à 300, nous n’avons jamais eu de temps de démarrage supérieur à 0,5s.
Résumé de ce qui a été testé :
| Répliques # | Spring Boot | Quarkus JVM | Quarkus native |
|---|
| 10 | 30s | 7s | 0.135s |
| 20 | 120s | 17s | 0.161s |
| 35 | ∞ | 25s | 0.169s |
| 100 | ∞ | ∞ | 0.227s |
| 300 | ∞ | ∞ | 0.446s |
Comparaisons dans un environnement Kubernetes, avec k3d
Le but de cette partie est de vérifier si Quarkus s’intègre vraiment “parfaitement” dans Kubernetes, et d’observer comment le temps de démarrage peut impacter la disponibilité de votre service.
Nous utilisons l’excellent k3d de Rancher, qui vous fournit un cluster Kubernetes dans docker.
Je vous recommande de lire ce très bon article sur k3d, surtout si vous n’êtes pas familier avec cet outil.
Que va-t-on faire ?
- Mettre en place un cluster Kubernetes avec 5 déploiements :
- Un pour l’application dans sa forme Spring Boot
- Un pour l’application dans sa forme Quarkus avec JVM classique
- Un pour l’application dans sa forme Quarkus avec GraalVM
- Deux bases de données Postgres (une pour Quarkus, l’autre pour Spring Boot)
- Mettre en place 3 pods qui vérifient la disponibilité du service avec un timeout maximal de 5 toutes les 0,2 seconde
- Tuer 1 pod de chaque application toutes les
- 5 secondes dans un script
- 15 dans l’autre
Cela simule le cas où votre application plante toutes les 5 ou 15 secondes. Pour les besoins de la démonstration, je n’ai pas créé de sondes de liveness et de readiness, ce qui est bien sûr une très mauvaise pratique, mais qui n’a pas d’utilité dans notre démonstration. Nous tuons directement le pod, pour rester simple.
Créer, préparer votre cluster k3d
Je recommande vivement d’utiliser k3d en environnement de développement, car il permet de construire très facilement un écosystème Kubernetes.
Un cluster k3d très simple peut être créé avec la commande suivante :
1
| k3d cluster create quarkus-poc --switch-context
|
Il s’agit d’un cluster à un seul nœud, ce qui ne pose pas de problème car c’est suffisant pour cette démonstration.
Comme je ne voulais pas que mon système dépende de registres Docker publics, j’ai utilisé la fonctionnalité d’import d’image de k3d, pour récupérer des images depuis mon registre Docker local et les pousser dans le registre de k3d :
1
| k3d image import quarkus-employee-native:0.0.1-SNAPSHOT-scratch -c quarkus-poc
|
Désormais, mon registre interne k3d contient les images Docker qui ont été importées depuis mon registre local.
Exécuter les déploiements et les services
Le code source est disponible dans le sous-répertoire quarkus-k3d de comparisons. Les scripts de test complets sont disponibles dans ce répertoire.
- create-kill-check.sh
- create-kill-check-slow.sh
Créer les vérificateurs de disponibilité
Comme un CronJob ne peut s’exécuter qu’à une fréquence d’une exécution par minute, ce n’est pas la bonne méthode pour vérifier la disponibilité sur notre cluster.
Comme nous voulons vérifier toutes les secondes, nous créons simplement un Pod chargé de vérifier la disponibilité, nous les exécutons puis les supprimons une fois que le script kill.sh a terminé son travail.
Ces helpers utilisent l’image busybox, avec la commande suivante : une pour Spring Boot, une pour Quarkus avec la JVM standard et une pour Quarkus avec GraalVM :
1
| while(true) do echo "requesting..."; wget -T5 -O- http://qk-jvm-employee:8081/hello ; sleep 0.2; done
|
Tout exécuter ensemble
En utilisant les scripts à la racine du dossier k3d, toutes les étapes ci-dessus s’exécutent et vous montrent un résultat basé sur les logs des vérificateurs de disponibilité.
Pour le premier test, qui prend 5 minutes à s’exécuter, nous déployons 1 réplique de chaque application et détruisons les pods toutes les 15 secondes. Si vous vous souvenez des sections précédentes, vous savez que l’application démarrera :
- en ~10 secondes pour Spring Boot
- en ~3 secondes pour quarkus-jvm
- en moins d'1 seconde pour quarkus-native
Ainsi, avec une destruction toutes les 15 secondes et une vérification toutes les secondes, cela devrait laisser à Spring Boot une chance de redémarrer correctement et de servir les requêtes.
1
2
3
4
| Number of connection refused (i.e. probably the number of seconds in three minute the app has been available since we began to crash it):
Spring-boot: 375 / 762
Quarkus standard JVM: 78 / 675
Quarkus GraalVM: 25 / 762
|
En tuant les pods toutes les 5 secondes, les choses se dégradent un peu pour les runtimes basés sur la JVM.
1
2
3
4
| Number of connection refused (i.e. probably the number of seconds in three minute the app has been available since we began to crash it):
Spring-boot: 202 / 212
Quarkus standard JVM: 46 / 164
Quarkus GraalVM: 22 / 212
|
On peut donc avoir une application instable qui paraît plus stable qu’elle ne l’est réellement pour les utilisateurs, à cause du temps de démarrage, qui est un point clé pour les applications sur Kubernetes.
Taux d’appels échoués parmi les appels attendus dans le tableau ci-dessous :
| Scénario | Spring Boot | Quarkus JVM | Quarkus native |
|---|
| Lent (15s) | 51.2% | 88.4% | 96.7% |
| Rapide (5s) | 0.05% | 72% | 90% |
Il semble que Quarkus soit un bon candidat pour le monde des conteneurs :
- faible consommation de ressources
- efficacité
- temps de démarrage rapide
Conclusion
Cet article démontre que :
- Quarkus nous aide lorsqu’on l’utilise avec un orchestrateur de conteneurs, pour obtenir un comportement stable même lorsque la charge augmente sur notre application.
- Quarkus nous aide à développer plus vite :
- De nombreuses extensions sont là pour vous aider à avoir moins de code répétitif (boilerplate).
- La communauté est très réactive pour vous aider en cas de problème.
- Quarkus est très efficace et ne sera pas aussi gourmand qu’une application Spring Boot (qui était jusqu’ici la meilleure façon de faire beaucoup de choses) :
- Cela vous aidera à réduire le coût de votre infrastructure, puisqu’il nécessite moins de ressources pour accomplir les mêmes tâches qu’une plateforme classique.
- La surface d’attaque est minimaliste lorsqu’on construit l’image à partir de scratch, ce qui est très important puisque les développeurs doivent désormais penser à la sécurité dès la conception de leurs applications (principe du shift-left).
| Spring Boot | Quarkus JVM | Quarkus native |
|---|
| Temps de démarrage | ~10s | ~2s | < 0.1s |
| Temps de build | ~18s | ~20s | ~4m avec GraalVM local & ~6m avec le multistaging |
| Taille de l’image Docker | 237M | 213M | 68.2M> |
| RAM | 386.5M | 205.7M | 15.96M |
| CPU | 0.38% | 0.32% | 0.02% |
| Échecs avec une instance (redémarrage toutes les 60s & vérification chaque seconde) | 19 | 7 | 0 |
| Échecs avec une instance (redémarrage toutes les 20s & vérification chaque seconde) | 99 | 37 | 1 |
| Nombre max de conteneurs en parallèle (8Go de RAM & Swarm) | 20 | 35 | 300 |
| Taux de succès dans kube avec 1 réplique (destruction toutes les 15 secondes & vérification toutes les 0,2 seconde & timeout des requêtes = 5s) | 51,2% | 88,4% | 96,7% |
| Taux de succès dans kube avec 1 réplique (destruction toutes les 5 secondes & vérification toutes les 0,2 seconde & timeout des requêtes = 5s) | 0.05% | 72% | 90% |
La conclusion de cet article sur Quarkus est donc claire :
Concevoir des applications Cloud Native exige flexibilité, efficacité et sécurité. Quarkus aide à écrire ce type d’applications et s’intègre parfaitement dans un monde de conteneurs, en particulier sur Kubernetes, puisque le temps de démarrage, les ressources et la sécurité sont devenus des éléments critiques.
Pour aller plus loin, découvrez notre formation Cloud Native Applications et notre expertise Cloud Native Applications.