Розробники спостерігають, як їхній щойно запущений додаток починає гальмувати в ту саму мить, коли кілька тисяч користувачів натискають «go», і це уповільнення рідко є помилкою в коді — це боротьба процесора (CPU) та оперативної пам'яті (RAM) сервера за простір. Це «вузьке місце» проявляється у тривалому завантаженні сторінок, таймаутах або повних збоях, що негативно впливає на користувацький досвід, дохід і довіру до бренду.
Чому сервер, який добре працював у лабораторії, може повністю зупинитися в продакшні
Під час розробки один розробник надсилає лише кілька запитів, тому ресурси сервера більшу частину часу простоюють. Коли додаток виходить у реліз, кожен відвідувач створює запит, якому потрібні два основні компоненти:
- CPU (central processing unit) — процесор, який виконує кожен цикл, функцію та обчислення. Уявіть, що це шеф-кухар, який може готувати лише обмежену кількість страв одночасно. Одне замовлення обслуговується миттєво; сто замовлень означають, що кухар працює з тією ж швидкістю, але відвідувачі чекають довше.
- RAM (random-access memory) — оперативна пам'ять, тимчасове сховище для даних, які потрібні CPU під час обробки запиту. Це як робочий стіл, на якому шеф-кухар тримає інгредієнти для кожної страви. Якщо стіл заповнений, кухар мусить припинити приймати нові замовлення, доки місце не звільниться.
Коли тисячі користувачів входять у систему одночасно, кожен запит забирає свою частку процесорного часу та свій об'єм оперативної пам'яті. Обмежений пул обох ресурсів сервера розподіляється між запитами, і черга зростає. Сам сервер не став повільнішим; збільшився час очікування для кожного запиту.
Спокуса «просто купити коробку більшого розміру»
Початковою реакцією часто є оновлення машини — практика, яка називається вертикальним масштабуванням (vertical scaling). Додавання більшої кількості ядер CPU або більшого об'єму RAM дійсно покращує потужність: перехід з 4 ядер на 16 або з 8 ГБ на 64 ГБ дозволяє поглинути більший сплеск трафіку без зміни коду.
Однак вертикальне масштабування має жорстку межу:
- Фізичні обмеження — кожна материнська плата може підтримувати лише певну кількість ядер і обмежений об'єм пам'яті.
- Зменшення віддачі — кожне додаткове ядро або гігабайт коштує дорожче за попередній, тоді як приріст продуктивності зменшується.
- Єдина точка відмови — якщо цей надпотужний сервер вийде з ладу, зникне весь сервіс.
Через ці обмеження лідери індустрії — стрімінгові платформи, пошукові системи, сайти електронної комерції — відмовилися від використання однієї «монструозної» машини.
Альтернатива: розподіл навантаження між багатьма меншими коробками
Замість того, щоб будувати вищу вежу, оператори додають більше серверів помірного розміру і дозволяють їм спільно обробляти трафік. Такий підхід горизонтального масштабування (horizontal scaling) дозволяє тримати кожну машину в межах комфортної продуктивності та уникає експоненціального зростання витрат, характерного для вертикальних оновлень.
Координація багатьох машин потребує балансувальника навантаження (load balancer) — програмного або апаратного забезпечення, яке приймає кожен вхідний запит і перенаправляє його на сервер із найбільшим вільним ресурсом. Балансувальник приховує складність від клієнта; з точки зору користувача сайт все одно виглядає як єдина кінцева точка.
Горизонтальне масштабування також забезпечує стійкість. Якщо один вузол (node) виходить з ладу, балансувальник просто спрямовує трафік на інші справні вузли, підтримуючи роботу сервісу.
На що звернути увагу, коли ви починаєте додавати машини
- Безстанова архітектура (stateless design) — запити не повинні залежати від даних, що зберігаються лише в пам'яті конкретного сервера; інакше користувача може перекинути на вузол, у якого немає необхідного контексту. Використання спільних кешів або баз даних вирішує цю проблему.
- Перевірки стану (health checks) — балансувальник повинен мати можливість швидко виявити несправний сервер і припинити надсилати йому трафік.
- Політики автомасштабування (auto-scaling policies) — багато хмарних платформ дозволяють визначати пороги (використання CPU, затримка запитів), які автоматично запускають або вимикають екземпляри, узгоджуючи витрати з попитом.
Контраргумент: вертикальне масштабування не померло
Для невеликих команд або додатків із низьким трафіком один потужний сервер може бути найпростішим і найдешевшим рішенням. Якщо сплеск трафіку є передбачуваним (наприклад, запланований запуск продукту), тимчасове вертикальне оновлення може бути практичнішим, ніж розгортання цілого флоту нових екземплярів.
Головне — вчасно зрозуміти, коли трюк із «більшою коробкою» перестає приносити пропорційну вигоду, і почати планувати розподіл ресурсів.
Підсумок
Уповільнення роботи сервера після запуску зазвичай є проблемою конкуренції за ресурси, а не дефектом коду. Цикли процесора та слоти оперативної пам'яті є обмеженими, і коли надходить багато запитів одночасно, вони стають у чергу, що збільшує час відповіді. Вертикальне масштабування дає трохи більше запасу продуктивності, але невдовзі ви стикаєтеся з фізичними та економічними обмеженнями. Горизонтальне масштабування — додавання менш потужних серверів за балансувальником навантаження — пропонує дешевший і стійкіший шлях у міру зростання трафіку. Як тільки ви помітите, що черга подовжується, настане час оцінити, чи вистачить кількох додаткових ядер, чи варто почати розподіляти навантаження між багатьма машинами.
Джерело: стаття на dev.to «Why Servers Slow Down – CPU, RAM and the hidden cost of every request».
