Node.js کا وہ بگ جو آپ کی مانیٹرنگ سے اوجھل ہے
آپ کا ہیلتھ چیک کہتا ہے کہ سب کچھ ٹھیک ہے۔ اس میں صرف ایک ملی سیکنڈ لگتا ہے۔ پھر ٹریفک بڑھتی ہے۔ اچانک، آپ کی p99 latency 400ms تک پہنچ جاتی ہے۔ آپ اپنے ڈیش بورڈز دیکھتے ہیں۔ سب کچھ سبز (green) نظر آتا ہے۔
CPU کا استعمال درمیانہ ہے۔ Event loop lag بالکل مستحکم ہے۔ میموری ٹھیک ہے۔ آپ کا APM ایک سست ریکویسٹ دکھاتا ہے لیکن یہ نہیں بتاتا کہ کیوں۔ کوئی سست ڈیٹا بیس کالز نہیں ہیں۔ کوئی ایررز نہیں ہیں۔
وقت libuv thread pool میں صرف ہو رہا ہے۔
عام Node observability صرف event loop پر توجہ مرکز کرتی ہے۔ یہ پول (pool) ایک الگ قطار ہے۔ یہ آپ کی پہنچ سے باہر ہے۔
Node، event loop پر JavaScript چلاتا ہے۔ یہ بھاری کاموں کو libuv thread pool میں بھیج دیتا ہے۔ ان میں شامل ہیں:
- Filesystem کا کام (fs.readFile, fs.writeFile)۔
- Crypto ٹاسکس (bcrypt, scrypt, pbkdf2)۔
- Compression (zlib gzip, deflate)۔
- DNS lookups (dns.lookup)۔
پول کی ڈیفالٹ سیٹنگ صرف چار تھریڈز (threads) کی ہوتی ہے۔ یہ حقیقت ہے، چاہے آپ کی مشین میں کتنے ہی CPU cores کیوں نہ ہوں۔
چار تھریڈز کافی نہیں ہیں۔ یہاں تین طریقے ہیں جن سے یہ پول ناکام ہو سکتا ہے:
لاگ ان پر Bcrypt۔ ایک سنگل bcrypt hash 250ms لے سکتا ہے۔ اگر چار لوگ ایک ساتھ لاگ ان کریں، تو تمام سلاٹس (slots) بھر جاتے ہیں۔ پانچواں شخص قطار میں انتظار کرتا ہے۔ اسے شروع کرنے کے لیے ہی 250ms کا انتظار کرنا پڑتا ہے۔ آپ کی latency دوگنی ہو جاتی ہے۔
بڑے gzip آپریشنز۔ ایک بڑے رسپانس کو کمپریس کرنے سے پول کا ایک سلاٹ استعمال ہو جاتا ہے۔ اگر چار ریکویسٹس ایک ساتھ ایسا کریں، تو باقی تمام کام انتظار کرتے ہیں۔ DNS lookups اور فائل ریڈز لائن میں پھنس جاتے ہیں۔
DNS lookups۔ زیادہ تر Node ایپس dns.lookup استعمال کرتی ہیں۔ یہ ایک بلاکنگ سسٹم کال (blocking system call) استعمال کرتا ہے۔ یہ ٹاسک کو پول پر ڈال دیتا ہے۔ اگر آپ کے نیٹ ورک میں کوئی خرابی آئے، تو یہ lookups پورے پول کو روک دیتے ہیں۔
پول کی قطار میں پھنسا ہوا ریکویسٹ نظر نہیں آتا۔ یہ CPU استعمال نہیں کر رہا ہوتا۔ یہ JavaScript نہیں چلا رہا ہوتا ہے۔ یہ بس رکا ہوا ہوتا ہے۔
اسے کیسے تلاش کریں:
اگر لوڈ کے دوران آپ کی p99 latency بڑھتی ہے لیکن event loop lag مستحکم رہتا ہے، تو پول کو چیک کریں۔
تیز ترین ٹیسٹ: UV_THREADPOOL_SIZE بڑھا دیں۔ اپنے انوائرمنٹ (environment) میں اسے 64 پر سیٹ کریں اور ری اسٹارٹ کریں۔ اگر latency کم ہو جاتی ہے، تو آپ کو مسئلہ مل گیا ہے۔
اسے صحیح طریقے سے کیسے ٹھیک کریں:
- bcrypt جیسے بھاری crypto کے لیے
worker_threadsاستعمال کریں۔ اس سے یہ libuv پول سے دور رہتے ہیں۔ dns.lookupکے بجائےdns.resolveاستعمال کریں۔ یہ ایک حقیقی async resolver ہے۔- zlib کے کام کے لیے streams استعمال کریں تاکہ سلاٹس جلدی خالی ہو سکیں۔
- اپنے مین ریکویسٹ پاتھز (request paths) پر بھاری filesystem کا کام کرنے سے گریز کریں۔
اپنے صارفین کے انتظار کے دوران سبز ڈیش بورڈز کو گھورنا بند کریں۔
Source: https://dev.to/r9v/the-nodejs-bug-thats-invisible-to-your-monitoring-oo8
