Nous connaissons Node.js pour ses performances rapides comme l’éclair. Pourtant, comme avec n’importe quel langage, vous pouvez écrire du code Node.js dont les performances pour vos utilisateurs sont pires que vous ne le souhaiteriez. Pour combattre cela, nous avons besoin de tests de performance adéquats. Aujourd’hui, nous allons couvrir exactement cela avec un regard approfondi sur la façon de mettre en place et d’exécuter un test de performance et d’analyser les résultats afin que vous puissiez faire des applications Node.js rapides comme l’éclair.
La meilleure façon de comprendre comment tester les performances de votre application est de marcher à travers un exemple.
Vous pouvez utiliser Node.js à de nombreuses fins : écrire des scripts pour exécuter des tâches, exécuter un serveur Web ou servir des fichiers statiques, comme un site Web. Aujourd’hui, nous allons parcourir les étapes pour tester une API web HTTP de Node.js. Mais si vous construisez quelque chose d’autre dans Node, ne vous inquiétez pas-beaucoup des principes seront similaires.
- La nature unique des performances de Node.js
- La boucle d’événement
- Les performances de Node.js et la boucle d’événement
- Étape 1 : Choisir l’outillage de test de performance de Node.js
- Étape 2 : Créer un profil de test de performance Node.js
- Tirer parti de plusieurs profils de test
- Répétition de systèmes distribués à grande échelle
- Étape 3 : Configurez votre observabilité/surveillance
- Se mettre en route avec un APM
- Outillage adapté à Node.js
- Étape 4 : créer une infrastructure de test de performance Node.js
- Étape 5 : Exécutez vos tests !
- Maintenant vous avez Node.js rapide comme l’éclair
La nature unique des performances de Node.js
Avant de commencer, jetons un coup d’œil rapide à l’une des caractéristiques les plus uniques des performances de Node.js. Nous aurons besoin d’avoir une connaissance de ces caractéristiques plus tard lorsque nous exécutons nos tests de performance.
De quoi est-ce que je parle ?
La grande considération pour les applications Node.js est leur comportement de single-thread, run-to-completion-facilité par ce qui est connu comme la boucle d’événement. Maintenant, je sais ce que vous pensez : c’est beaucoup. Alors décomposons un peu pour comprendre ce que cela signifie.
Débutons avec le single threading. Le threading, en tant que concept, permet le traitement simultané dans une application. Node.js n’a pas cette capacité, du moins pas dans le sens traditionnel. Au lieu de cela, pour écrire des applications qui effectuent plusieurs tâches à la fois, nous avons le code asynchrone et la boucle d’événement.
La boucle d’événement
Qu’est-ce que la boucle d’événement ?
La boucle d’événement est la façon dont Node.js décompose les processus à long terme en petits morceaux. Il fonctionne comme un battement de cœur : Toutes les quelques millisecondes, Node.js va vérifier une file d’attente de travail pour démarrer de nouvelles tâches. S’il y a du travail, il les amènera sur la pile d’appels et les exécutera jusqu’à leur achèvement (nous parlerons bientôt de l’exécution jusqu’à l’achèvement).
En décomposant les tâches, Node.js peut faire du multitâche, ce qui est votre substitut du threading. Cela signifie que pendant qu’une tâche attend, une autre peut démarrer. Donc, plutôt que le threading, nous utilisons du code asynchrone, facilité par des styles de programmation comme les callbacks, les promesses et async/await. La plupart des API Node prêtes à l’emploi ont à la fois une méthode d’exécution synchrone et asynchrone.
Ok, alors peut-être vous demandez-vous : qu’est-ce que tout ce techno-jargon a à voir avec les performances ?
Laissez-moi vous expliquer…
Les performances de Node.js et la boucle d’événement
Imaginez que vous construisez une application Node.js avec deux points de terminaison : un pour le téléchargement de fichiers, et un qui récupère un profil d’utilisateur. L’API de profil d’utilisateur sera probablement demandée beaucoup plus souvent que le téléchargement de fichiers, et si elle ne répond pas assez rapidement, elle bloquera chaque chargement de page pour chaque utilisateur – ce qui n’est pas bon.
L’API de téléchargement d’utilisateur est utilisée peu fréquemment. De plus, les utilisateurs s’attendent à ce que le téléchargement des tâches prenne du temps, mais ils sont beaucoup moins indulgents avec les temps de chargement des pages. Si nous ne programmons pas avec la boucle d’événement à l’esprit, pendant que le fichier est en cours de téléchargement, Node.js pourrait finir par accaparer toutes les ressources du système et pourrait bloquer les autres utilisateurs d’utiliser votre application-uh-oh!
Et c’est pourquoi vous devez comprendre la nature single-threaded de Node.js. Lorsque nous modifions notre application, nous devons tenir compte de ce comportement. Nous voulons éviter de faire des tâches à long terme de manière synchrone, comme faire des demandes de réseau, écrire des fichiers, ou effectuer un calcul lourd.
Maintenant que nous connaissons la nature single-threaded de Node.js, nous pouvons l’utiliser à notre avantage. Allons étape par étape comment vous pouvez mettre en place, exécuter et analyser un test de performance de votre application Node.js pour vous assurer que vous faites de votre mieux pour tirer parti des capacités de performance de Node.js.
Étape 1 : Choisir l’outillage de test de performance de Node.js
D’abord, vous voudrez choisir un outil qui vous permettra d’exécuter vos tests de performance. Il existe de nombreux outils, tous avec des avantages et des inconvénients différents pour le réglage des performances de Node.js. Une chose principale à considérer est que même si vous testez une application Node.js, si vous allez tester les performances depuis le monde extérieur à travers un réseau, il n’est pas important que votre outillage de test de performance soit écrit en Node.js.
Pour les tests de performance HTTP de base, j’aime Artillery un outil de test de performance simple écrit en Node.js. Il est également particulièrement bon pour exécuter des tests de performance pour les demandes d’API. Artillery fonctionne en écrivant un fichier de configuration qui définit votre profil de charge. Vous indiquez à Artillery quels endpoints vous voulez demander, à quel rythme, pour quelle durée, etc.
Un script de test de base ressemble à ceci:
config: target: 'https://artillery.io' phases: - duration: 60 arrivalRate: 20 defaults: headers: x-my-service-auth: '987401838271002188298567'scenarios:- flow:- get:url: "/docs"
Ici, vous demandez le site Web d’Artillery pour une durée de 60 secondes avec 20 nouveaux utilisateurs arrivant à l’URL.
Puis, pour exécuter le test, il suffit d’exécuter :
artillery run your_config.yml
Artillery fera autant de requêtes à votre application que vous lui avez demandé. Ceci est utile pour construire des profils de test de performance qui imitent votre environnement de production. Qu’est-ce que j’entends par profil de test de performance ? Couvrons cela maintenant.
Étape 2 : Créer un profil de test de performance Node.js
Un profil de test de performance, comme ci-dessus, est une définition de la façon dont votre test de performance s’exécutera. Vous voudrez imiter la façon dont votre trafic de production se comporte ou est censé se comporter, si possible, pour effectuer un réglage précis des performances de Node.js. Par exemple, si vous construisez un site Web d’événements, vous vous attendez à un trafic important au moment de la mise en vente des billets, vous voudrez donc construire un profil qui imite ce comportement. Vous voudrez tester la capacité de votre application à s’adapter à de grandes quantités de charge en un court laps de temps. Par ailleurs, si vous exploitez un site de commerce électronique, vous pouvez vous attendre à un trafic régulier. Ici, vos profils de test de performance devraient refléter ce comportement.
Tirer parti de plusieurs profils de test
Un point amusant et intéressant à noter est que vous pouvez créer différents profils de test et les exécuter de manière superposée. Par exemple, vous pouvez créer un profil qui imite votre niveau de base de trafic – disons 100 demandes par minute – et ensuite imiter ce qui pourrait se produire si vous voyiez beaucoup de trafic sur votre site, disons si vous mettez des annonces dans les moteurs de recherche. Tester plusieurs scénarios est important pour un réglage approfondi des performances de Node.js.
Répétition de systèmes distribués à grande échelle
Je dois prendre une seconde ici pour noter quelque chose : lorsqu’une application atteint une certaine taille, mimer la charge de cette manière perd de sa faisabilité. Les volumes de trafic que vous pourriez avoir pourraient être si sauvages, imprévisibles ou importants en volume qu’il est difficile de créer une façon réaliste et semblable de tester votre application avant sa sortie.
Mais que faire si c’est le cas ? Que faisons-nous ? Nous testons en production.
Vous pourriez penser, « Woah, attendez ! Ne sommes-nous pas censés tester avant la mise en production ? »
Vous pouvez, mais quand un système atteint une certaine taille, il peut être judicieux de tirer parti de différentes stratégies de test de performance. Vous pouvez tirer parti de concepts comme la mise en liberté canari pour mettre vos changements en production et les tester uniquement avec un certain pourcentage d’utilisateurs. Si vous constatez une baisse des performances, vous pouvez renvoyer ce trafic à la mise en œuvre précédente. Ce processus encourage vraiment l’expérimentation, et la meilleure partie est que vous testez sur votre application de production réelle, donc pas d’inquiétude sur le fait que les résultats des tests ne reproduisent pas la production.
Jusqu’à présent, nous avons décidé de notre outillage, et nous avons créé des profils qui recréent notre production, comme le trafic et les charges de travail. Que faisons-nous ensuite ? Nous devons nous assurer que nous avons les données dont nous avons besoin pour analyser notre application, et nous le faisons grâce à la surveillance des performances de Node.js et aux outils de gestion des performances des applications (APM). Qu’est-ce qu’un APM ? Lisez la suite, et je vous le dirai !
Étape 3 : Configurez votre observabilité/surveillance
Nous ne voulons pas simplement exécuter notre test de performance contre notre application et espérer et prier. Si nous le faisons, nous ne serons pas en mesure de comprendre comment elle se comporte et si elle fait ce que nous pensons qu’elle devrait faire. Avant de commencer, nous devons donc nous poser des questions telles que : « Pour mon application, qu’est-ce qui est bon ? Quels sont mes SLA et mes KPI ? Quelles sont les métriques nécessaires pour déboguer efficacement un problème de performance ? »
Si votre application fonctionne lentement, ou différemment de ce que vous attendiez, vous aurez besoin de données pour comprendre pourquoi afin de l’améliorer. Toutes les applications de production dignes de ce nom utilisent une certaine forme d’observabilité et/ou de solution de surveillance. Ces outils, souvent appelés APM, vous permettent de visualiser les métriques de performance critiques de Node.js sur votre application en cours d’exécution.
Se mettre en route avec un APM
Les APM se présentent sous différentes formes et tailles, toutes avec différentes fonctionnalités, étiquettes de prix, implications de sécurité, performances, vous l’appelez. Il est payant de magasiner un peu pour trouver le meilleur outil pour vos besoins. Ce sont ces outils qui vont nous donner les aperçus et les données dont nous avons besoin lorsque nous exécutons nos tests de performance Node.js.
Alors, si nous savons que nous devrions surveiller notre application – que devrions-nous surveiller exactement ?
Idéalement, vous voulez autant de données que possible – mais autant que nous aimons les données ; nous devons être réalistes quant à l’endroit où commencer ! Le meilleur endroit pour commencer est les trois domaines suivants :
- Journaux agrégés-Les journaux d’application sont émis soit implicitement par certaines bibliothèques, soit explicitement par un développeur pour avoir un aperçu d’une application. La plupart des outils de journaux agrégés vous permettent de rechercher et de visualiser facilement vos données journalisées. Dans notre cas, nous pourrions journaliser les performances de chacune de nos API et les tracer sur un graphique.
- Insights sur l’infrastructure-Votre application s’exécutera sur un hôte de toutes sortes, donc vous voudrez probablement voir toutes les données. Si vous vous exécutez dans le cloud, la plupart des fournisseurs vous donnent ces données (bien que sous une forme grossière) dès la boîte. Les données que vous obtiendrez de ces outils couvriront des choses comme l’utilisation du CPU et de la mémoire de votre hôte, les données de connexion, etc.
- Surveillance des applications – Ce type d’outil se trouve généralement dans le code de votre application et peut tirer des indications sur la façon dont les fonctions s’exécutent / sont appelées, quelles erreurs nous jetons, etc.
Certains outils APM, comme Retrace, ont toutes ou la plupart de ces trois fonctionnalités réunies en une seule, tandis que d’autres peuvent être plus spécialisés. Selon vos besoins, vous pourriez vouloir un outil qui fait tout ou toute une gamme d’outils pour différents objectifs.
Outillage adapté à Node.js
En plus des outils, nous pouvons également inclure d’autres outils et profilers spécifiques à Node.js, comme les graphiques de flamme, qui examinent l’exécution de notre fonction ou extraient des données sur l’exécution de notre boucle d’événement. Au fur et à mesure que vous vous familiariserez avec les tests de performance Node.js, vos besoins en données ne feront qu’augmenter. Vous voudrez continuer à magasiner, à expérimenter et à mettre à jour votre outillage pour vraiment comprendre votre application.
Maintenant que nous avons configuré notre outillage, obtenu des profils réalistes pour notre performance et compris la performance de notre application, nous sommes presque prêts à exécuter nos tests. Mais avant cela, il y a encore une étape : créer une infrastructure de test.
Étape 4 : créer une infrastructure de test de performance Node.js
Vous pouvez exécuter des tests de performance à partir de votre propre machine si vous le souhaitez, mais cela pose des problèmes. Jusqu’à présent, nous avons essayé très fort – avec nos profils de test, par exemple – pour nous assurer que nos tests de performance se répliquent. Un autre facteur de réplication de nos tests est de s’assurer que nous les exécutons toujours sur la même infrastructure (lire : machine).
L’une des façons les plus simples d’obtenir une infrastructure de test cohérente est de tirer parti de l’hébergement en nuage. Choisissez un hôte/machine à partir duquel vous voulez lancer vos tests et assurez-vous que chaque fois que vous exécutez vos tests, c’est toujours à partir de la même machine – et de préférence à partir du même emplacement, aussi – pour éviter de fausser vos données en fonction de la latence des requêtes.
C’est une bonne idée de scripter cette infrastructure, de sorte que vous puissiez la créer et la démonter selon les besoins. On appelle cette idée « infrastructure as code ». La plupart des fournisseurs de cloud le prennent en charge de manière native, ou vous pouvez utiliser un outil comme Terraform pour vous aider.
Phew ! Nous avons couvert beaucoup de terrain jusqu’ici, et nous en sommes à la dernière étape : l’exécution de nos tests.
Étape 5 : Exécutez vos tests !
La dernière étape consiste à exécuter réellement nos tests. Si nous lançons notre configuration en ligne de commande (comme nous l’avons fait à l’étape 1), nous verrons des requêtes vers notre application Node.js. Avec notre solution de surveillance, nous pouvons vérifier comment notre boucle d’événements se comporte, si certaines requêtes prennent plus de temps que d’autres, si les connexions se terminent, etc.
La cerise sur le gâteau pour vos tests de performance est d’envisager de les mettre dans votre pipeline de construction et de test. Une façon de le faire est d’exécuter vos tests de performance pendant la nuit afin que vous puissiez les examiner chaque matin. Artillery fournit un moyen agréable et simple de créer ces rapports, qui peuvent vous aider à repérer toute régression des performances de Node.js.
Maintenant vous avez Node.js rapide comme l’éclair
C’est un enveloppement.
Aujourd’hui, nous avons couvert la pertinence de la boucle d’événement pour la performance de votre application JavaScript, comment choisir votre outil de test de performance, comment configurer des profils de test de performance cohérents avec Artillery, quelle surveillance vous voudrez mettre en place pour diagnostiquer les problèmes de performance de Node.js, et, enfin, comment et quand exécuter vos tests de performance pour en tirer le maximum de valeur pour vous et votre équipe.
Expérimentez les outils de surveillance, comme Retrace APM pour Node.js, effectuez de petits changements afin de pouvoir tester l’impact des changements, et examinez fréquemment vos rapports de test afin de pouvoir repérer les régressions. Vous avez maintenant tout ce dont vous avez besoin pour tirer parti des capacités de performance de Node.js et écrire une application super performante que vos utilisateurs adorent !
.