Rumah  >  Artikel  >  hujung hadapan web  >  [Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

青灯夜游
青灯夜游ke hadapan
2023-01-28 19:25:373018semak imbas

Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Artikel berikut akan meringkaskan pengalaman penyelesaian masalah kebocoran memori Node untuk semua orang.

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

Dalam senario Nodejs pembangunan sisi pelayan, 内存泄漏 pastinya merupakan masalah yang paling menyusahkan; Tetapi selagi projek itu terus dibangunkan dan diulang, masalah 内存泄漏 sememangnya tidak dapat dielakkan, ia hanya berlaku lambat laun. Oleh itu, menguasai kaedah penyelesaian masalah 内存泄漏 yang berkesan secara sistematik adalah keupayaan paling asas dan teras seorang jurutera Nodejs.

Kesukaran menangani kebocoran ingatan ialah bagaimana untuk mengetahui antara fungsi dan fungsi yang tidak terkira dengan tepat yang mana fungsi dan baris mana dalam fungsi yang menyebabkan kebocoran memori. Malangnya, pada masa ini tiada alat di pasaran yang boleh mengesan kebocoran memori dengan mudah, jadi ramai jurutera yang menghadapi masalah ini buat kali pertama akan berasa keliru dan tidak tahu bagaimana untuk menanganinya. Di sini saya akan berkongsi idea pemprosesan saya berdasarkan kes siasatan 内存泄漏 dalam tempoh 22 tahun.

Penerangan Masalah

2022 Q4 Pada suatu hari, kumpulan pengguna R&D melaporkan bahawa platform R&D kami tidak dapat diakses, dan terdapat sejumlah besar tugas yang tidak normal dalam latar belakang yang tidak disiapkan. Reaksi pertama ialah mungkin terdapat kebocoran memori Nasib baik, perkhidmatan disambungkan ke pemantauan (prometheus + grafana Dalam panel pemantauan grafana, didapati bahawa memori telah meningkat sejak 10.00 dan). belum turun. Terdapat kebocoran data yang jelas. [Cadangan tutorial berkaitan: tutorial video nodejs]

DX 内存泄漏监控图.png

Arahan:

  • process memory: rss (Saiz Set Penduduk), saiz memori pemastautin proses.
  • heapTotal: Jumlah saiz timbunan V8.
  • heapUsed: Saiz timbunan V8 yang digunakan.
  • external: Penggunaan memori luar timbunan V8.

Anda boleh memanggil kaedah global Nodejs dalam process.memoryUsage() untuk mendapatkan data ini dan heapTotal ialah penggunaan timbunan V8, dan timbunan V8 disimpan oleh objek JavaScript. di tempat heapUsed. Dan Node.js mewakili memori yang diperuntukkan dalam timbunan bukan V8, seperti objek C++. external ialah jumlah penggunaan memori bagi proses tersebut. Secara amnya apabila melihat data pemantauan, hanya fokus pada penunjuk rss heapUsed

Jenis kebocoran memori

Kebocoran memori terutamanya dibahagikan kepada:

    Kebocoran global
  • Kebocoran tempatan
Malah, sama ada kebocoran memori global atau kebocoran memori tempatan, apa yang perlu kita lakukan ialah untuk meminimumkannya sebanyak mungkin Julat pengecualian.

Kebocoran memori global

Kebocoran kandungan global biasanya berlaku dalam:

dan 中间件 Penyelesaian masalah kebocoran memori jenis ini Ia juga paling mudah untuk dilakukan bangun. 组件

Malangnya, kebocoran memori yang saya temui dalam

bukan tergolong dalam jenis ini, jadi saya perlu menganalisisnya mengikut idea kebocoran tempatan. 2022 Q4

Penyelesaian masalah dikotomi

Saya tidak akan bercakap tentang kaedah analisis saintifik lain untuk jenis ini, saya rasa menggunakan kaedah dikotomi adalah yang paling cepat.

Aliran proses:

  • Ulas separuh daripada kod dahulu (kurangkan penggunaan

    , 中间件 atau perkara biasa lain logik separuh) 组件

  • Pilih antara muka atau tulis antara muka ujian baharu untuk ujian tekanan

  • Jika kebocoran memori berlaku, titik kebocoran ialah dalam kod yang sedang digunakan, jika tiada kebocoran, titik kebocoran muncul di

  • Kemudian teruskan mengulangi proses di atas selama kira-kira 20 ~ 60 minit Anda pasti dapat mencarinya lokasi terperinci kebocoran memori

Pada tahun 2020, semasa saya sedang mengusahakan aplikasi SSR berdasarkan

, saya mendapati kebocoran memori aplikasi semasa ujian tekanan sebelum pergi dalam talian. Selepas menentukan ia sebagai kebocoran global, ia mengambil masa kira-kira 30 minit untuk menggunakan kaedah dikotomi untuk menyelesaikan masalah tersebut. NuxtSebab kebocoran pada masa itu adalah kerana kami menggunakan
di bahagian pelayan Kemudian, ia diselesaikan selepas menyatukan semua axios perkara yang berkaitan dan menggantikannya dengan axios Sejak itu, kami menggantikan mereka dengan node-fetch dan mereka tidak akan digunakan lagi kemudian axios PDST Gunakan Node dalam perkhidmatan axios

Menyelesaikan masalah kebocoran memori setempat

Kebanyakan kebocoran memori adalah kebocoran tempatan. Titik mungkin wujud dalam

tertentu, 中间件 tertentu atau 接口 tertentu Disebabkan ciri ini, ia lebih sukar untuk diselesaikan. Dalam kes ini, 异步任务 akan digunakan untuk analisis. heapdump

Di sini saya bercakap tentang idea saya dalam kes ini, saya akan meletakkan penerangan terperinci heapdump dalam perenggan seterusnya,

Heap Dump: Longgokan longgokan, bahagian berikut dinyatakan. oleh heapdump , terdapat banyak alatan dan tutorial untuk melakukan heapdump, seperti: chrome, vscode, heapdump, perpustakaan sumber terbuka ini. Terdapat banyak tutorial dalam talian untuk perpustakaan heapdump yang saya gunakan, yang saya tidak akan pergi ke sini.

Menyelesaikan masalah kebocoran memori setempat memerlukan sejumlah pengalaman penyelesaian masalah kebocoran memori Setiap kali anda menghadapinya, anggap ia sebagai ujian untuk diri sendiri Selepas anda mengumpul lebih banyak pengalaman, anda boleh menyelesaikan masalah memori masalah kebocoran nanti.

1 Tentukan julat masa kebocoran memori berlaku

Ini sangat penting dengan mengetahui perkara ini boleh mengecilkan skop penyiasatan.
Situasi ini sering berlaku Lelaran ini mempunyai tiga fungsi A, B dan C, dan kebocoran memori berlaku semasa ujian tekanan atau selepas pergi ke dalam talian. Kemudian anda boleh terus mengunci dan kebocoran memori kecil akan berlaku di antara tiga fungsi baharu ini. Dalam kes ini, tidak perlu pergi ke pengeluaran heapdump Kami boleh menganalisis dan mencari titik kebocoran memori secara tempatan melalui beberapa alatan.

Disebabkan beberapa keadaan istimewa 20年Q4 kami, apabila kami menemui kebocoran memori, sukar untuk menentukan bila kebocoran ingatan mula-mula muncul. Kami hanya boleh menguncinya secara kasar pada bulan Januari. Bulan ini kami telah melalui satu lagi lelaran versi utama Jika kami menyemak fungsi dan antara muka ini satu demi satu, kosnya akan menjadi sangat tinggi. Oleh itu, lebih banyak data perlu digabungkan untuk analisis selanjutnya

2 Kumpul data timbunan

  • Apabila pengeluaran bermulanode Tambahkan --expose-gc, parameter ini. Kaedah gc() akan disuntik secara global untuk memudahkan pencetus manual GC untuk mendapatkan data 堆快照 yang lebih tepat
  • Di sini saya menambah dua antara muka dan membawa kebenaran eksklusif saya sendiri,
    • Citus GC secara manual
    • Cetak gambar timbunan
  • heapdump
    • Cetak data syot kilat untuk kali pertama selepas projek dimulakan
    • Memori meningkat sebanyak 100J Selepas: cetuskan GC dahulu, kemudian cetak data petikan timbunan untuk kali kedua
    • Cetuskan GC semula apabila memori hampir kritikal, kemudian cetak petikan timbunan

Pengumpulan Terdapat beberapa perkara yang memerlukan perhatian khusus apabila menimbun data syot kilat!

  • Perkhidmatan Node akan terganggu pada heapdump Masa ini akan mengambil masa kira-kira 2 hingga 30 minit bergantung pada saiz memori pelayan pada masa itu. Untuk melakukan heapdump dalam persekitaran pengeluaran, anda perlu bekerja dengan operasi dan penyelenggaraan untuk merangka strategi yang munasabah. Saya menggunakan dua pod rendah dan menengah di sini Apabila pod utama dihentikan, permintaan perniagaan akan dimuatkan seimbang kepada pod menengah untuk memastikan kemajuan biasa perniagaan pengeluaran. (Proses ini mestilah proses yang diselaraskan rapat dengan operasi dan penyelenggaraan. Lagipun, heapdump anda masih perlu mendapatkan 堆快照 fail dalam pelayan melaluinya)
  • Syot kilat pencetakan yang disebutkan di atas berhampiran titik kritikal hanyalah penerangan yang tidak jelas, jika anda telah mencubanya, anda akan tahu bahawa jika anda menunggu sangat dekat dengan titik kritikal sebelum mencetak gambar memori, anda tidak akan dapat mencetaknya. Jadi anda perlu mengawal diri anda untuk mendekati ijazah ini.
  • Lakukan sekurang-kurangnya 3 kaliheapdump (sebenarnya saya melakukannya 5 kali untuk mendapatkan data yang paling terperinci)

3 panel Untuk menganalisis data

memerlukan perkhidmatan aplikasi anda untuk mengakses pemantauan Aplikasi di sini menggunakan prometheus + grafana untuk pemantauan terutamanya penunjuk perkhidmatan berikut

  • QPS (minta lawatan sesaat), status permintaan dan laluan aksesnya
  • ART (purata masa tindak balas antara muka) dan data aksesnya
  • NodeJs versi
  • Actice Handlers(pegangan)
  • Event Loop Lag (selang peristiwa)
  • Bilangan proses perkhidmatan dimulakan semula
  • Penggunaan CPU
  • Penggunaan memori: rss, heapTotal, heapUsed, external, heapAvailableDetail

Hanya heapdump data tidak mencukupi, heapdump data sangat kabur , Walaupun dengan sokongan alat visualisasi, sukar untuk mengesan masalah dengan tepat. Pada masa ini, saya melihatnya bersama-sama dengan beberapa data daripada grafana.

Hasil analisis dan pemprosesan saya

Memandangkan data syot kilat pada masa itu hilang, saya akan mensimulasikan pemandangan di sini.

1. Melalui antara muka pemantauan grafana, saya mendapati bahawa memori telah meningkat dan tidak berkurangan, tetapi pada masa yang sama, saya juga menyedari bahawa bilangan 句柄 dalam perkhidmatan telah juga melambung tinggi dan tidak turun.

DX 内存泄漏监控图2.png

2. Ini adalah semasa saya menyemak ciri baharu pada bulan kebocoran berlaku dan mengesyaki bahawa kebocoran memori mungkin disebabkan oleh penggunaan komponen baris gilir mesej bull. Saya mula-mula menganalisis kod aplikasi yang berkaitan, tetapi saya tidak dapat melihat bahawa terdapat sesuatu yang tidak kena dengannya yang menyebabkan kebocoran memori. Digabungkan dengan masalah kebocoran pemegang dalam 1, nampaknya anda perlu mengeluarkan sumber tertentu secara manual selepas menggunakan bull Pada masa ini, saya tidak pasti tentang sebab tertentu.

3. Kemudian 5 kali data heapdunmp dianalisis, dan data diimport chrome Selepas membandingkan 5 kali syot kilat timbunan, didapati tiada peristiwa untuk TCP, Socket, dan EventEmitter selepas setiap baris gilir dilepaskan ke. Pada ketika ini, pada asasnya pasti ia berpunca daripada penggunaan bull yang tidak teratur. Barisan gilir biasanya tidak dibuat dengan kerap dalam bull dan sumber sistem yang diduduki oleh baris gilir tidak dikeluarkan secara automatik Jika perlu, ia perlu dikeluarkan secara manual.

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

4. Selepas melaraskan kod, ujian tekanan dilakukan semula dan masalah telah diselesaikan.

Petua: 句柄 dalam Nodejs ialah penunjuk yang menunjuk kepada sumber sistem asas (seperti fail, sambungan rangkaian, dll.). Pemegang membenarkan program Node.js mengakses dan memanipulasi sumber ini tanpa berinteraksi secara langsung dengan sistem asas. Pemegang boleh menjadi integer atau objek, bergantung pada jenis pemegang yang digunakan oleh perpustakaan atau modul Node.js. Biasa句柄:

  • fs.open() Pemegang fail yang dikembalikan
  • net.createServer() Pemegang pelayan rangkaian yang dikembalikan
  • dgram.createSocket() Pemegang soket UDP yang dikembalikan
  • child_process.spawn() Mengembalikan pemegang proses anak
  • crypto.createHash() Mengembalikan pemegang cincang
  • zlib.createGzip() Mengembalikan pemegang mampatan

analisis timbunan ringkasan

Biasanya ramai yang keliru apabila mendapat data 堆快照 buat kali pertama, dan saya juga begitu. Selepas membaca banyak teknik analisis di Internet dan menggabungkannya dengan amalan sebenar saya sendiri, saya telah merumuskan beberapa teknik yang lebih berguna Beberapa tutorial penggunaan asas tidak akan dibincangkan di sini. Di sini kita bercakap tentang cara melihat gambar selepas data diimport chrome;

Paparan ringkasan

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi ideaApabila melihat paparan ini, Retained Saiz biasanya akan diperiksa dahulu Kemudian perhatikan saiz dan bilangan objek Jurutera yang berpengalaman boleh dengan cepat menentukan bilangan objek tertentu adalah tidak normal. Dalam pandangan ini, selain mengambil berat tentang beberapa objek yang ditentukan oleh anda sendiri, Sesetengah objek yang terdedah kepada kebocoran ingatan juga memerlukan perhatian, seperti:

  • TCP
  • Socket
  • EventEmitter
  • global

Paparan perbandingan

Jika masalah tidak dapat dikesan melalui paparan Summary, maka biasanya kami menggunakan paparan Comparison. Melalui pandangan ini, kita boleh membandingkan bilangan objek dalam dua petikan timbunan dan perubahan dalam memori yang diduduki oleh objek; Melalui maklumat ini, kita boleh menilai nilai objek dalam timbunan dan perubahan memori selepas tempoh masa (operasi tertentu, melalui nilai ini, kita boleh menemui beberapa objek yang tidak normal). Nama atribut atau fungsi objek ini boleh mengecilkan skop penyiasatan kebocoran ingatan kami.

Pilih dua petikan timbunan dalam paparan Comparison dan bandingkan antaranya. Anda boleh melihat objek mana yang telah ditambah antara dua syot kilat timbunan, objek mana yang dikecilkan antara dua syot kilat timbunan dan objek mana yang berubah dalam saiz. Comparison Paparan juga membenarkan melihat perhubungan antara objek, serta butiran objek seperti jenis, saiz dan kiraan rujukan. Dengan maklumat ini, anda boleh memahami objek mana yang menyebabkan kebocoran memori.

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

Paparan pembendungan

memaparkan semua hubungan rujukan yang boleh dicapai antara objek. Setiap objek diwakili sebagai titik dan disambungkan kepada objek induknya dengan garis. Dengan cara ini anda boleh melihat perhubungan hierarki antara objek dan memahami objek yang menyebabkan kebocoran memori.

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

Paparan Statistik

Gambar ini sangat mudah dan saya tidak akan menerangkan secara terperinci

[Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea

Senario kebocoran memori

  • Pembolehubah global: Pembolehubah global tidak akan dikitar semula
  • Cache: Perpustakaan pihak ketiga intensif memori seperti Menyimpan terlalu banyak akan mengakibatkan memori tidak mencukupi Dalam perkhidmatan Nodejs, disyorkan untuk menggunakan lru-cache dan bukannya redislru-cache
  • Kendalikan kebocoran: sumber sistem tidak dikeluarkan selepas memanggil
  • Pemantauan acara
  • Penutupan
  • Rujukan pekeliling

Ringkasan

  • Perkhidmatan perlu diakses untuk pemantauan, yang sesuai untuk kali ketiga Tentukan jenis masalah sekaligus

  • Tentukan sama ada kebocoran memori adalah global atau tempatan

  • Gunakan kaedah dikotomi untuk menyelesaikan masalah dan mencari kebocoran memori global dengan cepat

  • Kebocoran memori setempat

      Tentukan titik masa apabila kebocoran memori berlaku dan cari dengan cepat. fungsi masalah
    • Kumpul data petikan timbunan, sekurang-kurangnya 3 kali
    • Data pemantauan gabungan, data syot kilat timbunan dan fungsi baharu pada masa berlakunya kebocoran untuk mencari titik kebocoran memori
    • Data kondusif untuk mengumpul pengalaman yang berkaitan dengan lebih cepat
Lain-lain

堆快照

Alat Ujian Tekanan: wrk

Untuk lebih banyak pengetahuan berkaitan nod, sila lawati:

tutorial nodejs
    !

Atas ialah kandungan terperinci [Ringkasan Pengalaman] Bagaimana untuk menyelesaikan masalah kebocoran memori dalam Node? Berkongsi idea. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam