توی این مقاله تجربهای را به اشتراک میگذاریم که در تپسی در مدت دو ماه برای تعدادِ درخواست درحدود ۱۰ برابر حالت عادی (در برخی از بخشها تا ۱۷ برابر) آمادگی کسب کردیم.
در این مقاله در ابتدا تعریف صورت مسئله و چالشهای آن را مرور میکنیم، و بعد از آن به نحوهی انجام لودتست و همچنین گرفتن بازخورد در بخشهای مختلف آن خواهیم پرداخت. این مقاله به جزئیات فنی نمیپردازیم و مسیر حل مسئله را با هم مرور میکنیم، در آینده در مقالههای دیگر به جزئیات بیشتری خواهیم پرداخت.
داستان از این قرار بود که در یک برنامهی تلویزیونی از بینندگان خواسته میشد که اگر همانلحظه اپلیکیشن را باز کنند، کد تخفیف میگیرند یا در قرعهکشی میتوانند شرکت کنند یا در نقشه به دنبال کد تخفیف بگردند و مواردی شبیه این. تجربهی سالهای گذشته این برنامه به ما نشون داد که باید برای تعداد درخواست در ثانیهی (TPS) بیشتر از ۷ برابر در باز شدن اپلیکیشن (نسبت به بیشترین حجم درخواستی که در گذشته براش آماده بودیم) و تعداد ثبتنام بیشتر از ۱۵ برابر بیشترین ثبتنام آماده میشدیم.
۱- عدم اطلاع دقیق از تعداد درخواست: ما با توجه به اعداد برنامه در سالهای گذشته در مورد نرخ درخواستها تخمین داشتیم ولی تخمین بود و اطلاعی از نرخ دقیق نداشتیم و باید برای بیشترین چیزی که تصورش رو میکردیم آماده میشدیم، برای همین باید به صورت کاملاً بدبینانه (البته خوشبینانه از نظر تعداد کاربر) آماده میشدیم.
۲- تغییر در رفتار کاربر: رفتار کاربر با اپلیکیشن به طور کامل در بازهی برنامه تغییر پیدا میکرد، و برای مثال اگر در یک مایکروسرویس درخواست A در گذشته بیشترین تعداد بود، در این برنامه ممکن بود درخواست B که تعدادش کم بوده بیشتر شود. مثلاً وارد کردن کد تخفیف درخواستیست که در زمانهای پربار سیستم خیلی تحت تأثیر قرار نمیگرفت ولی در این برنامه نیاز بود که عملکرد خیلی خوبی داشته باشد. در نتیجه شناخت کامل محصول، رفتار کاربر و رفتار احتمالی کاربر از مواردی بود که پیش از هرکاری لازم بود انجام شود.
۳- افزایش ضربهای تعداد درخواست: نرخ درخواستها به صورت ضربهای افزایش پیدا میکرد، و ابزارهای scaling که در کوبرنتیس مورد استفادهی ما بودند، به طور خاص در این مورد پاسخگوی نیازهای ما نبودند و باید برای این موضوع هم فکری میکردیم.
۴- عدم اطلاع از زمان دقیق برنامه: با توجه به تغییرات در برنامهها، زمان دقیق برنامه و افزایش تعداد درخواست مشخص نبود.
۵- تلاش برای کاهش هزینهها: یکی از اهداف ما این بود که با اضافه کردن کمترین سختافزار ممکن و با استفاده از منابع قبلی برای این برنامه آماده بشیم.
۶- مدیریت پروژه در بین تیمهای مختلف: در این پروژه تیمهای مختلفی درگیر بودند، ۴ تیم بکندی، ۲ تیم از وب و تیم زیرساخت، ایجاد هماهنگی بین این تیمها و بررسی خروجی کامل این کارها در کنار یکدیگر هم از چالشهای این پروژه بود.
۱- شناسایی نیازمندیها، محصولات تحت تأثیر و رفتار کاربران:
در ابتدا تیم فنی با همکاری تیم محصول، تمامی مسیرهایی که کاربران در طول برنامه به آن با احتمال (conversion) بیشتری مراجعه میکردند را استخراج کردند، بعد از تیم فنی APIها و مایکروسرویسهایی که در این فانل شناسایی کردند و بررسی دقیق پرفورمنس این سرویسها به تیمهای مربوطه واگذار شد.
اهمیت این شناخت بسیار بالا است، در دو ماه اجرای برنامه به طور کلی ۳ دقیقه داونتایم رو تجربه کردیم، دلیل این داونتایم فیچری بود که به صورت دقیقه ۹۰ی ۲۴ ساعت قبل از پخش برنامه بدون هماهنگی کامل در برنامه قرار گرفته بود و باعث لود بسیار بالا در بخش نقشه میشد، و عدم آمادگی ما برای این فیچر باعث شد که نتوانیم آمادگی کامل را برای این بخش داشته باشیم.
۲- بررسی فیچرهایی که در زمان برنامه مورد نیاز نیست (degraded mode):
با هدف کاهش مصرف منابع، در کنار شناسایی فیچرهای پرکاربرد در بازهی زمانی برنامه، در جهت کاهش هزینه و منابع تصمیم گرفتیم تا بخشهایی از سیستم که در طول برنامه نیاز به آن وجود ندارد، یا در تجربهی کاربری در آن زمان تأثیر قابل توجهی ندارد خاموش شود و ریسورسهای این فیچرها در اختیار سناریوهای مهم قرار بگیرد. برای مثال فیچرهایی برای بالا بردن دقت مچینگ (انتخاب رانندهی مناسب برای مسافر) وجود دارد که در زمان برنامه با توجه به این کاربران درخواست سفر نمیدهند اهمیت بالایی ندارد، و میتواند خاموش شود. این فیچرها و میزان مصرف ریسورس در آنها مشخص و اولویت خاموش کردن فیچرها نیز با کمک تیم محصول مشخص شدند. این کار را با استفاده از feature flagها در بخشهای مختلف سیستم انجام دادیم. فیچرفلگ در تپسی مدتهاست برای خاموش و روشن کردن و همچنین اجرای A/B Testها مورد استفاده قرار میگیرد و فیچرهای مختلف اپلیکیشن از سمت سرور قابل کنترل هستند. این ابزار همچنین برای کنترل فیچرهایی که در اپلیکیشن تأثیر مستقیم ندارند و در بکند تأثیرگذار هستند، نیز استفاده میشوند.
۳- بررسی محصولات تحت تأثیر و بهبود نقاط قابل بهبود شناساییشده:
پس از انجام مرحلهی ۱، تیمهای مربوطه با بررسی ابزارهای در دسترس، مانیتورینگها و ابزار profiling به صورت آفلاین تلاش خود را برای بهبود نقاط قابل شناسایی هر مایکروسرویس انجام دادند. در این بررسیها، بهبود الگوریتم، کاهش تعداد i/o، موازی کردن بخشهایی از سرویسها و استفادهی بهتر از دیتابیس (ایندکس مناسب، کوئریهای بهتر و یا بهبود کشینگ) اقداماتی بود که برای بهبود بخشهای مختلف انجام شد.
۴- پیادهسازی زیرساختی لودتست (Load test tool):
انجام اقدامات بالا به تنهایی به ما اطمینان کامل برای میزان تحمل لود سیستم را نمیداد، لازم بود که در تمامی بخشهای تپسی از بهبود عدد دقیق پاسخگویی سیستم و تحمل آن را داشته باشیم.
یکی از مهمترین مراحل انجام کار انجام لودتست برای شناسایی نقاط شکست سیستم و همچنین شناخت بهتر از ظرفیت کلی سیستم بود.
انجام لودتست به روشهای مختلف قابل انجام بود:
۵- پیادهسازی ابزار اسکیلینگ (auto/manual scaling tool):
همانطور که در ابتدا گفته شد با توجه به ضربهای بودن افزایش لود (۱۰ برابر شدن لود کلی در کمتر از دو دقیقه)، ابزارهای autoscalingی که استفاده میکردیم برای ما سرعت پاسخگویی کافی را نداشتند و امکان چند برابر شدن تعداد instanceهای مایکروسرویسهای مختلف در دو دقیقه وجود نداشت.
با توجه به این که برنامه در ساعت نسبتاً مشخصی پخش میشد، با ایجاد یک ابزار دستی، هر روز ۱۰ دقیقه قبل از برنامه اسکیل کلیهی مایکروسرویسها که با توجه به خروجی لودتست مشخص شده بود تعیین میشد و پس از برنامه به حالت قبلی برمیگشت.
۶- آمادگی برای شرایط اضطراری:
با وجود تمامی اقدامات بالا، با توجه به ناشناخته بودن حجم درخواست و نوع آن در اجراهای ابتدایی، لازم بود خودمون رو برای شرایط خاص آماده کنیم. در هرکدام از بخشهای سرویسها، مسئول سرویس راهحلهای اضطراری را از دو نوع آمادهی اجرا بودند. حذف فیچرهایی که از نظر تجربهی کاربری مورد نیاز بودند و همچنین دراپ کردن درخواستهای یک سرویس در شرایطی که تعداد درخواست بسیار بیشتر از پیشبینی ما بودند.
در اجراهای ابتدایی برنامه و در زمانهایی که انتظار تغییر رفتار کاربر رو داشتیم تیم آنکال مسئولیت مشاهده و مانیتور سیستم و رفتن به شرایط اضطرار (با کمک فیچرفلگها) را داشتند.[۲]
در نهایت با انجام فرآیندهای ذکرشده، به صورت متناوب و بازبینی شرایط باعث شد به جز یک مورد که در بالا ذکر شد، کاملاً شرایط تحت کنترل باشد و بتوانیم تعداد درخواست ۱۰ برابری را با موفقیت و با کیفیت سرویس مورد انتظار انجام دهیم.
منابع:
[1] https://www.artillery.io/blog/load-testing-in-production
https://sre.google/sre-book/testing-reliability/
[2] https://sre.google/sre-book/reliable-product-launches/
https://sre.google/sre-book/handling-overload/