Prowid Photos попала в подборку популярного блога. В пятницу вечером нагрузка выросла в десять раз: вместо привычных 350 RPS в пике — 3 500. Единственный сервер упёрся в 100% CPU, страницы открываются по восемь секунд, а потом начинаются ошибки 502. Что делать? Есть два пути: сделать сервер мощнее или добавить ещё серверов. От выбора зависит не только счёт за хостинг, но и то, как нужно писать приложение. В этом уроке разберём пределы одного сервера, вертикальное и горизонтальное масштабирование, главное требование к коду — stateless — и автомасштабирование.
Один сервер и его пределы
Любой сервер упирается в один из ресурсов: CPU, оперативную память, диск, сеть или число соединений с базой данных. Процесс Node.js выполняет JavaScript в одном потоке, поэтому один процесс использует одно ядро процессора (как задействовать все ядра — в уроке «Масштабирование: модуль cluster и stateless-приложения»).
Опасность в том, что сервер ломается не постепенно. Упрощённая модель очереди говорит: время ответа ≈ время обработки ÷ (1 − загрузка). При загрузке 50% запрос тратит вдвое больше времени, чем на пустом сервере, при 80% — в 5 раз, при 90% — в 10, при 95% — в 20. Реальные цифры отличаются, но «хоккейная клюшка» настоящая: поэтому серверы не грузят выше 60–70%.
💡 Прежде чем масштабировать, измерьте и найдите узкое место (
top,docker stats, метрики). Часто дешевле добавить индекс в базе данных или кеш, чем покупать сервер.
Вертикальное и горизонтальное масштабирование
Вертикальное (scale up) — сделать один сервер мощнее: больше ядер, памяти, быстрее диск. Просто, и код менять не нужно. Но у метода есть потолок: самая большая машина у облака ограничена (сотни ядер и терабайты памяти), а цена растёт быстрее мощности. К тому же сервер остаётся один — упал он, упал весь сайт, — а при смене размера машину обычно перезапускают.
Горизонтальное (scale out) — поставить рядом ещё серверы и распределять запросы между ними (балансировщику посвящён следующий урок). Потолка почти нет, потеря одного сервера не катастрофа, наращивать можно понемногу. Цена — сложность: нужны балансировщик, аккуратный деплой, мониторинг, а приложение обязано быть stateless.
| Вертикально (scale up) | Горизонтально (scale out) | |
|---|---|---|
| Что делаем | один сервер мощнее | больше серверов |
| Потолок | есть: самая большая машина | почти нет |
| Отказ сервера | лежит всё | остальные продолжают работать |
| Код приложения | не меняется | должен быть stateless |
| Сложность | низкая | выше: балансировщик, деплой, состояние |
Разумный порядок такой: измерить и оптимизировать, затем вырасти вертикально (самый простой шаг), но писать код так, чтобы его можно было размножить. Сколько экземпляров нужно? Берём пик, делим на нагрузку, которую безопасно дать одному экземпляру (≈ 70% от измеренного максимума), и прибавляем один запасной — экземпляры нужны не только для мощности, но и чтобы пережить падение одного из них (помните: два сервера по 99% дают 99,99%):