Техническая презентация
Concert.kz
Билетная платформа для крупных концертов и массовых мероприятий — от покупки билета и оплаты до прохода через турникеты. Построена как highload-система, а не как обычный сайт продажи билетов.
Чего мы ждём от крупных продаж
Нагрузка приходит не равномерно, а волной — в первые минуты после старта продаж. Каждый страх закрыт конкретным решением.
Что, если зайдут 100 000 человек сразу?
Горизонтальное масштабирование и управляемый запуск продаж — система дозирует вход, а не падает.
Что, если придут боты и скрипты?
Cloudflare перед всей инфраструктурой: защита от DDoS, фильтрация ботов, ограничение частоты запросов.
Оплата прошла, а билет не создался?
Идемпотентные операции и отдельный статус заказа для разбора — оплата не теряется, дубли не появляются.
Один из платёжных провайдеров недоступен?
Два независимых провайдера — Kaspi и ePay — и резервный сценарий переключения между ними.
Интернет на площадке нестабилен?
Билеты заранее выгружаются в локальную базу турникетов — проход работает автономно.
Как быстро найдём проблему?
Сквозной мониторинг и оповещения: видно, где именно сбой — код, база, платежи или периметр.
Стек: проверенные инструменты, каждый — по делу
При переходе к микросервисам предусмотрены очереди сообщений: RabbitMQ, Kafka или Azure Service Bus.
Production-контур: каждый слой закрывает свой риск
Запрос проходит сверху вниз — от клиента через защищённый периметр к сервисам и данным.
Azure · Kubernetes
Окружения: dev → stage → prod. Stage — на казахстанских серверах: дешевле проверять новые версии до production.
Очередь на вход — страховка, а не узкое место
В обычные дни покупатели идут к билетам напрямую. Очередь включается заранее — только перед стартом продаж крупного концерта.
Старт продаж крупного концерта — живая схема
Волна трафика → Cloudflare отсекает ботов → очередь дозирует пропуск → покупка идёт с предсказуемой нагрузкой.
Зачем
Снимает пиковый удар с API, PostgreSQL, Redis и платёжных сервисов в первые минуты продаж.
Когда
Первые три крупных концерта — режим управляемого запуска. Включается заранее, до старта продаж. В обычные дни покупка идёт напрямую, без очереди.
Что дальше
По данным трёх запусков решаем: оставить очередь только для крупных событий или сделать частью стандартной инфраструктуры.
Нагрузочное тестирование перед каждым крупным событием
Мы не заявляем «выдержит», а заранее измеряем реальные пределы платформы и устраняем узкие места до старта продаж.
Что проверяем
- Весь путь: интерфейс, API, PostgreSQL, Redis
- Платёжные интеграции и webhook-и
- Генерацию билетов и QR-кодов
- Cloudflare, очередь на вход, Kubernetes
- Мониторинг и оповещения под нагрузкой
Ключевые сценарии
- Старт продаж: резкая волна пользователей
- Десятки тысяч запросов в секунду
- Борьба за одни и те же места в секторе
- Пиковая оплата и массовая выдача билетов
- Отказ внешнего сервиса, деградация базы или провайдера
Что получаем на выходе
- Максимальный стабильный RPS и время ответа API (p95 / p99)
- Пределы PostgreSQL и Redis
- Узкие места в коде и инфраструктуре
- Расчёт ресурсов Azure под конкретное событие
- Решение о готовности к продаже концерта
Профиль нагрузки: обычный день → старт продаж → стабилизация
Очередь на первых концертах — дополнительная страховка. Но пределы платформы мы знаем по тестам, а не надеемся на очередь.
Отказоустойчивость критичных сценариев
Покупка, оплата, выдача билета и проход на событие должны работать всегда — остальное может подождать.
- Несколько реплик API за балансировщиком Azure — отказ одного контейнера незаметен для покупателей.
- PostgreSQL в managed-конфигурации высокой доступности; реплики чтения забирают отчёты и аналитику с основной базы.
- Redis снижает нагрузку на базу — горячие данные отдаются из кэша.
- Cloudflare держит внешний периметр — атаки и мусорный трафик не доходят до инфраструктуры.
- План восстановления после аварий подготовлен заранее: бэкапы, PITR, мониторинг состояния базы, оповещения.
- В перспективе — архитектура на несколько регионов.
Не потерять оплату и не выдать дубль билета
Платёжная цепочка журналируется полностью: создание заказа → оплата → webhook → успех / отказ / возврат.
Защита от дублей
Ключи идемпотентности на создании заказа и обработке webhook-ов: повторный запрос не создаёт второй платёж или билет.
Спорные ситуации
Оплата прошла, билет не создался → заказ попадает в отдельный статус для автоматической или ручной проверки. Вся цепочка — в платёжном журнале.
Резервный провайдер
При сбое Kaspi или ePay система переключает оплату на второго провайдера — продажи не останавливаются.
Валидация билетов работает даже без интернета
Проход людей — самый критичный момент мероприятия. Поэтому турникеты не зависят от связи с центральной системой.
Локальный контур площадки
Проверка QR-кода
Подлинность, статус использования и принадлежность событию. Повторный проход по тому же билету блокируется.
Автономный режим
При нестабильном интернете турникеты продолжают проверку по локальной базе. После восстановления связи статусы синхронизируются с центром.
Контроль в реальном времени
Контролёры и администраторы видят статусы проходов; каждое событие валидации попадает в журнал.
Защита периметра и контроль доступа внутри
Внешний периметр — Cloudflare
- Защита от DDoS — атаки гасятся до входа в инфраструктуру
- WAF — фильтрация вредоносных запросов к API
- Ограничение частоты запросов — скрипты не выкупают билеты
- Фильтр ботов + CAPTCHA / JS-проверка для подозрительного трафика
- HTTPS везде, защита API
Внутренний контур
- Ролевая модель доступа — каждый видит только своё
- Аудит действий пользователей с повышенными правами
- Секреты — в защищённом хранилище, не в коде
- Доступы разделены по окружениям dev / stage / prod
- Персональные данные — доступ ограничен ролями
Роли в системе
Видно, где именно проблема — за минуты, а не часы
Grafana — единая панель, Telegram и Email — оповещения. Наблюдаемость нужна не для графиков, а чтобы сразу видеть источник сбоя.
API и сервисы
Время ответа, доля ошибок, запросы в секунду, нагрузка CPU / RAM, ошибки авторизации и оплаты.
Бизнес-показатели
Заказы, успешные и неуспешные оплаты, выданные билеты, возвраты, конверсия из очереди в покупку.
PostgreSQL
Соединения, медленные запросы, блокировки, отставание реплик, размер и нагрузка базы.
Redis и очередь на вход
Память, доля попаданий в кэш, задержки; размер очереди, время ожидания, заблокированный трафик.
Платежи
Ошибки Kaspi и ePay, webhook-и, спорные статусы, среднее время подтверждения платежа.
Проход на событие
Успешные проходы, повторные попытки, отклонённые билеты, ошибки турникетов, задержки синхронизации.
Надёжно в пики — экономно в обычные дни
Мы не держим максимальную инфраструктуру постоянно: в спокойные дни система работает экономично, а перед крупными продажами масштабируется заранее.
Обычные дни
- Минимально необходимый набор ресурсов Azure — оплата по факту использования
- Автомасштабирование уменьшает реплики, когда нагрузки нет
- Cloudflare отдаёт статику из CDN и фильтрует мусорный трафик — серверная часть разгружена
Перед крупным концертом
- Ресурсы наращиваются заранее — под прогноз нагрузки, подтверждённый тестами
- Kubernetes масштабирует только те сервисы, которым это нужно
- После события инфраструктура возвращается к экономному режиму
Тест и stage — на казахстанских серверах: новые версии проверяются на недорогих местных мощностях и попадают в production-контур Azure только после проверки.
Четыре этапа: от ядра платформы до enterprise
Этап 1
Ядро платформы
- .NET 10, Next.js, Flutter
- PostgreSQL, Redis
- Kaspi / ePay
- Админ-панель, базовая валидация и мониторинг
Этап 2
Готовность к production
- Azure, Kubernetes, Docker
- CI/CD, dev / stage / prod
- Cloudflare, бэкапы, оповещения
- Управляемый запуск продаж, платёжный журнал, аудит
Этап 3
Высокие нагрузки
- Автомасштабирование, реплики чтения
- Нагрузочные тесты, защита от ботов
- Оптимизация покупки мест, платежей и QR-валидации
Этап 4
Enterprise
- Микросервисы и очереди сообщений
- Несколько регионов, расширенное восстановление
- SLA 99,99%, расширенные аудит и аналитика