Руководства

Пики нагрузки: как подготовить сервер к распродаже или рекламе

Пики нагрузки: как подготовить сервер к распродаже или рекламе

Сервер, который спокойно работает весь год, обычно ложится в тот единственный день, когда посетителей больше всего: распродажа, рассылка по всей базе, реклама у крупного блогера, Чёрная пятница. То есть ровно тогда, когда каждая минута простоя стоит дороже всего. Хорошая новость: в отличие от атак, такие пики известны заранее, и подготовиться к ним можно спокойно и дёшево. Ниже — как оценить ожидаемую нагрузку, найти потолок сервера до того, как его найдут покупатели, что даёт больше всего запаса и план по дням.

Сколько нагрузки ждать: прикидка на салфетке

Начните с цифр, а не с ощущений. Пример: рассылка на 50 000 подписчиков, из них откроют и перейдут на сайт 10% — 5 000 человек, большинство в первый час. Каждый посмотрит в среднем 6 страниц. Это 30 000 запросов страниц в час, или около 8 в секунду в среднем. Но трафик неравномерен: в первые 10–15 минут после отправки пик в 3–5 раз выше среднего — 25–40 запросов страниц в секунду.

Теперь сторона сервера. Динамическая страница на типичной CMS без кэша стоит 100–200 мс процессорного времени. Одно ядро успевает отдать 5–10 таких страниц в секунду. Чтобы выдержать 40 в секунду без кэша, нужно 4–8 ядер, работающих на пределе. С кэшем те же 40 запросов в секунду отдаёт одно ядро, почти не напрягаясь.

Цифры грубые, и для вашего проекта будут другими, но порядок величин и главный вывод сохраняются: кэш даёт больше, чем любой апгрейд.

Найдите потолок до того, как его найдут пользователи

Догадки здесь бесполезны: одна страница может стоить в двадцать раз дороже другой. Потолок проверяется нагрузочным тестом — инструмент имитирует растущее число посетителей, а вы смотрите, при каком количестве время ответа начинает расти и появляются ошибки.

Удобный инструмент — k6. Сценарий описывается простым скриптом:

import http from 'k6/http';
import { sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 50 },
    { duration: '5m', target: 200 },
    { duration: '2m', target: 0 },
  ],
};

export default function () {
  http.get('https://example.com/catalog/');
  http.get('https://example.com/search?q=куртка');
  http.get('https://example.com/product/123/');
  sleep(1);
}

Запуск без установки: docker run --rm -i grafana/k6 run - < test.js. В отчёте смотрите на http_req_duration (особенно p(95) — время, в которое уложились 95% запросов) и http_req_failed.

Три вещи, которые портят результат:

  • Тестировать только главную. Она обычно закэширована и держит что угодно. Реальный потолок задают каталог с фильтрами, поиск, корзина и личный кабинет — включайте их в сценарий.
  • Запускать тест с того же сервера. Тогда вы измеряете сервер и генератор нагрузки вместе. Генератор должен быть снаружи — например, отдельный Lite за $6 в другой локации на время подготовки.
  • Тестировать боевой сервер днём. Хороший способ устроить себе аварию досрочно. Используйте копию сайта или ночное окно.

Во время теста держите открытыми htop и iostat -x 5 на сервере: так видно, во что именно упираетесь — процессор, память или диск. От этого зависит, что лечить.

Что даёт больше всего запаса

1. Кэш страниц

Самый большой выигрыш при наименьших усилиях. Страница, которая не зависит от конкретного пользователя, отдаётся из кэша Nginx без запуска PHP и обращения к базе — разница с генерацией обычно два порядка. Для каталога и карточек товаров даже кэш на 30–60 секунд («микрокэш») снимает основную нагрузку, а цены и остатки остаются почти актуальными. Корзину, оформление заказа и личный кабинет из кэша исключите.

2. Статику — в CDN

Картинки, стили и скрипты — это обычно 70–90% трафика по объёму. Вынесите их в CDN, и сервер будет заниматься только HTML. Заодно страницы быстрее откроются у далёких пользователей.

3. Тяжёлое — в очередь

Всё, что не обязано выполняться прямо сейчас, — письма о заказе, уведомления, выгрузки в CRM и на маркетплейсы, обработку картинок — выносите в фоновые задачи. Пользователь получает ответ сразу, а тяжёлая работа рассасывается за минуты после пика.

4. PHP-FPM под реальную память

Число рабочих процессов PHP — частая причина падения в пике. Мало процессов — запросы встают в очередь; много — кончается память, и ядро убивает базу. Посчитайте средний размер процесса:

ps --no-headers -o rss -C php-fpm8.3 | awk '{s+=$1} END {print s/NR/1024 " MB"}'

Затем pm.max_children = память, которую можно отдать PHP, ÷ размер процесса. Например, 2 ГБ ÷ 60 МБ ≈ 30 процессов.

5. База данных

Включите журнал медленных запросов за пару недель до пика и разберите топ-5 — обычно это недостающие индексы на фильтрах каталога. Проверьте, что кэш базы настроен под память сервера, а не оставлен по умолчанию. Подробно — в статье «База данных на VPS».

6. Лимиты на дорогие операции

Разумный потолок частоты запросов на поиск и фильтры защищает от того, что несколько ботов-парсеров или слишком активных клиентов займут все ресурсы в самый неподходящий момент. Как настроить — в статье «Как защитить сервер от DDoS и пережить всплески трафика».

Временно увеличить тариф

Если пик известен по датам, разумно поднять тариф заранее. Переход на старший тариф выполняется без переноса данных, и неделя на Premium вместо Medium стоит несколько долларов — несопоставимо с ценой одного часа простоя в распродажу. Возможен ли обратный переход на младший тариф после пика и как он делается, уточните у провайдера заранее: обычно для этого занятое место на диске должно укладываться в лимит младшего тарифа.

Делайте это за несколько дней, а не в последний час: после апгрейда прогоните тест ещё раз и убедитесь, что узкое место действительно сдвинулось. Бывает, что упирается не в ресурсы, а в настройку — например, в pm.max_children, — и новые ядра ничего не дают, пока её не поправить.

Если узкое место — один тяжёлый поток (сложный расчёт корзины, генерация документов, 1С-обмен), полезнее не больше ядер, а выше частота: HI-CPU на Ryzen до 5.7 GHz. Как вообще считать нужные ресурсы — в статье «Как выбрать тариф VPS».

Premium в Финляндии под пик — $40/мес   Lite в Нидерландах под нагрузочный тест — $6/мес

Не забудьте про внешние сервисы

Сервер может выдержать, а упадёт что-то вокруг:

  • Платёжный шлюз — у некоторых есть лимиты на частоту запросов. Уточните заранее.
  • Почта — сервис транзакционных писем может ограничить отправку при резком всплеске, а свой почтовый сервер — попасть в спам из-за объёма. Письма о заказах должны уходить через очередь.
  • SMS, маркетплейсы, CRM — их API тоже имеют лимиты, и синхронная интеграция в момент оформления заказа превратит их ограничение в ваше.

План по дням

За 2–3 недели

  • Прикинуть ожидаемую нагрузку по формуле выше.
  • Прогнать нагрузочный тест по реальному сценарию покупателя, найти потолок и узкое место.
  • Включить журнал медленных запросов и разобрать его.
  • Настроить кэш, вынести статику в CDN, тяжёлые операции — в очередь.

За неделю

  • Поднять тариф, если тест показал нехватку ресурсов.
  • Повторить тест и убедиться, что запаса хватает минимум вдвое от ожидаемого пика.
  • Настроить мониторинг с уведомлениями: доступность, время ответа, память, диск.

За день

  • Заморозить выкладки: никаких обновлений кода, плагинов и CMS до окончания пика.
  • Сделать свежий бэкап и проверить, что он разворачивается. Как устроить хранение копий — в статье «Сервер для бэкапа».
  • Пройти путь покупателя целиком: от карточки до письма с подтверждением.
  • Договориться, кто дежурит и кто принимает решения.

Во время пика

  • Смотреть на мониторинг, а не на ощущения.
  • Иметь план Б: какие тяжёлые блоки можно отключить одним переключателем (рекомендации, «похожие товары», живой поиск), чтобы освободить ресурсы для оформления заказов.
  • Если сайт всё же упал — действовать по порядку из статьи «Что делать, если сайт упал», а не перезагружать всё подряд.

После

  • Вернуть тариф, если поднимали временно.
  • Разобрать графики: где был потолок, что упёрлось первым. Эти данные — лучшая подготовка к следующему пику.

Коротко

  • Посчитайте ожидаемую нагрузку: подписчики × переход × страницы, с запасом в 3–5 раз на пиковые минуты.
  • Найдите потолок нагрузочным тестом с отдельной машины, по реальному сценарию, не только по главной.
  • Больше всего запаса даёт кэш, затем CDN для статики и очереди для тяжёлого.
  • Тариф поднимайте за несколько дней и проверяйте повторным тестом.
  • За день — заморозка выкладок, бэкап, дежурный и план Б.