Dans les environnements de production, nous rencontrons parfois des anomalies détectées via les journaux d'exécution. Dans ces situations, il n'est pas toujours possible d'utiliser Visual Studio pour debugger à distance, et les informations des journaux ne reflètent pas toujours l'état exact des objets en mémoire. Par exemple, nous pourrions vouloir examiner l'état de toutes les connnexions Socket ou les informations de routage des services.
C'est-à-dire : Comment analyser les objets mémoire dans l'environnement .NET ?
Aujourd'hui, nous présentons un outil essentiel pour les développeurs .NET avancés : Windbg, qui permet d'analyser l'état des objets en mémoire.
Prenons un cas concret pour illustrer cette approche, ce qui rendra l'application plus pratique et pertinente.
Scénario métier : Dans une architecture distribuée, chaque processus de service conteneurise les informations de connexion Socket des divers services, facilitant ainsi les communications inter-services pendant l'exécution. Cependant, le réseau peut connaître des instabilités occasionnelles. Durant ces micro-coupures, de nombreuses connexions Socket sont interompues, et les appelants de service reçoivent des exceptions indiquant que la connexion est rompue.
Comment identifier rapidement quelles connexions Socket sont interrompues ? À quels serveurs et ports ces connexions étaient-elles établies ? Ces informations nous aident à analyser les problèmes réseau spécifiques et à mettre en place des mécanismes de compensation dans le code, comme la reconstruction des connexions. L'objectif : maintenir la haute disponibilité de l'appilcation !
Présentons donc notre outil principal pour aujourd'hui : Windbg. Voici la description officielle de Microsoft :
Plus précisément, nous devons capturer un instantané mémoire d'un processus spécifique, puis utiliser Windbg pour analyser l'état de divers objets, threads, files d'attente de finalisation, tas, tranches de temps du CPU, etc.
Par conséquent, la première étape consiste à capturer un fichier Full Dump (image mémoire) du processus que nous souhaitons analyser.
Gestionnaire des tâches -> Sélectionner le processus -> Créer un fichier de vidange
Le système enregistrera le fichier Dump dans un répertoire spécifique, que nous devons copier pour une utilisation ultérieure.
Deuxième étape : Télécharger et installer Windbg depuis :
https://developer.microsoft.com/en-us/windows/hardware/download-windbg
Sélectionnez X86 ou X64 en fonction de l'architecture de votre système d'exploitation. Ici, nous utilisons un système d'exploitation 64 bits, donc nous choisissons Windbg (X64).
Troisième étape : Appuyez sur Ctrl+D pour ouvrir le fichier Dump que vous venez de capturer
Quatrième étape : Charger la bibliothèque SOS.dll pour le débogage : .loadby sos clr
.loadby sos clr
Cinquième étape : Examiner les objets d'un type spécifique en mémoire :
!dumpheap -Type ConnexionReseau
Ici, ConnexionReseau est le type spécifique que nous voulons examiner. Pour vérifier l'état des connexions Socket, nous utilisons le type ConnexionReseau.
L'en-tête indique que MT=Table de méthodes (Method Table)
Nous devons utiliser le MT suivant : 00007ffafe50d700
Sixième étape : Afficher les adresses de tous les objets ConnexionReseau en mémoire :
!dumpheap -mt 00007ffafe50d700
Dans les résultats, la première colonne correspond à l'adresse mémoire d'un objet ConnexionReseau.
À ce stade, nous pouvons utiliser la commande suivante pour examiner aléatoirement les informations d'un objet ConnexionReseau :
!do 000001b2d188ae00
!do signifie : !dumpObj
Cependant, avec des centaines d'objets ConnexionReseau, examiner chacun individuellement serait fastidieux ! Bien sûr, nous ne procéderions pas ainsi. Windbg dispose de la commande .foreach
Dans la documentation Debugging help.chm, .foreach fournit un exemple :
.foreach /f ( place "g:\\myfile.txt") { dds place }
C'est-à-dire parcourir en boucle un fichier texte et exécuter une commande pour chaque ligne.
Revenons à notre sortie précédente : la liste des adresses de chaque objet ConnexionReseau. Nous la copions, puis utilisons un éditeur de texte pour extraire uniquement la première colonne (les adresses ConnexionReseau) et la sauvegardons dans un fichier nommé 1.txt.
Septième étape : Parcourir en boucle chaque objet en mémoire
.foreach /f (adr "C:\\1.txt") {!do adr}
La sortie :
Copiez toutes les sorties dans un éditeur de texte, puis recherchez les propriétés spécifiques, par exemple m_EstConnecte=0, pour identifier les objets ConnexionReseau dont la connexion est rompue. Ensuite, utilisez !gcroot pour examiner les relations de référence de cet objet, puis examinez progressivement les informations de chaque objet référencé pour effectuer une analyse approfondie.
Voici le processus complet d'analyse des objets mémoire .NET, partagé avec vous.