Tumpukan kami di Deepnote terdiri dari beberapa Node. aplikasi js berjalan di pod di kluster Kubernetes. Beberapa minggu yang lalu kami mulai mengalami masalah dengan kegagalan pemeriksaan keaktifan pod karena server Express kami tidak menanggapi waktu pemeriksaan kesehatan Show
Kami menduga pelakunya mungkin loop peristiwa yang macet Men-debug loop peristiwa yang macetPertanyaannya adalah apa yang menyebabkan loop acara macet. Sayangnya, kami tidak dapat mereproduksi masalah dalam pengembangan, jadi kami memutuskan untuk mencoba membuat profil Node. aplikasi js dalam produksi Debugger dapat diaktifkan sesuai permintaan, bahkan pada aplikasi yang sudah berjalan. Dan mengumpulkan profil CPU berfungsi bahkan saat loop acara aplikasi macet Tetapi melakukan ini secara manual berarti seorang insinyur harus merespons dengan sangat cepat terhadap kegagalan pemeriksaan kesehatan, SSH ke pod, mengaktifkan debugger node, dan kemudian menjalankan profiler Chrome DevTools melalui terowongan SSH pada instans produksi Kami tidak pernah benar-benar dapat menyelesaikan semua langkah ini tepat waktu Mengotomatiskan pembuatan profil CPUKami memutuskan untuk mengotomatiskan proses pembuatan profil CPU. Kami menyadari ini sebenarnya cukup mudah karena Kubernetes mengirimkan sinyal SIGTERM ketika probe liveness pod gagal, menunggu 30 detik, dan baru kemudian mengirim sinyal SIGKILL dan mengakhiri pod. Ini berarti kita memiliki 30 detik untuk memulai debugger, mengumpulkan profil CPU, dan menyimpannya di suatu tempat yang nantinya dapat kita akses Tetapi bagaimana cara mengotomatiskan pembuatan profil Chrome DevTools? Sekarang yang kita butuhkan hanyalah skrip yang membungkus perintah startup standar kita —
Dan itu saja. Sekarang setiap kali aplikasi kami berhenti merespons pemeriksaan liveness, kami secara otomatis menangkap profil CPU-nya sehingga nanti kami dapat membukanya di Chrome DevTools dan memeriksa di mana aplikasi kami menghabiskan waktu. Root-penyebab masalah kemudian biasanya sangat mudah Jika Anda menyukai apa yang Anda lihat di sini dan ingin membantu kami memecahkan tantangan teknik seperti ini, bergabunglah dengan kami di Deepnote *Kami menyimpan file Loop acara inilah yang memungkinkan Node. js untuk melakukan operasi I/O non-pemblokiran — terlepas dari fakta bahwa JavaScript adalah utas tunggal — dengan membongkar operasi ke kernel sistem jika memungkinkan Karena sebagian besar kernel modern multi-thread, mereka dapat menangani banyak operasi yang dijalankan di latar belakang. Ketika salah satu dari operasi ini selesai, kernel memberi tahu Node. js sehingga callback yang sesuai dapat ditambahkan ke antrean polling untuk akhirnya dieksekusi. Kami akan menjelaskan ini secara lebih rinci nanti di topik ini Diagram di bawah ini menunjukkan urutan pelaksanaan fase yang berbeda dalam acara Loop Analogi
Fase dalam EventLoop
Apa itu Memblokir EventLoop?Jika utas membutuhkan waktu lama untuk mengeksekusi panggilan balik (Event Loop) atau tugas (Pekerja), itu disebut "diblokir". Saat utas diblokir bekerja atas nama satu klien, utas tidak dapat menangani permintaan dari klien lain mana pun Mari blokir EventLoopMari kita mulai dengan contoh cara memblokir IO // lets prepare requisites blockEventLoop. jsJalankan server… node blockEventLoop.js _Lakukan ping, dan periksa pong curl 127.0.0.1:3000/ping _Mari tambahkan rute lain dengan tugas yang mahal… Ayo lari … // in Terminal 1 Segera setelah node blockEventLoop.js 1 dipanggil… node blockEventLoop.js 2 panggil kios. Periksa juga penggunaan CPU dari proses nodeJika misalnya kita menggunakan rute node blockEventLoop.js 2 sebagai healthCheck sederhana di lingkungan k8 sebagai probe liveness, ini akan tampak seperti server yang tidak sehat dan pod dimulai ulangApa yang sebenarnya terjadi di sini? IO yang berjalan lama (di sini fungsi crypto) memblokir loop acara Sekarang, Mari buka blokir loop acaraMari tambahkan rute node blockEventLoop.js _4 …dan lari // in Terminal 1 Tidak ada banyak perubahan meskipun kami memanggil fungsi yang dibungkus dengan paradigma node blockEventLoop.js 5Mengapa? Kami masih memblokir pengulangan acara dengan membuat terlalu banyak tugas mikro Mari tambahkan rute node blockEventLoop.js _6 …Ayo lari … // in Terminal 1 Sekarang node blockEventLoop.js _2 panggilan berhasil tanpa terhenti dan kami siap menangani permintaan yang masuk. Pemanfaatan CPU juga relatif rendahTapi ada peringatan…. butuh waktu lebih lama untuk menyelesaikan node blockEventLoop.js _6 panggilan. Itulah pengorbanan yang kami bayar tetapi kami tidak memblokir panggilan lainMengapa memanggil node blockEventLoop.js 9 (/ setImmedidate/ process. nextTick) buka blokir loop acara?Karena urutan di mana curl 127.0.0.1:3000/ping _0 dipanggil dalam loop acaraSedangEdit deskripsisedang. com Dalam contoh microtask kami (fungsi curl 127.0.0.1:3000/ping _1) menambahkan lebih banyak tugas ke antrean, dengan loop acara ini tidak mendapat kesempatan untuk menangani permintaan masuk (IO jaringan). Dengan memanggil setTimeout, kami memberikan ruang bernapas untuk menjalankan tugas makro seperti (panggilan IO jaringan) untuk mengeksekusi dengan menyelesaikan loop acara untuk setiap curl 127.0.0.1:3000/ping 1 panggilan yang dilakukanBagaimana cara menghindari pemblokiran peristiwa-loop?Dengan menghindari ini
Bacaan tambahan
Loop Peristiwa di Node JS. setTimeout, setImmediate vs proses. nextCentangMendokumentasikan perjalanan belajar sayasedang. com Loop Peristiwa di Node JS. MacroTasks dan MicroTasksDokumen ini berbicara tentang berbagai antrean terkait EventLoop untuk lebih memahami cara terbaik menggunakan Promises, Timer…sedang. com Arsitektur NodeJS. Hubungan antara libUV, V8 dan JSMendokumentasikan perjalanan belajar sayasedang. com Suka mengotak-atik dan belajar melalui coba-coba? . Bergabunglah dengan kami dalam membuat solusi digital yang berpusat pada kehidupan berikutnya |