مهندسی نرم‌افزار

بلک فرایدی در اسنپ‌پی: مهندسی برای غیرممکن

آرمین بیات۹ دقیقه مطالعه

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

برای اسنپ‌پی، هر میلی‌ثانیه اهمیت دارد و هر سیستم باید بتواند زیر فشار، مستقل از مقیاس، پایدار باقی بماند. در سه سال گذشته، اسنپ‌پی از یک پلتفرم کوچک با تعداد محدودی میکروسرویس، به یک اکوسیستم مالی توزیع‌شده تبدیل شده که میلیون‌ها کاربر را در اپلیکیشن اسنپ و پارتنرهای مختلف پشتیبانی می‌کند. رشد، پیچیدگی می‌آورد و پیچیدگی هم مسئولیت می‌آورد؛ مسئولیت اینکه در مهم‌ترین لحظه‌ها، سیستم بدون خطا و با بهترین عملکرد کار کند. بلک فرایدی ۲۰۲۵ بزرگ‌ترین آزمون ما تا آن روز بود.

تعیین هدف‌ها: آپ‌تایم و مدیریت منابع

بعد از بررسی قطعی‌ها، رفتار سیستم در سال‌های گذشته و نقاطی که می‌توانستند در روزهای پیک برای ما ریسک ایجاد کنند، دو هدف اصلی برای تیم مهندسی تعریف کردیم:

هدف آپ‌تایم: ۹۹.۹٪

هدف مصرف منابع: حداکثر ۶۰٪ در پیک ترافیک

این دو هدف، جهت تمام تصمیم‌های معماری، زیرساختی و عملیاتی ما در مسیر آماده‌سازی برای بلک فرایدی بودند.

یادگیری از گذشته: تبدیل شکست‌ها به یک فریم‌ورک

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

  • کوئری‌های سنگین یا کند دیتابیس

  • تنظیمات اشتباه Connection Pool

  • تعداد ناکافی Replicaها

  • سرویس‌هایی که زیر فشار کال‌های تکراری دچار مشکل می‌شدند

  • فایل‌های استاتیکی که اشتباهاً به سرورهای بک‌اند می‌رسیدند

  • گلوگاه‌های Gateway

  • رفتارهای ناپایدار و غیرقابل پیش‌بینی در Cache

این تحلیل، پایه‌ای شد برای ساختن سیستمی که فقط قرار نبود از بلک فرایدی جان سالم به در ببرد؛ قرار بود آن را مدیریت کند.

قدم اول: خارج کردن فشار لایه ای‌کامرس از بک‌اند

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

برای این کار، معماری‌ای ساختیم که روی Arvan Edge و S3 کار می‌کرد. صفحات به‌صورت خودکار هر دو دقیقه به‌روز می‌شدند و صفحات کلیدی هم امکان به‌روزرسانی فوری داشتند. این یعنی تیم مارکتینگ برای کنترل محتوای صفحات، دیگر وابسته به تیم بک‌اند نبود و می‌توانست تقریباً در لحظه تغییرات خودش را اعمال کند.

اما ارزش اصلی این تغییر فقط استقلال مارکتینگ نبود. اتفاق مهم‌تر این بود که فشار لود از روی بک‌اند برداشته شد. سیستم عملاً می‌توانست هر تعداد درخواست را بدون ایجاد فشار روی سرویس‌های اصلی مدیریت کند. محاسبه دقیق تعداد کل درخواست‌هایی که از این مسیر جذب شد سخت است، اما برآورد ما این است که این معماری توانست بیش از ۸۶۴ میلیون درخواست اضافه را بدون افت عملکرد مدیریت کند.

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

قدم دوم: حذف کامل فشار فایل‌های استاتیک از بک‌اند

فایل‌های استاتیک، مثل تصویرها، بنرها و فایل‌های JSON، اگر در زمان پیک از طریق بک‌اند سرو شوند، می‌توانند بی‌سروصدا به قاتل عملکرد سیستم تبدیل شوند. برای همین یک قانون جدی گذاشتیم: تمام محتوای استاتیک باید ۱۰۰٪ از طریق CDN سرو شود.

نتیجه این تصمیم خیلی سریع خودش را نشان داد:

  • کاهش جدی مصرف CPU

  • افزایش پایداری زیر فشار

  • عملکرد قابل پیش‌بینی‌تر

  • حذف نیاز به Scale کردن اضافی برای محتوای استاتیک

از آن به بعد، فایل‌های استاتیک دیگر به سرورهای ما نمی‌رسیدند و در نتیجه دیگر ریسکی برای پایداری سیستم نبودند.

قدم سوم: لود شدن صفحه اصلی در یک چشم به هم زدن

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

هدف ما برای امسال بلندپروازانه بود: صفحه اصلی باید تقریباً لحظه‌ای لود شود و بتواند ۵۰ هزار درخواست در ثانیه را تحمل کند.

برای رسیدن به این هدف، از سمت فرانت‌اند روی Lazy Loading پیشرفته، Preload کردن فونت‌های اصلی اپلیکیشن، Preconnect به سرویس‌های مهم Third-party و Prefetch صفحات پرترافیک کار کردیم. همچنین Scroll Caching را بهبود دادیم، جریان داده بین کلاینت و سرور را بازطراحی کردیم و پنج کوئری سنگین بک‌اند را Cache کردیم؛ کوئری‌هایی که فقط یک بار در هر Session اجرا می‌شدند.

اما اینجا یک هدف مهم دیگر هم داشتیم. می‌خواستیم یکی دیگر از دغدغه‌های تیم مارکتینگ را حل کنیم: اینکه بتوانند هر تعداد Push Notification یا SMS که نیاز دارند ارسال کنند، بدون اینکه نگران پایداری بک‌اند باشند. در سال‌های قبل، زمان‌بندی و حجم این کمپین‌ها باید با دقت زیادی هماهنگ می‌شد، چون هر موج پیامک یا پوش می‌توانست ترافیک شدیدی به بک‌اند وارد کند. امسال این محدودیت از بین رفت.

در مجموع، بیش از ۱۵۰ میلیون Push Notification و SMS در بازه‌های پیک و غیرپیک ارسال شد و سیستم کاملاً پایدار باقی ماند. اسپایک‌های ترافیکی ناشی از پیام‌رسانی دیگر تهدیدی برای بک‌اند نبودند. مارکتینگ می‌توانست آزادانه کار کند و تجربه کاربر هم بدون مشکل باقی بماند.

نتیجه این تغییرات برای ما بسیار مهم بود:

  • کاهش قابل توجه فشار دیتابیس

  • تجربه سریع‌تر و روان‌تر برای کاربر

  • رندر شدن تقریباً لحظه‌ای صفحات

  • عملکرد پایدار در سطح ۵۰K RPS

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

قدم چهارم: کنترل هوشمند ترافیک؛ جلوگیری از Overload

در سال‌های قبل، هر درخواست ورودی مستقیماً به سرویس‌های بک‌اند می‌رسید و همین باعث می‌شد اسپایک‌های ناگهانی ترافیک، رفتار سیستم را غیرقابل پیش‌بینی کنند. امسال با استفاده از Arvan Edge، یک Virtual Waiting Room پیاده‌سازی کردیم تا فقط آن مقدار ترافیکی وارد سیستم شود که می‌توانستیم با اطمینان پردازش کنیم.

این تغییر جلوی چند ریسک اصلی را گرفت:

  • Burstهای ناگهانی ترافیک

  • خطاهای زنجیره‌ای و Cascading Failure

  • کمبود منابع در سرویس‌های حساس

  • افزایش ناگهانی Latency

از این نقطه به بعد، ترافیک برای ما قابل کنترل‌تر، قابل پیش‌بینی‌تر و پایدارتر شد.

قدم پنجم: بهینه‌سازی سراسری سیستم با کمک AI

با کمک تحلیل‌های مبتنی بر AI، الگوهای مصرف حافظه JVM، چرخه‌های Garbage Collection، تأخیر Redis، اشباع Thread Poolها و Throughput دیتابیس را بررسی کردیم. این تحلیل‌ها به ما کمک کرد نقاطی را ببینیم که شاید در بررسی‌های معمولی کمتر دیده می‌شدند.

نتیجه بسیار قابل توجه بود: ۵۰٪ کاهش در مصرف کل منابع سیستم و تقریباً دو برابر شدن ظرفیت تحمل بار، بدون اضافه کردن سخت‌افزار جدید.

قدم ششم: مقاوم‌سازی دیتابیس‌ها

دیتابیس یکی از حساس‌ترین بخش‌های سیستم مالی است و در بلک فرایدی باید کاملاً قابل اتکا باقی می‌ماند. برای همین منابع Master را سه برابر کردیم، تعداد Read Replicaها را از یک به سه افزایش دادیم و توزیع خواندن را بین Zoneهای مختلف متعادل کردیم.

در روز بلک فرایدی، Master تقریباً Idle باقی ماند؛ دقیقاً همان چیزی که از یک سیستم مالی پایدار انتظار داریم.

در کنار این کارها، لایه دیتابیس را هم بازطراحی کردیم تا بار خواندن و نوشتن به شکل واضح از هم جدا شوند. بخش زیادی از ترافیک Read-heavy به Replicaها منتقل شد و Master فقط روی عملیات حساس نوشتن تمرکز کرد. با استفاده از Cache تهاجمی، تعداد برخورد مستقیم به دیتابیس را کاهش دادیم و کارهای غیرضروری را به Pipelineهای Async منتقل کردیم تا در لحظه پیک، فشار اضافه‌ای روی هسته سیستم وارد نشود.

این تفکیک مسئولیت‌ها، یعنی Master برای Write، Replicaها برای Readهای پرتعداد و پردازش Async برای کارهای غیرحیاتی، باعث شد معماری دیتابیس ما بسیار پایدارتر، قابل پیش‌بینی‌تر و آماده‌تر برای تحمل لود شدید شود.

قدم هفتم: High Availability برای Redis

Redis نقش مهمی در Cache، Session و منطق‌های Real-time سیستم دارد. برای بلک فرایدی، کلاسترینگ Redis را تقویت کردیم، استراتژی‌های Failover را بهبود دادیم، Latency را کاهش دادیم و تلاش کردیم عملکرد Redis حتی زیر فشار شدید هم قابل پیش‌بینی باقی بماند.

قدم هشتم: ساخت یک میکروسرویس مستقل برای شناسایی کاربر

در معماری قبلی، یک سرویس هم‌زمان مسئول کاربران، مرچنت‌ها و عملیات ادمین بود. این مدل با رشد سیستم، ریسک ایجاد می‌کرد. برای همین یک میکروسرویس کاملاً مستقل برای User Identification طراحی و پیاده‌سازی کردیم.

این جداسازی معماری باعث شد مقیاس‌پذیری، پایداری و قابلیت Debug بهتر شود. در زمان پیک، سرویس‌ها دیگر اثر منفی مستقیم روی یکدیگر نداشتند، چون هر دامنه مسیر Scale، منابع و مرزهای عملیاتی خودش را داشت. به زبان ساده‌تر، هر بخش از سیستم می‌توانست «زندگی خودش را داشته باشد» بدون اینکه باعث ناپایداری بخش‌های دیگر شود.

نتیجه نهایی: یک فصل رکوردشکن

خروجی بلک فرایدی برای ما بسیار مهم و قابل توجه بود:

  • آپ‌تایم ۹۹.۴۴٪

  • مصرف فقط ۲۵٪ از ظرفیت سیستم در زمان پیک

  • پردازش بیش از ۱.۲۴ میلیارد درخواست در بلک فرایدی

  • عملکرد پایدار، قابل پیش‌بینی و قابل اتکا زیر فشار واقعی و شدید

بلک فرایدی همیشه برای تیم‌های مهندسی یک میدان نبرد است. اما امسال اسنپ‌پی فقط فشار را تحمل نکرد.

ما آن را فتح کردیم.

جمع‌بندی: بی‌رحمانه تست کنید، دائماً تیون کنید

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

Load Test، Stress Test، Fault Injection، Peak Replay، سناریوهای Chaos؛ همه این‌ها باید انجام شوند. هرچقدر بیشتر تست کنید، سیستم بیشتر ضعف‌های پنهان خودش را نشان می‌دهد. بهتر است خودتان این ضعف‌ها را پیدا کنید تا اینکه ترافیک واقعی کاربران آن‌ها را برایتان آشکار کند.

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

و مهم‌تر از همه: همه چیز را مستند کنید.

سیستمی که خوب مستند شده باشد، راحت‌تر تیون می‌شود، راحت‌تر Debug می‌شود، راحت‌تر Operate می‌شود و راحت‌تر تکامل پیدا می‌کند.

تست کردن، تیون کردن و مستندسازی، چک‌لیست‌های ساده نیستند؛ دیسیپلین‌های مداوم مهندسی‌اند. همین دیسیپلین‌ها بودند که به ما کمک کردند بلک فرایدی ۲۰۲۵ را از یک کابوس احتمالی، به یکی از جدی‌ترین پیروزی‌های مهندسی اسنپ‌پی تبدیل کنیم.

دیدگاه‌ها

دیدگاه‌ها پس از بررسی و تأیید منتشر می‌شوند.

  • هنوز دیدگاه تأیید‌شده‌ای وجود ندارد.