چگونه یک وب اپلیکیشن را به‌طور مؤثر مقیاس‌بندی کنیم؟


۰


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

می‌توانم حدس بزنم الان در ذهن خوانندگان حباب‌های اعتراض درباره مواردی مثل CDN (شبکه تحویل محتوا)، کشینگ، بالانس‌کننده‌ی بار (Load Balancer) و اتواسکیلرها ایجاد شده است. بله، همه‌ی این‌ها تکنیک‌های عالی‌ای هستند — اما فقط وقتی کاربرد دارند که واقعاً نیاز باشد. فرض کن نرخ ترافیک سایتت به حداکثر هزار درخواست در ساعت می‌رسد، در این صورت راه‌اندازی کش، لود بالانسر و چند نمونه سرور وب باعث پیچیدگی و افزایش هزینه عملیاتی می‌شود بدون اینکه ارزش افزوده‌ای داشته باشد. از طرفی اگر مطمئنی سایتت میلیون‌ها کاربر روزانه خواهد داشت، حتماً باید از همان ابتدا معماری را برای چنین بار سنگینی طراحی کنی. این کار هزینه و تلاش زیادی دارد، بنابراین امیدوارم تخمین‌هایت درست باشد.

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

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

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


زمان پاسخگویی صفحات

شرکت‌هایی که در فضای اینترنت کسب‌وکار می‌کنند یا تبلیغ می‌کنند می‌دانند که SEO (بهینه‌سازی موتور جستجو) و زمان بارگذاری صفحات عوامل کلیدی در جذب، حفظ و تبدیل بازدیدکنندگان هستند. بر اساس تجربه من، SEO بیشتر به ورودی‌های بازاریابی و محصول بستگی دارد، در حالی که زمان بارگذاری صفحه مسئولیت مهندسی است.

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

بارگذاری طولانی‌تر صفحات منجر به افزایش پرش و کاهش نرخ تبدیل می‌شود. گوگل از ژوئیه ۲۰۱۸ سرعت را در رتبه‌بندی صفحات وارد کرده است و آپدیت‌های بیشتری نیز برای بهار ۲۰۲۰ برنامه‌ریزی شده بود اما به دلیل همه‌گیری کرونا به ۲۰۲۱ موکول شد.

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

نمونه‌ای از زمان بارگذاری ۲ ثانیه‌ای: ۰.۳ ثانیه در مرورگر، ۰.۸ ثانیه اینترنت، و ۰.۹ ثانیه سرور وب

زمان بارگذاری نمونه به تفکیک زمان صرف شده روی مرورگر، انتقال در اینترنت و وب اپلیکیشن

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

مرورگر در حال ارسال درخواست به سرور وب که با پایگاه داده و ذخیره‌سازی فایل ارتباط دارد

نمونه‌ی مرورگر در حال ارسال درخواست به سرور وب که با سرویس‌های خارجی صحبت می‌کند

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


بهینه‌سازی مبتنی بر داده

یکی از رایج‌ترین هزینه‌های از دست رفته (Opportunity Cost) و علت پیچیدگی غیرضروری، بهینه‌سازی زودهنگام است. مهندسان نرم‌افزار از تجربه‌های قبلی برای شناسایی سریع راه‌حل‌ها برای چالش‌های جدید استفاده می‌کنند و راه‌حل‌ها را الگو‌-یابی می‌کنند تا به سرعت به نتیجه برسند. این معمولاً خوب جواب می‌دهد، ولی وقتی موضوع حل مشکلات عملکرد است، راه‌حل‌هایی که در یک پروژه عامل اصلی گلوگاه بودند، در پروژه دیگر الزاماً چنین نیستند.

مقیاس‌پذیری نرم‌افزار وب کار یکباره و تمام شونده نیست.

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

پس چاره‌ای نداریم جز اینکه بهینه‌سازی عملکرد را صرفاً بر اساس داده‌های واقعی انجام دهیم. سرویس‌هایی مانند Datadog APM و New Relic کل کد نرم‌افزارت را زیر نظر می‌گیرند، نقاطی را که بیشترین زمان در پردازش درخواست صرف شده نشان می‌دهند، مانند کوئری‌های کند پایگاه داده، خواندن فایل‌، یا زمان صرف شده در سلسله تماس توابع.

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

داشبورد با شاخص‌های کلیدی عملکرد AWS


روش کلی و کلی‌نگر

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

حالا اگر نظارت نشان ‌داد:

  • بیشتر زمان صرف ارائه دارایی‌های استاتیک (مثل عکس، CSS و جاوااسکریپت) می‌شود، آنها را به CDN (مثل CloudFlare یا AWS CloudFront) منتقل کن، تصاویر را برای وب و عملکرد بهینه کن، و کد CSS و جاوااسکریپت را Minify کن.
  • هنوز بیشتر زمان صرف بارگذاری تصاویر از CDN می‌شود، تصاویر Lazy Load کن به خصوص آنهایی که پایین صفحه (below-the-fold) قرار دارند.
  • بیشتر زمان صرف کوئری‌های پایگاه داده می‌شود، بررسی کن که آیا نتایج کوئری را می‌توان کش کرد، از تحلیل‌گر کوئری پایگاه داده برای اضافه کردن ایندکس‌ها، بازنویسی کوئری‌ها یا پیشنهادات دیگر استفاده کن (مثلاً پستگرس). یکی از اشتباهات رایج توسعه‌دهندگان استفاده از ORM است که باعث ایجاد n+1 selects می‌شود.
  • بیشتر زمان صرف رندر کردن پاسخ‌ها روی سرور می‌شود، ببین آیا می‌توان کل پاسخ یا بخشی از آن را کش کرد، و علت کندی را بررسی کن، ممکن است حلقه نامؤثر یا اطلاعات اضافی باشد که می‌توان فیلترش کرد.
  • پهنای باند دیسک زیاد استفاده می‌شود، ببین آیا سرور وب فایل‌های حجیم یا فایل‌های متعددی را بارگیری می‌کند؟ اگر پاسخ‌ها مستقیماً ارسال می‌شوند کش کردن آنها روی CDN یا حافظه توصیه می‌شود. اگر فایل‌ها در محاسبات استفاده می‌شوند، شاید بتوان بخشی از داده‌ها را پیش‌محاسبه و کش کرد.
  • بیشتر زمان صرف انتقال محتوای داینامیک یا رندر سمت مرورگر می‌شود، محتواهای پایین صفحه را Lazy Load کن.
  • بار پردازنده (CPU) بالا است، ببین تمام زمان در یک تابع خاص صرف می‌شود یا نه، اگر هست بین بازسازی کد و بهینه‌سازی آن (که ممکن است نشدنی باشد) یا مقیاس‌پذیری عمودی و افقی با لواد بالانسر و نمونه‌های موازی Trade-off انجام بده.
  • استفاده حافظه بالا است، نشت حافظه (Memory Leak) بررسی کن و اگر لازم بود RAM را افزایش بده. در برخی موارد نتایج کوئری بزرگ باعث پر شدن حافظه می‌شود یا الگوریتمی بیشتر از حد انتظار حافظه می‌گیرد که باید Refactor‌شود. گاهی باید به مقیاس‌پذیری عمودی روی آورد.
  • تأخیر شبکه بیشترین گلوگاه برای کاربران دور از سرور است، راهکاری پیدا کن که سرورهای وب را نزدیک‌تر به کاربرانت اجرا کنی.
  • تأخیر شبکه به صورت کلی گلوگاه است، مقیاس‌پذیری افقی یا عمودی ممکن است مشکل را در هاست ابری حل کند، وگرنه باید راهی برای افزایش پهنای باند شبکه به سرور پیدا کنی.

تکرار روی گلوگاه مهم فعلی

معمولاً خروجی ابزار APM زمان و درصد مصرف شده روی بخش‌های مختلف سیستم را هنگام پاسخ به یک درخواست مشخص می‌کند.

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

چرخه پایش و بهینه‌سازی

اگر برنامه وب روی پلتفرم ابری PaaS یا IaaS مستقر باشد، محیط توسعه محلی معمولاً مکان مناسبی برای ارزیابی عملکرد نیست.


رتبه‌بندی تاکتیک‌های بهبود عملکرد

فهرست شخصی‌سازی‌شده و بر اساس تجربه ۳۰ ساله‌ام از تکنیک‌های معمول به ازای بازدهی در برابر هزینه و تلاش است. تکنیک‌هایی که بیشترین اثر و کمترین هزینه را دارند از همه بهترند و بالعکس. تکنیک‌های کم‌اثر معمولاً نباید وقت صرفشان کرد، اما گاهی تکنیک‌های کم‌اثر و کم‌هزینه به صورت وسوسه‌کننده به نظر می‌رسند که به آنها snacking گفته می‌شود.

ماتریس تاثیر در مقابل تلاش


تکنیک‌هایی که معمولاً اهمیت زیادی دارند

  • تصاویر را در اندازه مناسب مقیاس کن و فشرده کن. به ویژه برای موبایل‌ها که شبکه کندتر، حافظه کمتر و قدرت پردازش کمی دارند.
  • دارایی‌های استاتیک را از طریق CDN خدمت‌رسانی کن: AWS CloudFront, GCP Cloud CDN, Azure CDN. اگر هاست ابری نداری از CloudFlare استفاده کن.
  • سرورهای وب را عمودی و افقی مقیاس بده تا CPU، حافظه و پهنای باند شبکه محدود کننده نباشند. اگر در فضای ابری هستی با شروع از نمونه کوچک تست کن: با اضافه کردن نمونه‌ها بررسی کن زمان پاسخ کاهش می‌یابد یا نه. اگر CPU یا حافظه اشباع شد، اندازه نمونه را بیشتر کن و دوباره با یک نمونه تست کن.
  • دارایی‌هایی که پایین صفحه هستند را Lazy Load کن.

تکنیک‌هایی که گاهی اهمیت دارند

این تاکتیک‌ها معمولاً پیش از تحلیل داده‌ها توسط توسعه‌دهندگان مطرح می‌شوند و می‌توانند پرهزینه و کم‌تاثیر باشند:

  • تنها جاوااسکریپت و CSS مورد نیاز هر صفحه را Minify و جدا کن (مثلاً با Webpack Code Splitting؛ یا ابزارهای مخصوص هر فریمورک مانند Flask-Assets یا ابزارهای ASP.NET).
  • کش کردن فایل‌ها، کوئری‌ها، محاسبات و رندر (البته مراقبinvalidate شدن کش باش).
  • جلوگیری از رندر مجدد غیرضروری SPAهای بزرگ.
  • بهینه‌سازی کوئری‌های پایگاه داده.
  • کاهش تعداد درخواست‌های AJAX پشت سر هم از SPA که ممکن است در مرورگر یا سرور صف شوند.
  • Lazy Load محتوای پایین صفحه (پیاده‌سازی آسان در SPA، اما برای صفحات رندر سمت سرور پیچیده‌تر است).
  • بهینه‌سازی ساختار داده‌ها.
  • انتقال منطق غیرهمزمان به Workerهای async. در مقیاس بالا، معماری Event-Driven می‌تواند مناسب باشد.
  • اجرای سرورها نزدیک جغرافیایی کاربران.
  • بهینه‌سازی الگوریتم‌ها.

تکنیک‌هایی که به ندرت اهمیت دارند

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

البته استثنا وجود دارد، مثلاً آماده‌سازی یک سامانه خرید بلیط که فروش بلیط برای ۵ کنسرت ۷۰,۰۰۰ نفری را در لحظه آغاز باز می‌کند.

  • انتخاب بین SQL و NoSQL
  • انتخاب بین Redis، Memcached و کشینگ‌های دیگر
  • انتخاب بین سرویس‌های ابری AWS, GCP, Azure, Oracle Cloud Infrastructure و غیره
  • انتخاب فریمورک‌های وب مثل Express، Flask، Rails و غیره
  • انتخاب کتابخانه‌ها و فریمورک‌های فرانت‌اند مثل React، Angular، Vue و غیره
  • انتخاب زبان برنامه‌نویسی مثل JavaScript، Python، Ruby، Go، C#، Java، Rust و غیره
  • انتخاب الگوهای معماری مثل MVC، MVVM، MVP و غیره

پیشرفت و جلوگیری از پسرفت در عملکرد

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

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

این کار می‌تواند با تست زمان پاسخ در تست‌های یکپارچه‌سازی، یا با ابزارهایی مثل Google Chrome Lighthouse انجام شود، یا سایر سرویس‌های ثالث که زمان پاسخ را تست می‌کنند.


پیش‌بینی رشد و آماده‌سازی سایت

وقتی سایت مدتی است رشد کرده، درآمد زیاد شده و نگرانی از رشد ناگهانی و تقاضای پیک وجود دارد، وقت آزمایش فشار (Load Testing) است.

Load Testing شبیه‌سازی رفتارهای واقعی کاربران است — مثل جستجو، افزودن کالا به سبد خرید، ایجاد حساب و پرداخت. از تحلیل داده‌های سایت می‌توان نرخ و نسبت این رفتارها را فهمید. کاربران را در ابزارهایی مثل Locust یا Apache JMeter مدل کن و ببین وقتی کاربران بالاتر از مقدار واقعی استفاده می‌کنند، سیستم چطور عمل می‌کند.

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


نتیجه‌گیری

مقیاس‌پذیری وب اپلیکیشن‌ها وقتی بر اساس داده‌ها و شواهد انجام شود، دیگر یک هنر حدسی و بدون پایه نیست. اندازه‌گیری دقیق و تحلیل سه‌باره قبل از هر کار، کلید تمرکز بهینه‌سازی‌ها است.

حدود ریسک بارگذاری تعریف کن، آنها را در تست‌های CI/CD بگنجان و اینطوری می‌توانی بی دغدغه روی ویژگی‌های جدید کار کنی بدون اینکه مردم از افت سرعت یا کاهش رتبه صفحه نگران باشند.

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


منابع خوب برای یادگیری بیشتر:


نظرات، دیدگاه‌ها و نقدهای شما حتما برای یادگیری و پیشرفت ما مفید هستند. خوشحال می‌شویم نظرتان را بدانیم!

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

سپاس ویژه از استنفنی چنی و سوفی پارکر بابت بازخوردهای بسیار مفیدشان!

دژ
داجنگو
جنگو
پایتون

۰


نظرات


author
نویسنده مقاله: حمید فیض‌آبادی

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

تمام حقوق این سایت متعلق به وبسایتcodebymeمیباشد.