Кейс: Как мы делали MVP Ad Exchange (технология RTB)

Кейс: Как мы делали MVP Ad Exchange (технология RTB)

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

Начнем с описания построения MVP проекта.

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

Что такое RTB и Ad Exchange

В интернете достаточно много определений технологии RTB, как она работает и зачем она нужна.

Если очень кратко, то RTB (Real Time Bidding) – это рекламная технология, которая позволяет организовать аукцион между продавцами и покупателями рекламы в реальном времени.

В состав RTB входит множество компонентов, каждый из которых отвечает за свою часть работы.

Представим упрощенную схему компонентов экосистемы RTB и их взаимодействие между собой:

Consumer – это любой из нас, любой человек который зашел на сайт или открыл мобильное приложение, где есть реклама.

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

SSP (Supply-side platforms) – платформа, которая позволяет Publisher разместить рекламу.

Ad Exchange – онлайн аукцион. Его задача подобрать наилучшее предложение рекламы для показа Consumer.

DSP (Demand-side platforms) – платформа, которая подбирает наиболее подходящую для пользователя рекламу. Для детализации информации о Consumer используется DMP.

DMP (Data Management Platform) – поставщик данных о Consumer.

Advertiser – покупатель, который хочет, чтобы за определенную плату была показана его реклама.

Упрощенная последовательность действий при работе RTB:

  1. Consumer заходит на сайт (Publisher).
  2. Publisher выполняет код, который сообщает SSP, что нужна реклама.
  3. SSP формирует запрос, в котором находится информация о Consumer, о Publisher и о формате необходимой рекламы. Сформированный запрос отправляется в Ad Exchange.
  4. После того как Ad Exchange получил запрос от SSP, запрос пересылается во множество различных DSP.
  5. DSP получает дополнительную информацию о пользователе из DMP.
  6. DSP выбирает рекламу для пользователя и цену на основе данных из DMP и запроса от Ad Exchange.
  7. Ad Exchange получает ответы от всех DSP и выбирает лучшее предложение, которое передает в SSP.
  8. SSP получает ответ от Ad Exchange, после этого Publisher показывает рекламу.

Для нашего проекта нам необходимо реализовать роль Ad Exchange из этой схемы.

Почти все SSP реализуют Ad Exchange самостоятельно. Они проводят аукцион, рассылая запросы DSP. Отсюда возникает логичный вопрос: зачем реализовывать отдельный Ad Exchange, если SSP его сами реализуют?

Все довольно просто: количество различных DSP огромно и реализовать взаимодействие со всеми значимыми DSP даже у крупных SSP нет возможности, не говоря уже о более мелких SSP и DSP. К тому же в реальности цепочка аукционов может быть достаточно длинной и проходить не один RTB. Поэтому на рынке еще есть место для новых RTB платформ.

Схема работы Ad Exchange:

  1. Получаем запросы от SSP по HTTP.
  2. Отправляем каждый запрос в несколько DSP.
  3. Сравниваем цены, кто из DSP предложил большую цену, тот и победил (возможны более сложные схемы, но мы рассматриваем самый простой вариант).
  4. Уменьшаем немного цену.
  5. Отправляем ответ SSP.
  6. Мы как-то должны узнать, что мы победили в аукционе в SSP. В идеале SSP должен сообщить нам об этом через вызов нашего API с указанием Id запроса и итоговой цены показа (она могла изменить).
  7. Сообщаем DSP о том, что его ставка победила.

Какие требования предъявляются к Ad Exchange

Глядя на схему работы Ad Exchange мы можем подумать, что выглядит все просто, но всегда есть подводные камни. А именно нефункциональные требования:

  1. Таймаут ожидания ответа в SSP – 300 мс (он может быть разным, но возьмем достаточно вольготные условия).
  2. Количество запросов от SSP – до 30 000 QPS. Пока что мы реализуем только MVP, поэтому ставим такое ограничение, в дальнейшем количество запросов может увеличиться.

Как давно вы строили систему с обработкой такого количества запросов с гарантией низких задержек? Напоминаю, что за 300 мс нам надо сходить еще и во внешние системы (DSP).

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

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

Как мы реализовали нефункциональные требования

Первое требование – время ожидания ответа в SSP не должно превышать 300 мс

  1. После получения запроса от SSP мы отправляем запросы во множество DSP. Взаимодействие с внешней системой по сети – это всегда не быстро. Наш случай не исключение, это самая большая графа расходов в плане времени обработки запроса от SSP.
    1. Какое время ответа DSP на различные запросы? Оно укладывается в выделенное время? Как себя DSP ведет при нагрузке? Может выдержать 30 000 QPS?
      Что произойдет если DSP не успеет ответить за отведенное время?
      При подключении нового DSP всегда необходимо ответить на каждый из этих вопросов. DSP – это черный ящик, и мы должны понимать, что от него можно ожидать. Именно поэтому необходимо тестировать DSP с нагрузкой, сопоставимой с боевой. DSP, который просаживается при нагрузке, может быть причиной нагрузки на сервере-аукционе, причем от этой нагрузки не будет никакого профита, т.к. ответа мы не дождемся.
      И конечно же нам нужен таймаут, нельзя ждать ответа от DSP вечно.
    2. Также у нас много запросов к DSP для каждого запроса от SSP. Само собой их надо выполнять параллельно. А чтобы не плодить потоки, лучше использовать HTTP клиент, который не блокирует поток.
  2. Наш сервер и SSP находятся не в одной серверной стойке, поэтому стоит учесть время на сетевое взаимодействие между SSP и нашим сервером. При подключении нового SSP мы проводим тесты на сетевое взаимодействие между нами и SSP, желательно HTTP пакетами.
    По результатам тестирования возможно придется корректировать время, которое отведено нам на работу.
  3. Не надо забывать о сборщике мусора. В большинстве языков он сейчас есть и может доставить немало проблем, начав сборку и остановив работу аукциона скажем на 200 мс. Без ограничения в 300 мс мы этой остановки просто не заметим, но в нашем случае это значительная часть отведенного времени на обработку запроса. Поэтому стоит задуматься о выборе сборщика мусора и его настройке.
  4. Окружение, где все будет запускаться.
    Мы выбрали железные сервера, т.к. нет желания воевать с облаком за ресурсы. Все мы знаем, что в облаках размещаются виртуальные машины с перекрытием ресурсов, для лучшей их утилизации облаком. И когда нам неожиданно могут потребоваться эти ресурсы, они могут оказаться занятыми. А пока нас облако перенесет на другую более свободную машину, мы потеряем время.
  5. Все взаимодействие между SSP, Ad Exchange и DSP происходит через протокол HTTP. Сам по себе протокол HTTP не очень подходит для отправки большого количества сообщений, т.к. на каждый запрос открывается отдельное TCP соединение. Но в протокол HTTP было добавлено расширение keep-alive, которое позволяет в рамках одного TCP соединения отправлять несколько запросов. Использование этого расширения позволит нам значительно снизить нагрузку на сервера и уменьшить время взаимодействия с SSP и DSP. Но это расширение должна поддерживать и вторая сторона, поэтому при подключении новых SSP и DSP стоит проверять, что они поддерживают keep-alive.

Как реализовать требование к количеству запросов – 30 000 QPS от SSP

  1. Мы сейчас говорим об MVP, на реальной боевой системе запросов может быть больше, поэтому нам необходимо предусмотреть масштабирование системы. Обработка одного запроса от SSP не зависит от обработки другого запроса, так же как не зависит от состояния на сервере, т.е. запросы от SSP – stateless. Это значит, что сервера аукциона мы можем горизонтально масштабировать, а запросы распределить по серверам при помощи балансировщика.
  2. Балансировищик никакой обработки запросов не производит, он только выступает в качестве proxy. Стоит отказаться от любого преобразования запросов на балансировщике, т.к. это будет создавать дополнительную нагрузку.
  3. Балансировщик мы ставим между SSP и нашим Ad Exchage. Мы уже говорили о необходимости использовать расширение протокола HTTP keep-alive. Необходимо обратить внимание, что балансировщик должен поддерживать это расширение как при взаимодействии с SSP, так и при взаимодействии с Ad Exchage.
  4. Как обрабатывать запросы на серверах аукциона? Таймаут обработки запроса – 300 мс, но в реальности мы будем успевать и за 100 мс (зависит от DSP). В один момент времени у нас будет выполняться до 3000 запросов.
    Для MVP нам достаточно простого подхода. Например, мы можем каждый запрос обрабатывать в отдельном потоке, значит в пике мы будем иметь до 3000 потоков. Почти все потоки будут в процессе ожидания ответа от DSP. Но все равно это много для одного сервера, процессор будет тратить много времени на постоянное переключение контекста. Разделив эту нагрузку на 3 сервера, мы получим по 1000 потоков и 10 000 QPS на сервер. Эти цифры более чем реальны для сервера с 8 ядрами.

Заключение

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

Сейчас мы рассказали о первом этапе – запуске MVP Ad Exchange. Далее мы подключим к нему необходимые SSP и DSP и посмотрим, какие цифры получатся.

Скорее всего, на выходе будет разница между цифрами продаж в SSP и DSP, 3-4% потерь – это отличный результат и обычно это значит, что у нас отличный трафик без ботов. Но в реальной жизни все не так хорошо.

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

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

О том, как мы все это делали, о масштабировании системы и анализе трафика мы расскажем в следующих статьях.

 

Автор статьи: Николай Еремин, Старший Java разработчик, Maxilect

Все статьи