Привет, меня зовут Александр, я тимлид команды разработки трекинговых решений компании Admitad.


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


Чем занимается команда?


В задачи команды входят поддержка сервисов трекинга, исследование и разработка новых трекинговых решений. Также мы реализуем в коде новые фичи и бизнес-идеи, с которыми приходят к нам продакт-менеджеры. Кроме того, решаем внутренние задачи по развитию сервисов и покрываем техдолг (как же без него). И наконец, команда обязана выполнять SLA с заказчиком по времени даунтайма сервисов и реакции на проблемы.


Что такое трекинг?


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



Аналогичным образом работает и трекинг партнерской сети Admitad, только Admitad отслеживает целевые действия пользователей для своих партнеров.


Какие сервисы задействованы в трекинге?


Наша команда разрабатывает и поддерживает сервисы переходов и регистрации действий Admitad. Вот так схематично можно представить их взаимодействие с Admitad и его партнерами (сплошными стрелками обозначены активные действия пользователей, пунктирными — реакция сервисов на них).



Пояснения к схеме:


  • Партнерская ссылка Admitad инициирует редирект пользователя через сервис переходов.
  • Click_id, или идентификатор перехода, генерируется на лету и не содержит никаких персональных данных.
  • Примером сайта партнера может являться интернет-магазин, в котором пользователь хочет купить телевизор (совершить целевое действие).

Какие требования к сервису переходов?


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


Поскольку пользователи живут в разных странах, ноды сервиса переходов также закреплены за балансировщиками, размещенными в разных точках Земли. Благодаря этому среднее время ответа сервера составляет ~10 мс в любом регионе.


Рабочая нагрузка колеблется в пределах ~1 000–2 000 RPS. Естественно, кластер имеет запас прочности на случай повышения нагрузки, так как объем трафика внезапно может вырасти в 1,5–2 раза.




Так как это основной сервис Admitad, его доступность 24/7 для пользователей обеспечивается резервированием нод в нескольких ДЦ. Идентификаторы click_id гарантированно доставляются в Admitad через очереди RabbitMQ.


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


Если в прод все-таки просочился баг или утекла память на сервере, уведомления в Sentry и Slack позволят вовремя среагировать на ошибку. А за текущими метриками железа мы наблюдаем на дашбордах Grafana.



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


Зачем делить сервис переходов?


Сервис переходов частично выполняет задачи по регистрации действий, так как у него удобная распределенная инфраструктура, и текущая схема user journey выглядит скорее так.



Функции двух различных по назначению сервисов совмещены в одном. Почему так получилось? Исторически технологическая платформа Admitad была монолитом. В процессе развития она начала распадаться на независимые сервисы. Нынешний сервис переходов — один из них.


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



Как разогнать сервис переходов?


Объем трафика, проходящего через сервис переходов, ежегодно растет. В дни распродаж, такие как День холостяков 11.11 на AliExpress, достигается пиковая нагрузка, поэтому компания заранее готовится к ним: вводится code freeze, девопсы проверяют скрипты для развертывания дополнительных нод.


Очевидно, что горизонтальное и вертикальное масштабирование сервисов увеличивает расходы на поддержание инфраструктуры. Более предпочтительным вариантом является оптимизация веб-приложения, чтобы выдерживать больше RPS на том же железе, поэтому при написании нового сервиса было принято решение отказаться от Flask и перейти на aiohttp.


Мы (и не только мы) считаем, что асинхронный фреймворк позволит разогнать новый сервис, чтобы он держал большую нагрузку. Конечно, не стоит руководствоваться только предположениями, поэтому был запущен процесс нагрузочного тестирования. Мы завели выделенную ноду и задеплоили на нее приложение. Сейчас с помощью Apache JMeter и Locust нагружаются эндпоинты сервиса. Сравнив метрики старого и нового сервисов на одной и той же ноде, можно будет сделать обоснованные выводы о производительности.


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



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


И как при этом все не сломать?


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


Мы попросили ребят из QA сделать нам E2E тесты, которые будут проверять сервис переходов как «черный ящик». Подменив содержимое «ящика», можно будет удостовериться, что поведение нового приложения для пользователя и Admitad осталось прежним. А подключение E2E тестов отдельным этапом в CI позволит нам в дальнейшем спокойно деплоиться по пятницам (на самом деле нет).



Что дальше?


У нас есть планы, как сделать сервис переходов лучше, быстрее и надежнее.


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

Послесловие


Спасибо, что прочитали этот обзор. Надеюсь, ответы на вопросы получились достаточно содержательными, чтобы вы получили общее представление о трекинговых сервисах Admitad.


Если у вас был опыт построения нагруженных сервисов на aiohttp или сравнения производительности разных Python-фреймворков, пожалуйста, поделитесь им в комментариях. Также было бы интересно почитать про опыт профилирования и нагрузочного тестирования распределенных систем. Какие инструменты использовали? Что посоветуете почитать по теме?