Разработка высоконагруженного веб-сервиса для B2C: архитектура под пики и большое число пользователей

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

Обследование и замеры — от 200 000 ₽, 2–3 неделиПроверка нагрузочным испытанием по профилю пика, а не по среднемуИсходный код в вашем репозитории с первого коммита

С чем приходят

Когда сервис для массовой аудитории упирается в нагрузку

Рассылка или акция роняет сервис

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

Вечерами всё замедляется

Часто виновата не вся система, а одна операция: тяжёлый запрос, блокировка записи или медленный внешний сервис.

Рост запланирован, сервис писали на малую аудиторию

Никто не знает, где предел. Он находится испытанием, а не догадкой в день запуска рекламы.

Сервис ещё не написан, а запуск будет массовым

Часть решений нужно принять до первой строки кода: что кэшируется, что идёт через очередь, что отключается при перегрузке. На живом сервисе их менять труднее.

Профили нагрузки

Четыре профиля нагрузки: что страдает первым и с чего начинаем

У одного сервиса бывает несколько профилей, и каждый лечится своим приёмом.

Профиль
Пример сервиса
Что страдает первым
С чего начинаем
ПрофильМного чтенияпросмотры
Пример сервисаКаталог услуг, лента, афиша, расписание: большинство посетителей только смотрят
Что страдает первымПриложение и база, которые каждый раз собирают одну и ту же страницу
С чего начинаемКэш готовых ответов, реплики для чтения, раздача файлов отдельно от приложения
ПрофильПик по событиюстарт продаж, рассылка
Пример сервисаЗапись на ограниченное число мест, продажа по сроку, вход после уведомления
Что страдает первымВход, оплата и «горячие» записи: остаток, купон, место
С чего начинаемПрофиль пика, виртуальная очередь входа, ограничение запросов, порядок отключения функций
ПрофильПоток записисобытия, отметки
Пример сервисаСообщения, события клиентских приложений, показания, отметки пользователей
Что страдает первымТаблица, которая растёт быстрее остальных, и индексы на ней
С чего начинаемПриём через очередь, пакетная запись, разбиение таблицы по времени, правила хранения
ПрофильТяжёлые операциифайлы, отчёты
Пример сервисаОбработка загрузок, формирование документов, расчёты по запросу пользователя
Что страдает первымРабочие процессы заняты, остальные страницы ждут
С чего начинаемФоновые задачи с видимым статусом, отдельные очереди, лимиты на размер и число
Нагрузочная модель

Как мы считаем нагрузку: по пику, а не по размеру аудитории

Фраза «нужно выдержать много пользователей» не задание. Задание получается из нескольких измеренных или принятых величин.

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

  • Сколько людей работает одновременно в самый плотный час. Для действующего сервиса это берётся из журналов балансировщика и приложения. Для нового это гипотеза бизнеса, и мы так её и записываем: «принято как гипотеза, проверим после запуска».
  • Из чего состоит запрос в пик. Какая доля запросов читает, какая пишет, какая обращается к внешней системе.
  • Насколько быстро растёт пик. Рост за час и всплеск за минуту после уведомления лечатся по-разному: во втором случае не успевают ни добавление мощностей, ни прогрев кэша.
  • Что нельзя ронять ни при каком пике. Обычно это вход, оплата и оформленные заказы.

Как строим нагрузочное испытание

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

Число одновременных пользователей на выходе мы называем только по замерам на вашем стенде и не переносим с других проектов.

Слои сервиса

Кэш, реплики, очередь и фоновые задачи: что где работает и чем опасно

Каждый приём снимает один вид нагрузки и приносит свой риск.

Приём и что он снимает
Где применяем
Для каких данных
Чем рискуем
Приём и что он снимаетКэш готовых ответовповторное построение страниц
Где применяемПубличные страницы, каталог, ленты, справочники
Для каких данныхОдинаковое для многих; срок жизни зависит от того, как быстро данные должны обновляться
Чем рискуемПоказ устаревшего. Нужны правила сброса; персональные данные в общий кэш не кладём
Приём и что он снимаетКэш с ключом пользователяповторные запросы одного человека
Где применяемПрофиль, настройки, права, счётчики
Для каких данныхЧасто читается, редко меняется, сбрасывается при изменении
Чем рискуемЧужие данные при ошибке ключа. Проверяем тестом из-под двух учётных записей
Приём и что он снимаетРеплики базытяжёлое чтение
Где применяемОтчёты, поиск, истории, ленты
Для каких данныхДопускает отставание на секунды; запись и критичное чтение остаются в основной базе
Чем рискуемПользователь сохранил и не видит изменения. Читаем собственную запись из основной базы
Приём и что он снимаетОчередь записипиковая запись
Где применяемПриём событий, письма, обмен с внешними системами
Для каких данныхОтвет «принято», результат позже
Чем рискуемДубли и потери. Нужны повтор без повторного действия, список необработанного и статус
Приём и что он снимаетФоновые задачидолгие операции
Где применяемФайлы, обработка загрузок, пересчёты
Для каких данныхВсё, что длится дольше обычного ответа страницы
Чем рискуемПользователь не знает, готово ли. Показываем статус и уведомляем о завершении
Вход и боты

Вход, сессии и боты: наплыв, который нельзя отключить

К нагрузке от людей в массовом сервисе добавляются боты, перебор паролей и сборщики данных.

Вход ломается первым: все приходят в него одновременно, а он обращается и к базе пользователей, и к хранилищу сессий, и часто к сервису отправки кодов.

Сессии и токены

Серверные сессии в быстром хранилище (Redis или совместимое) позволяют мгновенно закрыть вход конкретного человека, но обращаются к хранилищу при каждом запросе. Подписанные токены с коротким сроком не требуют этого, но досрочно их отозвать труднее. Выбор зависит от того, что важнее: мгновенный отзыв или разгрузка. В обоих случаях права проверяются на сервере на каждый запрос.

Ограничение числа запросов

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

Виртуальная очередь

Если событие даёт доступ к ограниченному числу мест, а желающих больше, честнее поставить «зал ожидания»: пускаем порциями, остальные видят своё место. Размер порции подбирается испытанием.

Деградация

Порядок отключения функций при перегрузке: решаем заранее, а не в момент аварии

Лучше упрощённая работа основного сценария, чем медленная работа всего.

Функция и приоритет
Что делаем при перегрузке
На чём держится
Как возвращаем
Функция и приоритетОплата и заказнельзя ронять
Что делаем при перегрузкеНе отключаем; остальные функции освобождают для неё ресурсы
На чём держитсяОтдельные рабочие процессы, повтор с паузой у платёжного провайдера
Как возвращаемПосле пика сверяем платежи и заказы
Функция и приоритетВход и восстановлениенельзя ронять
Что делаем при перегрузкеОграничиваем частоту попыток, включаем виртуальную очередь
На чём держитсяСерверная часть входа отдельно от остальных страниц
Как возвращаемСнимаем очередь, когда нагрузка вернулась к обычной
Функция и приоритетКаталог, лента, поискможно упростить
Что делаем при перегрузкеОтдаём кэш с большим сроком, упрощаем поиск
На чём держитсяКэш и реплики; что именно упрощается, записано в регламенте
Как возвращаемСрок кэша возвращается к обычному
Функция и приоритетРекомендацииможно отключить
Что делаем при перегрузкеПоказываем общий список вместо персонального
На чём держитсяПереключатель в настройках без выпуска версии
Как возвращаемВключаем по одному, глядя на нагрузку
База данных

Где ломается база: четыре места, которые ищем первыми

Горячая строка

Остаток товара, лимит купона, число мест: множество запросов обновляют одну запись и ждут друг друга. Решается порядком обновления и короткими транзакциями.

Пул соединений

У базы ограничено число подключений. Когда приложение держит их дольше нужного, пик упирается сюда, а процессор простаивает.

Таблица событий без правил

История действий и журнал заходов растут быстрее остальных, копирование и обновление структуры затягиваются. Нужны разбиение по времени и правила хранения.

Тяжёлые отчёты на основной базе

Выгрузка для маркетинга занимает базу в часы пик. Отчёты уходят на реплику или в отдельное хранилище.

Что делаем

Из чего состоит работа и сколько она стоит

Цены — по тарифам. Точная сумма называется только у обследования, дальше вилка, которая сужается. Остановиться можно после любой ступени.

Обследование: один контур

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

200 000 ₽ · 2–3 недели

Обследование: несколько систем

Сервис с платёжным провайдером, 1С, CRM, рассылками: схема обменов и то, что останавливается при сбое каждой системы.

350 000 ₽ · 3–4 недели

Пилот: одно узкое место

Устраняем самое дорогое место и доказываем повторным испытанием на тех же данных: кэш, переписанный запрос, очередь для одной операции.

150 000–400 000 ₽ · 2–8 недель

Пилот: несколько частей архитектуры

Вынос тяжёлых операций, реплики, виртуальная очередь входа, новая схема хранения событий. Переход этапами.

400 000–1 200 000 ₽ · 2–3 месяца

Вывод в эксплуатацию

Перенос боевой нагрузки по этапам, опытная эксплуатация на пиковом событии, регламент проверок восстановления, приёмка.

от 1 500 000 ₽ этапами по 300 000–700 000 ₽ · от 3 месяцев

Сопровождение

Мониторинг, обращения, разбор инцидентов, подготовка к известным пикам. Плановые доработки с пакета на 60 000 ₽. Сверх пакета — 5 000 ₽ в час.

20 000 / 60 000 / 120 000 ₽ в месяц
Процесс

Как идёт работа

2–4 недели — Обследование и замеры

Берём журналы, снимаем профиль запросов, находим первые узкие места, спрашиваем бизнес о ближайших рассылках, акциях и запусках.

До разработки — Нагрузочная модель

Принимаем с вами профиль пика, список того, что нельзя ронять, и порядок отключения остального.

Первый шаг — Пилот на самом дорогом месте

Устраняем одно узкое место и повторяем испытание.

Этапами — Перенос и испытание пика

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

Дальше — Передача или сопровождение

Передаём код, инструкцию по развёртыванию, регламент реагирования и мониторинг.

Цена

Что двигает цену внутри вилки

Число профилей и горячих мест

Сервис с просмотрами и сервис с продажей ограниченного ресурса стоят по-разному. Каждое горячее место добавляет и проектирование, и испытание.

Требования к доступности

Обещание «работаем всегда» в договорах с пользователями меняет архитектуру. Что именно вы обещаете, разобрано в статье о <a href="../blog/chto-znachit-sla-tri-devyatki/">доступности «три девятки»</a>.

Состояние действующего сервиса

Если нет журналов, мониторинга и тестового стенда, часть обследования уходит на то, чтобы их получить.

Внешние зависимости

Платёжный провайдер, отправка кодов и 1С ограничивают пропускную способность, и чужие ограничения мы не меняем.

Контроль

Что остаётся у вас и чего мы не делаем

Остаётся у вас

  • Исходный код в вашем репозитории с первого коммита.
  • Нагрузочные сценарии и описание профиля пика: их можно запускать самим перед каждым событием.
  • Регламент деградации: что и в каком порядке отключается, кто решает.
  • Схема архитектуры и инструкция по развёртыванию; с ними можно идти к другому подрядчику.
  • Право остановиться после любой ступени: сделанное остаётся у вас по акту.

Мы этого не делаем

  • Не оказываем хостинг: сервис стоит на ваших серверах или у выбранного вами хостера.
  • Не защищаем от атак на сетевом уровне как услугу: это у вашего провайдера. Мы делаем ограничения и очереди на уровне приложения.
  • Не делаем мобильные приложения для iOS и Android, маркетплейсы, стриминг и платёжные продукты. Платежи принимает ваш эквайринг, данные карт мы не храним.
  • Не дежурим круглосуточно и не называем число пользователей без испытания на вашем стенде.
  • Не берём работы дешевле 150 000 ₽.
Граница

Высокая нагрузка, микросервисы или веб-сервис: где проходит граница

Эта страница про сервис для массового пользователя, где главный риск связан с пиками. Если у вас закрытая корпоративная система с долгими отчётами и релизами раз в квартал, смотрите микросервисы и высокую нагрузку. Выбор между монолитом и сервисами описан в статье «Микросервисы или монолит»: для большинства B2C-сервисов на старте достаточно монолита с правильным кэшем и очередью.

Если сервиса ещё нет, начните со веб-сервиса или веб-приложения. Если вы продаёте доступ компаниям, а не людям, это SaaS-платформа. Если нужен кабинет к данным учёта, хватит личного кабинета. Если проблема в обмене с внешними системами, начинают с API и бэкенда. Состояние кода покажет аудит кода и архитектуры.

Инструменты

На чём собираем

Серверная часть и данные
  • Python: Django или FastAPI, при необходимости Go для тяжёлых участков
  • PostgreSQL с репликами для чтения, посредник для соединений, разбиение таблиц по времени
  • Redis или совместимое хранилище для кэша, сессий и ограничений запросов
  • RabbitMQ или очередь на PostgreSQL для фоновых задач
Интерфейс, проверка и развёртывание
  • React или Vue, TypeScript, адаптивная вёрстка
  • Nginx или другой балансировщик, раздача файлов отдельно от приложения
  • Нагрузочные сценарии на Locust или k6, трассировка через OpenTelemetry
  • Docker, GitLab CI, мониторинг в вашем контуре
Материалы

Материалы по теме

Статья

Как подготовить B2C-сервис к высокой нагрузке

Порядок подготовки по узким местам: что измерять до запуска, что кэшировать, что откладывать и как репетировать пик.

  • Узкие места по порядку
  • Репетиция пика
  • Что отключаем
Читать →
Статья

Что означает доступность «три девятки» и как её проверять

Какой простой допускает каждая цель по доступности и что проверить до подписания обязательств перед пользователями.

  • SLI, SLO, SLA
  • Цепочка зависимостей
  • Что измерять
Читать →
Статья

Микросервисы или монолит: как выбрать архитектуру

Когда хватает монолита с кэшем и очередью, а когда пора выделять сервис.

  • Цена распределённости
  • Как разрезать
  • Вопросы подрядчику
Читать →
Заявка

Разберём ваш профиль пиков и назовём первые узкие места

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

Спасибо, заявка отправлена. Ответим в течение рабочего дня.

Не удалось отправить. Напишите в телеграм или позвоните.

Вопросы

Частые вопросы: разработка высоконагруженного B2C-сервиса

Сколько стоит разработка высоконагруженного веб-сервиса?

Начинаем с обследования: 200 000 ₽ за один контур, 350 000 ₽ при нескольких системах. Дальше пилот на узком месте (150 000–400 000 ₽) или на нескольких частях архитектуры (400 000–1 200 000 ₽), вывод в эксплуатацию от 1 500 000 ₽ этапами по 300 000–700 000 ₽. Обследование вычитается из первого этапа, если продолжаете с нами.

Сколько пользователей выдержит сервис?

Без замеров на вашем стенде число называть нельзя, и мы его не называем. Нагрузка зависит от того, что люди делают в пик, от базы, внешних сервисов и скорости роста пика. Результат испытания записывается как профиль, при котором сервис работает в заданных пределах, и как первое, что отказывает при превышении.

Нужны ли микросервисы для высокой нагрузки?

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

Можно ли пережить пик без закупки новых серверов?

Иногда да: кэш, очередь входа и вынос тяжёлых операций снимают нагрузку без нового оборудования. Если упирается сама мощность, это покажет испытание, и мы так и скажем. Стоимость оборудования и облака мы не называем, она зависит от вашего поставщика.

Защитите ли вы от ботов и атак?

На уровне приложения: ограничения запросов по ключам, защита входа от перебора, виртуальная очередь, проверка прав на сервере. Защиту от атак на сетевом уровне вы получаете у своего провайдера, мы её как услугу не оказываем.

Можно ли развернуть сервис у нас, а не в облаке?

Да. Сервис работает на ваших серверах или у выбранного вами хостера. Персональные данные граждан России обычно должны храниться на серверах в России, это учитывается при выборе размещения. Юридические вопросы решает юрист заказчика.

Вы работаете только в Ростове-на-Дону?

Мы в Ростове-на-Дону, работаем с заказчиками по всей России: удалённо и в вашем контуре. Доступ к системам и обследование согласуем на старте с вашей службой безопасности.