Rumah > hujung hadapan web > tutorial js > Menjejaki penggunaan memori yang tinggi dalam Node.js

Menjejaki penggunaan memori yang tinggi dalam Node.js

Patricia Arquette
Lepaskan: 2024-12-17 00:40:25
asal
867 orang telah melayarinya

Dalam artikel ini, saya akan berkongsi pendekatan saya untuk menjejak dan membetulkan penggunaan memori yang tinggi dalam Node.js.

kandungan

  • Konteks
  • Pendekatan
    • Fahami kod
    • Replikasi isu secara berasingan
    • Tangkap profil daripada perkhidmatan pementasan
    • Sahkan pembetulan
  • Keputusan
  • Kesimpulan

Konteks

Baru-baru ini saya mendapat tiket dengan tajuk "baiki isu kebocoran memori di perpustakaan x". Penerangan termasuk papan pemuka Datadog yang menunjukkan sedozen perkhidmatan yang mengalami penggunaan memori yang tinggi dan akhirnya ranap dengan ralat OOM (kehabisan ingatan), dan semuanya mempunyai perpustakaan x yang sama.

Saya telah diperkenalkan baru-baru ini kepada pangkalan kod (<2 minggu) yang menjadikan tugasan itu mencabar dan juga bernilai dikongsi.

Saya mula bekerja dengan dua maklumat:

  • Terdapat perpustakaan yang digunakan oleh semua perkhidmatan yang menyebabkan penggunaan memori yang tinggi dan ia melibatkan redis (redis dimasukkan dalam nama perpustakaan).
  • Senarai perkhidmatan yang terjejas.

Di bawah ialah papan pemuka yang dipautkan ke tiket:

Tracking down high memory usage in Node.js

Perkhidmatan sedang berjalan pada Kubernetes dan jelas sekali bahawa perkhidmatan mengumpul memori dari semasa ke semasa sehingga mereka mencapai had memori, ranap (menuntut semula ingatan) dan bermula semula.

Pendekatan

Dalam bahagian ini, saya akan berkongsi cara saya menangani tugasan yang sedang dijalankan, mengenal pasti punca penggunaan memori yang tinggi dan kemudian membetulkannya.

Fahami kod

Memandangkan saya masih baru dalam pangkalan kod, saya mula-mula ingin memahami kod, perkara yang dilakukan oleh perpustakaan berkenaan dan cara ia sepatutnya digunakan, dengan harapan dengan proses ini lebih mudah untuk mengenal pasti masalah. Malangnya, tiada dokumentasi yang betul tetapi daripada membaca kod dan mencari cara perkhidmatan menggunakan perpustakaan, saya dapat memahami intipatinya. Ia adalah perpustakaan yang melilit aliran redis dan mendedahkan antara muka yang mudah untuk pengeluaran dan penggunaan acara. Selepas menghabiskan satu setengah hari membaca kod, saya tidak dapat memahami semua butiran dan cara data mengalir disebabkan oleh struktur dan kerumitan kod (banyak warisan kelas dan rxjs yang saya tidak biasa).

Jadi saya memutuskan untuk berhenti membaca dan cuba mengesan masalah sambil memerhati kod dalam tindakan dan mengumpul data telemetri.

Tiru isu secara berasingan

Memandangkan tiada data pemprofilan tersedia (cth. pemprofilan berterusan) yang akan membantu saya menyiasat lebih lanjut, saya memutuskan untuk meniru isu tersebut secara setempat dan cuba menangkap profil memori.

Saya menemui beberapa cara untuk menangkap profil memori dalam Node.js:

  • Menggunakan Gambar Timbunan
  • Menggunakan Heap Profiler
  • JavaScript Pemprofilan Prestasi
  • Clinic.js

Tanpa petunjuk tentang tempat untuk mencari, saya memutuskan untuk menjalankan bahagian yang saya fikir adalah bahagian paling "intensif data" perpustakaan, pengeluar dan pengguna aliran redis. Saya membina dua perkhidmatan ringkas yang akan menghasilkan dan menggunakan data daripada aliran redis dan saya meneruskan dengan menangkap profil memori dan membandingkan hasilnya dari semasa ke semasa. Malangnya, selepas beberapa jam menghasilkan beban kepada perkhidmatan dan membandingkan profil, saya tidak dapat melihat sebarang perbezaan dalam penggunaan memori dalam mana-mana dua perkhidmatan, semuanya kelihatan normal. Perpustakaan itu mendedahkan sekumpulan antara muka yang berbeza dan cara berinteraksi dengan aliran redis. Ia menjadi jelas kepada saya bahawa ia akan menjadi lebih rumit daripada yang saya jangkakan untuk meniru isu itu, terutamanya dengan pengetahuan khusus domain terhad saya tentang perkhidmatan sebenar.

Jadi persoalannya ialah, bagaimana saya boleh mencari masa dan keadaan yang sesuai untuk menangkap kebocoran memori?

Tangkap profil daripada perkhidmatan pementasan

Seperti yang dinyatakan sebelum ini, cara paling mudah dan paling mudah untuk menangkap profil ingatan ialah melakukan pemprofilan berterusan pada perkhidmatan sebenar yang terjejas, pilihan yang saya tidak ada. Saya mula menyiasat cara sekurang-kurangnya memanfaatkan perkhidmatan pementasan kami (mereka menghadapi penggunaan memori tinggi yang sama) yang membolehkan saya menangkap data yang saya perlukan tanpa usaha tambahan.

Saya mula mencari cara untuk menyambungkan Chrome DevTools kepada salah satu pod yang sedang berjalan dan menangkap petikan timbunan dari semasa ke semasa. Saya tahu kebocoran memori berlaku dalam pementasan, jadi jika saya dapat menangkap data itu, saya berharap saya akan dapat melihat sekurang-kurangnya beberapa titik panas. Saya terkejut, ada cara untuk melakukannya.

Proses untuk melakukan ini

  • Dayakan penyahpepijat Node.js pada pod dengan menghantar isyarat SIGUSR1 kepada proses nod pada pod anda.
kubectl exec -it <nodejs-pod-name> -- kill -SIGUSR1 <node-process-id>




</p>
<p><em>Lagi tentang isyarat Node.js di Acara Isyarat</em></p>

<p>Jika berjaya, anda sepatutnya melihat log daripada perkhidmatan anda:<br>
</p>

<pre class="brush:php;toolbar:false">Debugger listening on ws://127.0.0.1:9229/....
For help, see: https://nodejs.org/en/docs/inspector
Salin selepas log masuk
  • Dedahkan port yang sedang didengari oleh penyahpepijat, secara setempat dengan berjalan
kubectl port-forward <nodejs-pod-name> 9229
Salin selepas log masuk
  • Sambungkan Chrome Devtools kepada penyahpepijat yang anda dayakan pada langkah sebelumnya. Lawati chrome://inspect/ dan di sana anda akan melihat dalam senarai sasaran proses Node.js anda:

Tracking down high memory usage in Node.js

jika tidak, maka pastikan tetapan penemuan sasaran anda disediakan dengan betul

Tracking down high memory usage in Node.js

Kini anda boleh mula merakam syot kilat lebih masa (tempoh bergantung pada masa yang diperlukan untuk kebocoran memori berlaku) dan membandingkannya. Chrome DevTools menyediakan cara yang sangat mudah untuk melakukan ini.

Anda boleh mendapatkan lebih banyak maklumat tentang petikan memori dan Alat Pembangun Chrome di petikan timbunan rekod

Apabila membuat syot kilat, semua kerja lain dalam urutan utama anda dihentikan. Bergantung pada kandungan timbunan, ia mungkin mengambil masa lebih daripada satu minit. Syot kilat terbina dalam ingatan, jadi ia boleh menggandakan saiz timbunan, mengakibatkan mengisi keseluruhan memori dan kemudian ranap apl.

Jika anda akan mengambil gambar timbunan dalam pengeluaran, pastikan proses yang anda ambil daripadanya boleh ranap tanpa menjejaskan ketersediaan aplikasi anda.

Daripada dokumen Node.js

Jadi kembali kepada kes saya, memilih dua syot kilat untuk membandingkan dan mengisih mengikut delta, saya mendapat apa yang anda boleh lihat di bawah.

Tracking down high memory usage in Node.js

Kita dapat melihat delta positif terbesar berlaku pada pembina rentetan yang bermakna perkhidmatan itu telah mencipta banyak rentetan antara dua syot kilat tetapi ia masih digunakan. Sekarang persoalannya ialah di mana ia dicipta dan siapa yang merujuknya. Nasib baik syot kilat yang ditangkap mengandungi maklumat ini juga dipanggil Retainers.

Tracking down high memory usage in Node.js

Semasa menggali gambar dan senarai rentetan yang tidak pernah susut, saya melihat corak rentetan yang menyerupai id. Mengklik padanya, saya dapat melihat objek rantai yang merujuknya - aka Retainers. Ia adalah tatasusunan yang dipanggil sentEvents daripada nama kelas yang boleh saya kenali daripada kod perpustakaan. Tadaaa kita ada penyebabnya, satu-satunya senarai id yang semakin meningkat yang pada ketika ini saya andaikan tidak pernah dikeluarkan. Saya merakam sekumpulan gambar lebih masa dan ini adalah satu-satunya tempat yang terus muncul semula sebagai hotspot dengan delta positif yang besar.

Sahkan pembetulan

Dengan maklumat ini, daripada cuba memahami kod sepenuhnya, saya perlu menumpukan pada tujuan tatasusunan, apabila ia diisi dan apabila dibersihkan. Terdapat satu tempat di mana kod itu menolak item ke tatasusunan dan satu lagi tempat kod itu mengeluarkannya yang mengecilkan skop pembetulan.

Adalah selamat untuk mengandaikan bahawa tatasusunan tidak dikosongkan apabila sepatutnya. Melangkau butiran kod, apa yang pada asasnya berlaku ialah ini:

  • Perpustakaan telah mendedahkan antara muka untuk sama ada memakan, menghasilkan acara atau menghasilkan dan menghabiskan acara.
  • Apabila ia memakan dan menghasilkan acara, ia perlu menjejaki peristiwa yang dihasilkan oleh proses itu sendiri untuk melangkaunya dan tidak menggunakannya semula. SendEvents telah diisi apabila menghasilkan dan dikosongkan apabila semasa cuba untuk menggunakan ia akan melangkau mesej.

Bolehkah anda melihat ke mana arahnya? ? Apabila perkhidmatan menggunakan perpustakaan hanya untuk menghasilkan acara, sentEvents masih akan diisi dengan semua acara tetapi tiada laluan kod (pengguna) untuk mengosongkannya.

Saya menampal kod untuk hanya menjejak acara pada pengeluar, mod pengguna dan digunakan untuk pementasan. Walaupun dengan beban pementasan adalah jelas bahawa tampung membantu mengurangkan penggunaan memori yang tinggi dan tidak memperkenalkan sebarang regresi.

Keputusan

Apabila tampung digunakan pada pengeluaran, penggunaan memori telah dikurangkan secara drastik dan kebolehpercayaan perkhidmatan telah dipertingkatkan (tiada lagi OOM).

Tracking down high memory usage in Node.js

Kesan sampingan yang bagus ialah pengurangan 50% dalam bilangan pod yang diperlukan untuk mengendalikan trafik yang sama.

Tracking down high memory usage in Node.js

Kesimpulan

Ini adalah peluang pembelajaran yang hebat untuk saya mengenai penjejakan isu memori dalam Node.js dan seterusnya membiasakan diri saya dengan alatan yang tersedia.

Saya fikir adalah lebih baik untuk tidak memikirkan butiran setiap alat kerana ia patut diberi jawatan berasingan, tetapi saya harap ini adalah titik permulaan yang baik untuk sesiapa sahaja yang berminat untuk mengetahui lebih lanjut tentang topik ini atau menghadapi isu yang serupa.

Atas ialah kandungan terperinci Menjejaki penggunaan memori yang tinggi dalam Node.js. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan