Node, en tant que moteur d'exécution pour Javascript côté serveur, enrichit considérablement les scénarios d'application de Javascript.
Cependant, le runtime Node.js lui-même est une boîte noire. Nous ne pouvons pas percevoir l'état du runtime et il est difficile de reproduire les problèmes en ligne.
Par conséquent, la surveillance des performances est la pierre angulaire du « fonctionnement normal » des applications Node.js. Non seulement divers indicateurs d’exécution peuvent être surveillés à tout moment, mais cela peut également aider à résoudre des problèmes de scénarios anormaux.
La surveillance des performancespeut être divisée en deux parties :
collecte et affichage des indicateurs de performances
capture et analyse des données de performances
telles que QPS, HTTP lent, journaux de liaison de traitement métier, etc.Dans l'image ci-dessus, vous pouvez voir les avantages et les inconvénients des trois solutions actuelles de surveillance des performances Node.js. Voici une brève introduction à la composition de ces trois solutions :
Prometheus
AliNode en boucle fermée.
Alinode est un environnement d'exécution étendu compatible avec Nodejs officiel, fournissant quelques fonctions supplémentaires :
agenthub est un processus résident utilisé pour collecter des indicateurs de performance et signalez-les.
forment une boucle fermée à partir de la surveillance, de l'affichage, de l'instantané et de l'analyse. L'accès est pratique et simple, mais il existe toujours des risques lors de l'extension du runtime d'
Easy-Monitor
Node.js Addon
pour implémenter l'Les données de consommation de temps CPU du processus actuel peuvent être obtenues via process.cpuUsage()
L'unité de la valeur de retour est la microseconde
Les données d'allocation de mémoire du processus actuel peuvent être obtenues via process.memoryUsage()
. L'unité de la valeur de retour est l'octet
Comme le montre la figure ci-dessus, rss
comprend le segment de code ( Code Segment
), la mémoire de pile ( Stack
) et la mémoire de tas ( Heap
peuvent obtenir des données d'analyse de la mémoire du tas v8 et de l'espace du tas via v8.getHeapStatistics()
et v8.getHeapSpaceStatistics()
La figure suivante montre la distribution de la composition de la mémoire du tas de la v8 :
L'espace mémoire du tas est d'abord divisé en espaces, et l'espace est divisé en pages. La mémoire est paginée selon un alignement de 1 Mo.
Nouvel espace : Espace de nouvelle génération, utilisé pour stocker certaines données d'objets avec un cycle de vie relativement court, divisé en deux espaces (le type d'espace est semi space
) : from space
to space
Ancien Espace : l'espace d'ancienne génération, utilisé pour stocker les objets promus par New Space
Code Space : stocke le code exécutable compilé par v8 JIT.
Map Space : stocke l'objet pointeur de la classe cachée pointée par Object. v8 selon le moteur d'exécution. La structure de présentation des objets est utilisée pour accéder rapidement aux membres des objets.
Grand espace d'objet : utilisé pour stocker les objets de plus de 1 Mo qui ne peuvent pas être alloués aux pages.
L'algorithme de récupération de place de
Mark-Sweep-Compact
. GC mineur pour le recyclage d'objets dans l'ancienne générationScavenge
est utilisé pour recycler les objets dans la nouvelle générationPrémisse : New space
est divisé en deux espaces d'objets : from
et to
Synchronisation du déclenchement : lorsque New space
est plein.
Étapes :
dans from space
, effectuez une traversée en largeur
et constatez que l'objet survivant (accessible)
Old space
et àto space
Lorsque la copie se termine, il ne reste que les objets survivants dans to space
, from space
est vidé,
l'échange from space
et to space
est lancé, et le prochain cycle Scavenge
commence.
est adapté à un recyclage fréquent et à une mémoire insuffisante. Pour les objets volumineux, la stratégie espace-temps typique a l'inconvénient de gaspiller deux fois plus d'espace que
Trois étapes : marquage, dégagement et organisation
. Chronométrage du déclenchement : lorsque Old space
est plein.
Étapes :
Marquage (méthode de marquage tricolore)
marking queue
(pile explicite), et marquez ces objets en gris.pop
l'objet de marking queue
et marquez-le en noir.push
vers marking queue
Un balayage
.
Old space
, de sorte que l'espace libéré soit continu et complet.Lorsque la v8 effectue initialement un garbage collection, elle doit arrêter le programme, analyser l'intégralité du tas et récupérer la mémoire avant de réexécuter le programme. Ce comportement est appelé pause complète ( Stop-The-World
).
Bien que les objets actifs de la nouvelle génération soient petits et fréquemment recyclés, un arrêt complet a peu d'impact. Cependant, les objets survivants de l'ancienne génération sont nombreux et volumineux. et les pauses causées par le marquage, le nettoyage, le tri, etc. Ce sera plus grave.
Ce concept ressemble en fait un peu à l'architecture Fibre du framework React. Ce n'est que pendant le temps libre du navigateur qu'il parcourra l'arbre Fibre pour effectuer les tâches correspondantes, sinon l'exécution sera retardée, affectant le moins possible les tâches du thread principal. , en évitant les retards des applications et en améliorant les performances des applications.
Parce que la v8 a une limite par défaut sur l'espace des nouvelles et anciennes générations.
New space
par défaut : 32 M pour les systèmes 64 bits et 16 M pour les systèmes 32 bits.Old space
par défaut : 1400 M pour les systèmes 64 bits et. 700M pour les systèmes 32 bits.Par conséquent, node
Deux paramètres sont fournis pour ajuster la limite d'espace supérieure des nouvelles et anciennes générations
--max-semi-space-size
: Définir la valeur maximale de l' New Space
Space--max-old-space-size
: Définit la valeur maximale de Old Space
spacenode
de journal GC propose également trois façons d'afficher les journaux GC :
--trace_gc
: Une ligne de journal décrit brièvement l'heure, le type, les changements de taille de tas et les causes de chaque GC--trace_gc_verbose
: affiche chaque tas V8 après chaque GC État détaillé de l'espace--trace_gc_nvp
: informations détaillées sur la paire clé-valeur de chaque GC, y compris le type de GC, le temps de pause, les modifications de mémoire, etc.Étant donné que le journal GC est relativement primitif et nécessite
traitement secondaire, vous pouvez utiliser v8-gc- développé par l'équipe AliNode. L'd'analyseur de journaux
prend un instantané de la mémoire tas d'un programme en cours d'exécution et peut être utilisé pour analyser la consommation de mémoire et modifier
des fichiers Heapsnapshot .heapsnapshot
être généré des manières suivantes :
en utilisant heapdump
Utilisation du profil de tas de la v8
v8.getHeapSnapshot()
fournie par le module v8 intégré de nodejs
v8.writeHeapSnapshot(fileName)
Utilisation de v8-profiler-next
.heapsnapshot
être téléchargé en mémoire sur la barre d'outils des outils de développement Chrome, et les résultats seront affichés comme indiqué ci-dessous :
La vue par défaut est Summary
. Ici, nous devons faire attention aux deux colonnes les plus à droite : Shallow Size
et Retained Size
Size
Retained Size
Shallow Size
la taille de l'objet lui-même alloué dans la mémoire tas v8.Shallow Size
de tous les objets référencés de l'objet.Lorsqu'il s'avère que Retained Size
est particulièrement grande, il peut y avoir une fuite de mémoire à l'intérieur de l'objet. Vous pouvez développer davantage pour localiser le problème
Comparison
Analysez les instantanés de tas de deux périodes différentes. La colonne Delta
peut être utilisée pour filtrer les objets présentant les changements de mémoire les plus importants.
effectue un échantillonnage instantané du CPU exécutant le programme, qui peut être utilisé pour analyser le temps CPU et la proportion.
Il existe plusieurs façons de générer un fichier .cpuprofile
:
Il s'agit d'une collection d'échantillons de profil de processeur de 5 minutes
Le fichier .cpuprofile
généré Javascript Profiler
La vue par défaut est la vue Heavy
. Ici nous voyons deux colonnes : Self Time
et Total Time
Time
Total Time
: représente le temps d'exécution de cette fonction (y compris les autres)Self Time
Total Time
Self Time
un calcul gourmand en CPU qui prend beaucoup de temps. Vous pouvez également effectuer un dépannage supplémentaire.
l'application se bloque et se termine de manière inattendue. le système l'enregistrera automatiquement. Le processus plante les informations d'allocation de mémoire, le compteur de programme et le pointeur de pile et d'autres informations clés à ce moment-là pour générer
. Trois méthodes pour générer des fichiers .core
:
ulimit -c unlimited
ouvre la limite du noyau.node --abort-on-uncaught-exception
L'ajout de ce paramètre au démarrage du noeud peut générer un fichier core lorsqu'une exception non capturée se produit dans l'applicationgcore <pid>
Générer manuellement.Après avoir obtenu le fichier .core
, analysez. le diagnostic peut être réalisé grâce à des outils tels que mdb, gdb, lldb, etc. La cause réelle du crash du processus
llnode `which node` -c /path/to/core/dump
Lors de la surveillance, on peut observer que la mémoire du tas continue d'augmenter, des instantanés du tas sont donc nécessaires pour le dépannage
Grâce au heapsnapshot
nous pouvons analyser et découvrir qu'il existe un objet newThing
qui a toujours conservé une mémoire relativement grande
unused
theThing
newThing
. Les cas replaceThing
causés par des fermetures.
Les fuites de mémoire courantes incluent les situations suivantes :
Par conséquent, dans les situations ci-dessus, vous devez soigneusement déterminer si l'objet en mémoire sera automatiquement recyclé. ne soit pas automatiquement recyclé, vous devez effectuer un recyclage manuel, comme la définition manuelle des objets sur null
, la suppression des minuteries, la dissociation des écouteurs d'événements, etc.
cet article. Cet article a donné une introduction détaillée à l'ensemble du système de surveillance des performances de Node.js.
Premièrement, il présente les problèmes résolus par la surveillance des performances, ses composants et une comparaison des avantages et des inconvénients des solutions traditionnelles.
Ensuite, les deux principales parties des indicateurs de performances et des outils d'instantanés sont présentées en détail.
Enfin, un cas simple de fuite de mémoire est reproduit à partir de l'observation, de l'analyse et du dépannage, et les situations et solutions courantes de fuite de mémoire sont résumées.
J'espère que cet article pourra aider tout le monde à comprendre l'ensemble du système de surveillance des performances de Node.js.