We’ll talk about a path that we’ve gone through @ Concert.ua: from a ticketing start-up to a leader of the ticketing market of the country. DDOS, f*ck-ups and victories. How did we manage to overcome a monolith piece of software and got to a distributed web-application architecture with high peak loads.
14. ВСКРЫВШИЕСЯ
ПРОБЛЕМЫ
Неуклюжий самописный фреймворк
Отсутствие документации и комментариев
Синхронная обработка всего
Проект был не по канонам ООП и MVC
Зависимости впаяны в репозиторий
Непродуманная схема данных в db
Почти полное отсутствие индексов в db
Прямые SQL-запросы из контроллеров
Отсутствовала полноценная корзина
Не обрабатывались многие ошибки
AJAX-запросы не авторизовывались
Довольно часто получались дубли мест
Поиск по названию занимал до 30 сек
Типичное время отклика было 3-10 сек
Разнились цифры в отчётах
17. УСПЕХИ В ЭВОЛЮЦИИ
Поиск событий и площадок через ElasticSearch
Созданы индексы в db
Хранение сессий и кеш сущностей в Redis
Тюнинг apache и добавление nginx как reverse proxy
Добавлены обработчики ошибок
Исправлены злостные просчёты в схеме данных
19. ТРАНСФОРМАЦИЯ:
PHASE 1
Переход на PHP7
Замена Apache на nginx + PHP-FPM для legacy
Переписывание Frontstore на Yii2
Внедрение билетного ядра vCORE
Создание экосистемы stateless-сервисов
Очереди на RabbitMQ
Разделение монолитной DB
20. EUROVISION SONG
CONTEST 2017
Переезд в облако Digital Ocean
Тонкая настройка CloudFlare
Anti-scalper Lua-скрипты для nginx
Боевое крещение ядра vCORE
Queue-It сервис электронных очередей
21. ТРАНСФОРМАЦИЯ:
PHASE 2
dRPC-архитектура ядра vCORE на основе WAMP v2 (Crossbar)
New-gen v-Ticket Frontend (Angular, WAMP v2 over WSS)
Storage service: хранение изображений и документов
Sentry: централизованный сбор ошибок и исключений
Analytics service: сбор и агрегация big data
ELK-стек: сбор логов со всех служб
Prometheus: слежение за heart-beat критических служб
Контейнеризация приложений и сервисов
27. IMAGINE DRAGONS
2018
Полностью новый сайт
Queue-It сервис электронных очередей
Абсолютный рекорд Украины:
50% стадиона за 6 часов
Concert.ua продал 84%
Sales
Concert.ua Others
28. НАГРУЗКА НА 2018
50000-80000 посещений
5000 билетов в 3000 заказах
в сутки
Билетный сайт №2 по посещаемости в СНГ
29. ОТРАЖЕНИЕ DDOS
o CloudFlare: WAF, Rate Limiter, Country Block, Load Balancer
o Распознавание паттернов атаки
o Правила на nginx (ограничения PUT/POST, referrer и т.п.)
o Кастомные правила WAF на CloudFlare
o Barracuda Cloudgen Firewall или a10 WAF
30. ВЫВОДЫ
При проектировании архитектуры стоит держать в голове вопрос: «Как это
будет работать завтра?»
Переделывать рабочий проект намного дольше, дороже и сложнее,
нежели написать такой с нуля
PHP-приложение может стабильно работать в качестве демона и даже
мульти-процессно
WS стабильно работает даже в условиях DDOS
Оправдано дальнейшее дробление сервисов на более мелкие
Editor's Notes
Меня зовут Евгений Лысенко, я со-владелец и CTO компании Concert.ua и со-основатель всего холдинга VIRUS Music, куда входит Concert.ua
Concert.ua сейчас является лидером билетного рынка страны
Рассказ о нас, был бы не полным, если бы я вкратце не рассказал о наших корнях
1999 – музыкальный рекорд-лейбл
2003 – онлайн рейтинг
2006 – начали проводить большие события: Godskitchen, фестиваль Global Gathering, Пиратская Станция, A State Of Trance, Tiesto Club Life и многие другие
2011 – провели первый Sensation
2012 – билетный оператор Concert.ua
Так как мы были сфокусированы на проведении событий, разработка софта для нас не была профильной и первую версию системы для нас целиком реализовала аутсорс компания
Бизнес канва Александра Остервальдера
Классические, общепринятые технологии, принятые без зазора на будущее и без рассмотрения альтернатив
Hardware:
апп-сервер с 2мя 4х ядерными камнями Xeon, с 24ГБ памяти и Raid 1
Дб-сервер с 2мя 4х ядерными камнями Xeon с 16ГБ памяти и Raid10 на 15K SAS-дисках
По RESTful или SOAP API
В первые пару лет было всего пару внешних билетных партнёров, сейчас их уже несколько десятков
Получив боевой опыт на продаже собственных событий, мы решили предложить этот продукт широкому рынку
Однако мы быстро поняли, что v-Ticket – плохой консюмерский бренд и придумали бренд понятный для широкой аудитории
Concert.ua – frontstore, витрина. Хранит внешнее представление ассортимента, подборки, рейтинга, консюмеров, процессит оплаты
V-Ticket – склад, система. Хранит залы, продажи, билетную массу, биллинговую информацию и многое другое
Как и многие стартаты – Большой Комок Грязи
Монолитный кусок кода, где всё исполнялось синхронно
Всего пара-тройка крон-джобов
Скорее класс-ориентированное программирование, нежели ООП
Назвать продукт соответствующим парадигме MVC тоже не получалось
~2-3 посещения в минуту
В пиковые моменты продаж бывало до 10 посещений в минуту
Активная работа над брендом и его продвижение принесли плоды и трафик и продажи пошли вверх
С 2014 года мы в среднем утраиваем свой оборот каждый год
Начал расти трафик и продажи, начали расти нагрузки и проявляться проблемы одна за другой
Торможение файловой системы из 21млн файлов в тмп-папке с ШК
При отказе некоторых сервисов наше приложение тоже прекращало адекватно работать – например при отказе SMS-шлюза становилось невозможным оформить заказ
Приложение прогрессивно замедлялось с ростом базы
Проблемы начали накапливаться как снежный ком
В 2014 году было принято решение забрать разработку продукта in-house
Оказалось что репозиторий проекта не соответствовал файлам на продакшене
Сложная ситуация: с одной стороны трафик рос и бизнес требовал новых фич, с другой проект явно подходил к грани, за которую физически не мог перешагнуть
Нужно было срочно что-то менять
Код был полностью связан, как лапша в тарелке и пере
Невозможно переписать модуль за модулем, поскольку не было никаких модулей
Попытки переписать какую либо часть часто приводили к полной неработоспособностия
Каждая решённая проблема вскрывала новые и новые проблемы
1. Решение проблемы за проблемой, до исправления всех детских болезней
Позже стало понятно, что этот вариант не сможет исправить фундаментальные промахи в проектировании программной архитектуры
2. Создание полностью новой системы с нуля. Дальнейшая интеграция со всеми сервисами, включая свою старую систему и постепенный перевод клиентов
Был создан прототип новой системы. Даже был внедрён в автоматизации одной из площадок. Но бизнес интересы текущей системы всегда были в приоритете и новая система так и не смогла догнать по функционалу старую
3. Выстраивание новой системы на базе старых данных, но не кода
Построение нового билетного ядра (VCORE), на его базе нового Frontstore, разбиение системы на микросервисы, а монолитную DB на части
Эти меры несколько улучшили картину и на какое-то время оттянули, как стало ясно позднее, неизбежное
Старт продаж Depeche Mode – Global Spirit Tour 19.07.2017 на НСК Олимпийский
500-800 одновременных чел на сайте положили сервис из-за отсутствия индекса, используемого при определённом джойне
Синтетические нагрузочные тесты эту проблему не выявили
Репутационный удар и финансовые потери
К тому времени начали писать новое билетное ядро для создания Параллельной Реальности
Базы: Galera Cluster, PostgreSQL, ElasticSearch, Redis
Сервис-воркеры на основе ReactPHP: Ticket renderer, Apple Wallet renderer, Email sender, SMS sender, vSync worker, LAdesk worker, fin-transaction worker, etc
Воркеры стабильно работают и довольно редко текут по памяти. Проблем с ними у нас нет.
Мы любим Symfony, но Yii2 оказался самым быстрым PHP-фрейморком из протестированных нами, кроме Phalcon (который имеет свои сложности, в частности с дебагом)
Продали все доступные билеты на финал за первые 15 минут продаж
На старте, на странице продажи финала было одновременно до 3200 человек
Электронная очередь доходила до 12 500 чел
Среднее время отклика системы стало 150-200мс даже в моменты пиковой нагрузки
Как работает электронная очередь…
Всё это позволило продать билетов на ЕВ более чем на 70млн грн
Ядро, как центральный элемент экосистемы использует Identity Service, который выдаёт JWT-удостоверения пользователям бекофиса
Используем Pub/Sub возможности WAMP/Crossbar
С ядром мы пошли дальше и помимо того, что его инстансы работают как демон, само ядро имеет хост-процесс, поддерживающий пулл воркер-процессов. Воркеры порождаются/уничтожаются по необходимости
Верхняя часть отвечает за frontstore, нижняя – склад и службы
Эта диаграмма не полная. Здесь нет нашего сервиса аналитики: Amazon Kinesis, Amazon Athena, Lambda и API Gateway
В процессе переезда на AWS
Для более быстрой масштабируемости планируем миграцию на Aurora Serverless
Так как мы имеем дело с большим кол-вом визуального контента, для нас важно иметь подходящее, гибкое хранилище изображений
Хранилище полностью автономно от приложения
FlySystem – Возможно использование таких хранилищ: Local File system, AWS S3, DO Spaces, Azure, Memory, Migration Adapter
Intervention Image для работы над картинками
Может хранить любые BLOB-объекты, не только картинки
Как это работает?
Также через адаптер можно проводить онлайн миграцию в другое хранилище
Электронная очередь доходила до 52500 чел
Выручка за первые 6 часов превысила 1 млн долларов
Фан-зона была раскуплена за первые 2 часа
И всё это за 8 месяцев до концерта – удивительно
Наш успех не остался не замеченным и майка лидера привлекла к себе внимание во всех его проявлениях
В том числе и DDOS атака в этом июне, длившаяся 1,5 месяца с небольшими перерывами
Альтернатива CF – Imperva Incapsula
Готовиться к атакам нужно заранее, иначе справится с ней будет сложнее
Интересный факт: поднятые WS-соединения оставались рабочими даже в пиках DDOS
За последние пару лет нами написано немало полезных инструментов и мы обсуждаем возможность выпуска некоторых из них в Open Source
Например: vORM, Vinjecto, SeatyJS