Bug Node.js yang tidak terlihat oleh monitoring Anda
Health check Anda mengatakan semuanya baik-baik saja. Hanya butuh satu milidetik. Kemudian trafik meningkat. Tiba-tiba, latensi p99 Anda melonjak ke 400ms. Anda melihat dashboard Anda. Semuanya tampak hijau.
Penggunaan CPU moderat. Event loop lag tetap stabil. Memori sehat. APM Anda menunjukkan permintaan yang lambat tetapi tidak memberi tahu alasannya. Tidak ada panggilan database yang lambat. Tidak ada error.
Waktu habis di dalam libuv thread pool.
Observabilitas Node standar berfokus pada event loop. Pool tersebut adalah antrean terpisah. Ia berada di luar jangkauan Anda.
Node menjalankan JavaScript pada event loop. Ia mendorong tugas-tugas berat ke libuv thread pool. Ini termasuk:
- Pekerjaan filesystem (fs.readFile, fs.writeFile).
- Tugas crypto (bcrypt, scrypt, pbkdf2).
- Kompresi (zlib gzip, deflate).
- DNS lookups (dns.lookup).
Pool ini secara default hanya memiliki empat thread. Hal ini tetap berlaku terlepas dari berapa banyak core CPU yang dimiliki mesin Anda.
Empat thread tidaklah cukup. Berikut adalah tiga cara pool tersebut bermasalah:
Bcrypt saat login. Satu hash bcrypt bisa memakan waktu 250ms. Jika empat orang login secara bersamaan, semua slot akan penuh. Orang kelima harus menunggu dalam antrean. Mereka harus menunggu 250ms hanya untuk memulai. Latensi Anda berlipat ganda.
Operasi gzip besar. Mengompresi respons yang besar akan menahan slot pool. Jika empat permintaan melakukan ini secara bersamaan, tugas lainnya akan menunggu. DNS lookups dan pembacaan file akan tertahan dalam antrean.
DNS lookups. Sebagian besar aplikasi Node menggunakan dns.lookup. Ini menggunakan system call yang bersifat blocking. Ini menempatkan tugas ke dalam pool. Jika jaringan Anda mengalami gangguan, lookup ini akan menghambat seluruh pool.
Permintaan yang tertahan di antrean pool tidak terlihat. Ia tidak menggunakan CPU. Ia tidak menjalankan JavaScript. Ia hanya terparkir.
Cara menemukannya:
Jika latensi p99 Anda naik saat beban tinggi tetapi event loop lag tetap stabil, periksa pool tersebut.
Tes tercepat: Tingkatkan UV_THREADPOOL_SIZE. Atur ke 64 di environment Anda dan restart. Jika latensi turun, Anda telah menemukan masalahnya.
Cara memperbaikinya dengan benar:
- Gunakan
worker_threadsuntuk crypto berat seperti bcrypt. Ini menjauhkan tugas tersebut dari libuv pool. - Gunakan
dns.resolvealih-alihdns.lookup. Ini adalah resolver async yang sesungguhnya. - Gunakan streams untuk pekerjaan zlib agar melepaskan slot lebih cepat.
- Hindari pekerjaan filesystem yang berat pada jalur permintaan utama Anda.
Berhentilah menatap dashboard hijau sementara pengguna Anda menunggu.
Sumber: https://dev.to/r9v/the-nodejs-bug-thats-invisible-to-your-monitoring-oo8
