تحلیل ترافیک در میدان یکتانت

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

هیچ وقت فکر نمی‌کردم چیزهایی که در آزمایشگاه شبکه به ما یاد می‌دادند، مثل wireshark، یه روزی توی کار به دردم بخوره. البته شاید هر جایی هم لازم نباشه که آدم با ابزارهای خاص شبکه سیستمش رو تحلیل کنه. حدس من اینه که در جاهایی که اندازه سیستم بزرگ می‌شه، بعضی وقتا، لازم می‌شه. یکتانت هم به عنوان یک بازار تبلیغاتی بزرگ مستعد اینه که با مسائلی مواجه بشه که - اقلا برای کسی مثل من که تجربه زیادی نداشتم - لازم باشه که از ابزار استفاده کنه تا بتونه مسئله رو بررسی و در نهایت حل کنه. دوستان از پشت صحنه اشاره می‌کنند که حل مسئله یکی از ارکان فرهنگ یکتانته :))

یک - قله‌های تیز مشکوک در ترافیک ارگانیک

مسئله‌های اول و دوم مربوط به زمان قطعی اینترنت بین‌الملل میشه که باعث شد نمایش تبلیغات ما در وبسایت‌های داخلی هم متوقف بشه. یکتانت به عنوان پلتفرم تبلیغات کلیکی، هر لحظه که یکی از سرویس‌هاش کار نکنه، به صورت خطی براش ضرر مالی مستقیم داره و مهم‌تر از اون اعتباریه که مردم برای این پلتفرم قائلند. تصویر با‌کیفیت و ایمن سیستم در صورتی که خرابی سرویس‌ها طولانی باشه خدشه دار می‌شه. پس ما سریعا تصمیم گرفتیم که با تغییر دادن توپولوژی شبکه سرویس‌رسانی، مشکل رو حل کنیم و دوباره نمایش تبلیغاتمون رو برقرار کنیم. خوش‌بختانه در زمانی که ما زندگی می‌کنیم بیزینس‌هایی بومی مثل ابر آروان وجود دارند که خدمت شبکه توزیع محتوا (CDN) و واسطه‌ی ابری رو ارائه می‌دن. یعنی چیزی مشابه خدمتی که CloudFlare ارائه می‌ده. ما برای حل مسئله لازم بود که از CloudFlare روی یک سرویس داخلی سوئیچ کنیم.

بعد از این که تغییرات لازم رو انجام دادیم و از ابر آروان استفاده کردیم یک الگوی عجیب در ترافیک تبلیغاتمون مشاهده کردیم. جا داره اولین ابزار رو همین‌جا به شما معرفی کنم که در روزهای سرد و گرم زندگی در عین سادگی‌اش در کنار بچه‌های فنی یکتانت بوده. یکی از ابزارهایی که ما استفاده می‌کنیم netdata است که به محض این که روی سیستمت نصبش کنی کلی اطلاعات مفید رو برای مانیتور کردن زیرساخت در اختیارت می‌ذاره. این ابزار بود که به ما کمک کرد این مشکل رو کشف کنیم. نمودار زمانی تعداد درخواست‌های سامانه در هر ثانیه به شکل زیر در اومده بود که اصلا چیزی نیست که طبیعی باشه.

نمودار تعداد درخواست بر ثانیه
نمودار تعداد درخواست بر ثانیه


چیزی که در این نمودار مشاهده می‌کنید اصلا طبیعی نیست چرا که ترافیک مشاهده‌ی تبلیغات (صفحات وب فارسی) یک ترافیک کاملا ارگانیکه و توسط سیستم‌ها ایجاد نمی‌شه. و ربات‌ها هم هیچ‌وقت در حد و اندازه‌ای نیستند که در رقابت با کاربران واقعی بتونن همچین الگوی ترافیکی‌ رو ایجاد کنند. ترافیکی که طبیعی باشه و از سمت کاربر بیاد از این قله‌های تیز نداره. اگه بخواد همچین اتفاقی بیفته احتمالا باید شاهد همچین چیزی در خبر سراسری باشیم:

- جناب آقای حیاتی: «خوب هموطنان عزیز با شمارش من همگی با هم صفحه‌های موبایلتون رو رفرش کنید. یک، دو، سه … حالا دوباره،‌ یک، دو، سه ...»


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

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

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

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

دو - کانکشن‌های یتیم خیلی زیاد (منظور همون کانکشن‌های orphan عه)

مشکل ما تعداد غیر طبیعی و زیاد کانکشن‌های یتیم بود که باعث می‌شد منابع سرور تموم بشه و دیگه کانکشن جدید نشه زد. شاید برای شما عجیب باشه ولی کانکشن‌ها هم مثل آدم‌ها یتیم می‌شن. حتی کانکشن‌ها رفوزه هم می‌شن :) برای کسایی که کمتر آشنا هستند بگم که کانکشن وقتی یتیم می‌شه که پردازه‌ی صاحبش از بین بره ولی کانکشن باقی بمونه.

همون موقعی که ما به CDN داخلی سوئیچ کردیم دیدیم که درخواست‌های دریافت عکس‌های تبلیغاتی به شکلی باعث می‌شن کانکشن‌های یتیم و در پی اون تعداد کانکشن‌های اشغال شده زیاد بشه.

کسی که این واقعیت رو به ما نشون داد باز netdata بود. باید بگم که netdata کلی هشدار از پیش آماده داره که وقتی اونو روی سرورتون نصب می‌کنید معیارهای مختلف رو رصد می‌کنه و در صورتی که غیر طبیعی باشن به شما هشدار می‌ده. خلاصه ایشون به ما هشدار داد که کانکشن‌های یتیم زیاد شده‌اند.

من هم برای حل این مشکل تصمیم گرفتم با ابزار wireshark که در دانشگاه ازش استفاده کرده بودم ترافیک سرور رو در لایه TCP تحلیل کنم و ببینم که چرا کانکشن‌ها یتیم می‌شن. البته wireshark برای استفاده در محیط بدون گرافیک سرور مناسب نیست و من از tshark استفاده کردم. چیزی که مشاهده کردم این بود که علی‌رغم این که CDN می‌خواست کانکشن TCP رو ببنده و دستور FIN رو ارسال می‌کرد ولی nginx که وظیفه سرو کردن عکس‌ها رو داشت دستور FIN رو نمی‌فرستاد و صبر می‌کرد. بسته‌های یکی از کانکشن‌ها رو می‌تونید در زیر ببینید:

بسته‌های مربوط به یکی از کانکشن‌های یتیم
بسته‌های مربوط به یکی از کانکشن‌های یتیم


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

علت این که nginx دستور پایان کانکشن رو ارسال نمی‌کرد این بود که ابر آروان از هدر Keep-Alive در لایه HTTP استفاده می‌کرد و این باعث می‌شد که nginx در لایه TCP اش، کانکشن رو باز نگه داره تا شاید چیز دیگه‌ای برای ارسال به کاربر وجود داشته باشه. با کاهش مدت زمان کانکشن‌های Keep-Alive از ۶۰ ثانیه به ۱۵ ثانیه این مشکل حل شد.

سه - دامنه که فیلتر شده باشه رفتار HTTPS چه شکلی می‌شه؟

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

باز هم wireshark رو وارد میدان کردم و صفحه رو لود کردم. جالبه که بدونید درخواست‌های HTTPS قبل از این که از حالت رمز در بیان، لازمه که مشخص باشه مربوط به کدوم وبسایت روی یک سرور هستند. حالتی رو فرض کنید که چند وب‌سایت روی یک سرور در حال سرو شدن باشند. و هر کدوم برای رمزنگاری از کلید‌های مختلف استفاده کنند. در این صورت حتما لازمه که در داده‌های غیر رمز شده‌ی HTTPS چیزی باشه که مشخص کنه درخواست مربوط به کدوم وبسایت (دامنه) می‌شه.

برای همین در یکی از مراحل HTTPS بسته‌ای به عنوان ClientHello ارسال می‌شه که شامل ServerName مربوط به درخواسته. نتیجه‌گیری اخلاقی‌ای که اینجا می‌شه کرد اینه که اگه جایی هستید که ترافیکتون شنود می‌شه، شاید محتویاتتون رو با HTTPS به صورت ایمنی جابجا کنید؛ ولی اگه مثلا به سایت خاصی برید، کسی که داره ترافیکتون رو شنود می‌کنه می‌فهمه که به اون سایت رفتید؛ حتی اگه در حال استفاده از HTTPS باشید.

همین موضوع کمک می‌کنه که سامانه فیلترینگ بتونه درخواست‌های HTTPS ای که برای دامنه‌های فیلترشده هستند رو قطع کنه. رفتاری که نهایتا شما مشاهده‌ خواهید کرد اینه که یک کانکشن TCP ایجاد می‌شه و HTTPS پیش می‌ره و بعد از این که نام سرور مورد نظر از سمت مرورگر ارسال می‌شه دیگه هیچ پاسخی از سمت سرور دریافت نمیشه، انگار که دیگه هیچ پاکتی در اون اتصال TCP قابلیت رفت و آمد نداشته باشه و این باعث می‌شه که سمت مرورگر یک Timeout اتفاق بیفته.

راستی به دلیل این که درخواست HTTPS هست و سامانه فیلترینگ کلید سرور اصلی رو نداره نمی‌تونه به جای سرور اصلی جواب شما رو بده و شما رو به peyvandha بفرسته. به این شکل مطمئن شدم که دامنه‌مون فیلتره و بعد از اون درخواست خاصی دادیم که مشکلش رفع بشه.

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

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