چند روز پیش، قرار شد که یه اپلیکیشنی بنویسم که تعدادی ریکوئست به یه API ارسال کنه. یه ConsoleApp بود و کار زیاد پیچیده‌ای نداشت. اپلیکیشن  رو نوشتم و روی سیستم خودم تست کردم اوکی بود. بعد گفتن که ریکوئست‌ها باید به صورت موازی ارسال بشه!. یه تغییر کوچیک دادم و همه ریکوئست‌ها رو باهم ارسال کردم. روال کار به این صورت بود که من یه لیستی از تسک‌ها درست کردم و بعدش صبر کردم که همه تسک‌ها تموم بشن (await Task.WhenAll) . اپلیکیشن روی 10,000 ریکوئست تست کردم جواب میداد. من اول فک کردم برای 1 یا 2 هزار حداکثر باشه. بگذریم، روزی که قرار بود اپلیکیشن روی سرور ران بشه، رفتیم توی جلسه و بعد گفتن ریکوئست‌ها نزدیک به 150,000 هستش. یکم استرس داشتم. چون تست من توی اون اندازه نبود. توی اون  جلسه تیم لید زیرساخت، تیم لید دیتابیس، تیم لید بک‌اند و CTO مجموعه هم بود. اپلیکیشن که ران بعد چند ثانیه اون اپلیکیشنی که ریکوئست‌هارو دریافت میکرد خطا داد. (بنازم) بهتر از این نمیشد!. خیلی واسم حس بدی داشت ینی اگه اخراج میشدم انقد حس بد نداشتم. از طرف هیچ‌ شخصی حرفی یا چیزی گفته نشد که من ناراحت بشم، خودم حس خیلی بدی داشتم که چرا اپلیکیشن الان باید خطا بده!. خلاصه، ریکوئست هارو به صورت موازی 100 تا 100 تا ارسال کردیم و کارمون تموم شد.

من اون رو فراموش نکردم و گفتم باید بدونم چرا اون اپلیکیشن توی اون تایم روی ریکوئست بالا خطا داد. همون تعداد ریکوئست رو آوردم روی سیستم خودم اجرا کردم و دیدم که اپلیکیشن خطا داد. خیلی سرچ کردم گفتن نباید این همه ریکوئست رو باهم ارسال کنی و از این حرفا. ولی قانع نشدم. بعد اومدم اپلیکیشنی که ریکوئست‌ها بهش ارسال میشد رو روی IIS ران کردم.

اصلا انگار نه انگار 150,000 ریکوئست داره میره سمتش. همه ریکوئست‌ها رو جواب داد!. خیلی واسم عجیب بود. این Kestrel که این همه ازش تعریف میشه که خوبه، پرفورمنس خوبی داره و ... چطوری در کنار IIS انقد سریع کم آورد. تایم بدی بود، جنگ ایران و اسراییل بود، اینترنت اصلا نبود. یه جوری سرچ میکردم که فقط توی صفحه اول گوگل از روی عنوان‌ها و توضیحات سایت‌ها که توی صفحه اول گوگل هستش یه چیزی پیدا کنم. نشد، توی استک اورفلو سوال پرسیدم که یه همچین سناریویی دارم و به مشکل خوردم. چرا این کد روی IIS به خوبی کار میکنه ولی روی Kestrel نه. باز هم نتیجه‌ای نگرفتم. از اقای وحید نصیری توی سایتشون پرسیدم که همچین مشکلی برام پیش اومده، توی استک اورفلو سوال پرسیدم، ممنون میشم اگه نظری در موردش دارید بگید. 

نمیدونم چطوری از ایشون تشکر کنم. یه کامنتی روی سوال من گذاشتن و گفتن که وقتی از IIS استفاده میکنی، ریکوئست‌ها از طریق HTTP.sys مدیریت میشن و این HTTP.sys در سطح هسته سیستم عامل میکنه!.

کلی سوال جدید برام پیش اومد که اصلا این HTTP.sys چیه و چطوری کار میکنه.

HTTP.sys یه درایوره که در سطح هسته سیستم عامل کار میکنه و کلی کار انجام میده. همین درایور به اپلیکیشن این قابلیت رو میده که مستقیم به اینترنت وصل بشه و ریکوئست‌های کاربر رو دریافت کنه. درحالی که میگن Kestrel نباید مستقیم به اینترنت وصل بشه و ریکوئست‌های کاربران رو مستقیم دریافت کنه.Kestrel حتما باید پشت یه Reverse Proxy مثل nginx یا IIS باشه. HTTP.sys خیلی قابلیت داره حتما در موردش بخونید.

اشتباهی که ما انجام داده بودیم این بود که اون اپلیکیشنی که ریکوئست‌ها رو ارسال میکرد یه Kestrel روی همون سروری بود که Kestrel روش ران شده بود. یعنی خود Kestrel به صورت مستقیم ریکوئست‌های ConsoleApp رو دریافت می‌کرد. همین کار باعث شد که بعد از چند ثانیه کلی خطا روی Kestrel داشته باشیم.

تجربه‌ای که من توی این بدست آوردم این موارد بودن:

  • هر وقت یه اپلیکیشنی رو درست می‌کنید کامل بپرسید که این قراره چندتا ریکوئست رو هندل کنه.
  • قراره در چه مقیاسی کار کنه.
  • حتما حتما قبل اجرا روی سرور اصلی، حداقل یکبار اون سناریو رو شبیه سازی کنید.
  • وقتی به خطایی برخورد می‌کنید، سرسری ازش رد نشید و بدونید چرا این پیش اومده، همین باعث میشه کلی مطالب جدید یاد بگیرید و به تجربیاتتون اضافه بشه

اینجا هم چندتا رفرنس در مورد Http.sys میزارم که بخونید و به دانشتون اضافه بشه:

Powered by Froala Editor

نظرات