Sell Side platform

Добрый день, дорогой читатель! Продолжая цикл статей о реализации стека RTB нашей компанией, предлагаю вам ознакомиться с реализацией нашей SSP — VOX Ad Exchange.

2dd71b38d8c34e83a51670f5a30d593a.jpg
Нагрузка здесь не такая большая, как, например, в нашей DSP, а основное время обработки запроса тратится на ожидание ответов от подключенных DSP. Написана она в виде асинхронного ASP.NET MVC-приложения.
Итак, давайте для начала разберёмся, как же происходит обработка запросов.

Запрос на получение рекламы начинает формироваться ещё на стороне клиента. Здесь посредством javascript мы стараемся собрать как можно больше информации о посетителе сайта, на котором установлен наш скрипт. В основном это техническая информация: включен ли в браузере flash player, размеры окна браузера, размеры экрана, получаем адрес страницы и реферер на страницу, с которой пришёл пользователь и прочее. Далее информация собирается в JSON строку, кодируется и отправляется запрос на получение рекламы. Теперь за дело берётся back-end.

455d29b5195d4f99abcddb3d71a0bfb1.jpg

Получив запрос на показ рекламы, так же получаем из базы всю известную нам информацию о данном посетителе (историю его интересов, просмотров рекламы и кликов). По user-agent’у мы получаем данные об используемом браузере, его версии и операционной системе посетителя, а по ip-адресу определяем его текущее местоположение. Всю собранную о пользователе информацию мы отправляем в нашу DMP для её дальнейшего анализа.

Собрав данные о пользователе, мы переходим к площадке. Получаем информацию о стоимости рекламного места, CTR площадки, категориях контента, наличию запрещённого контента и т.д., на основе этих данных будет сформирована минимальная пороговая цена аукциона. Закончив с площадками, переходим к самой длительной задачи SSP, это опрос подключенных DSP. На основе полученных выше описанным способом данных формируется запрос к DSP. Далее происходит паралельный опрос DSP, на ответ каждой из них отводиться 120 ms, в которые входит и время на доставку запроса, и получение ответа (ping до серверов, на которых расположена DSP). Так что месторасположение DSP тоже играет важную роль. Получив ответ от всех DSP, остаётся лишь отсортировать их по размеру ставки и взять ответ с самой большой. Ответ в виде JSON’а, для показа рекламы мы возвращаемся на front-end.

Фронтенду остаётся самая малость — вывести код полученного объявления. Так как уследить за качеством кода DSP и его совместимостью с площадками нет никакой возможности, наш код для вывода объявления на страницу создаёт отдельный iframe, загружает в него код, и вот его-то мы и выводим на страницу. На этом и заканчивается обработка запроса на рекламу.

Давайте теперь разберёмся с какими трудностями пришлось столкнуться в ходе реализации SSP, и как мы с ними справились. Одной из основных проблем в ходе реализации SSP стало забивание пула IIS. Причиной этому было ожидание ответа от DSP в течении 100 и более миллисекунд. В то время, когда SSP ждала ответа от DSP, остальные запросы ждали, пока SSP обработает текущий. А решением данной проблемы стало использование асинхронных контроллеров, вот здесь нам и пригодились модификаторы async/await. Также не лишним будет упомянуть, что информация о площадке и DSP кешируется в памяти приложения и ежеминутно обновляется. Следующим основным местом, на которое стоит обратить внимание, является опрос DSP. Первоначально встал вопрос, как распараллелить опрос DSP. В ходе разработки SSP было опробовано несколько вариантов решения этой задачи, таких как: Parallel.ForEach, Task.WaitAll и Task.WhenAll. Особых различий в производительности обнаружено не было, каждый способ исправно выполнял свою задачу, но в связи с переходом на асинхронную модель выбор пал на последний вариант. Сам запрос к DSP осуществляется посредством HttpWebRequest. Самое главное, что следует сделать при работе с HttpWebRequest, это включить поддержку KeepAlive, потому что запросы к DSP идут постоянно друг за другом, и постоянные обрывы и установка соединения начнут заметно тормозить получение ответа. Приведу пример получившегося класса для опроса DSP:

Код
public class DspRequests
{
    private const string _method = "POST";
    private const string _contentType = "application/json";
    private static List _headers = new List { "x-openrtb-version: 2.0" };
    private List _dspUrls { get; set; }

    public List DspUrls {
        get
        {
            returns _dspUrls;
        }
        set
        {
            _dspUrls = value;
        }
    }

    public async Task> PollDspAsync(string request)
    {
        List responses = null;
        var tasks = _dspUrls.DspRecords.Select(el => PollAsync(el, request));
        responses = (await Task.WhenAll(tasks)).Where(el => el != null).ToList();
        return responses;
    }

    private async Task PollAsync(string url, string bidRequest)
    {
        string response = null;

        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
        httpWebRequest.Method = _method;
        httpWebRequest.ContentType = _contentType;
        httpWebRequest.KeepAlive = true;
        foreach (string header in _headers)
            httpWebRequest.Headers.Add(header);
        httpWebRequest.Timeout = 120;

        using (StreamWriter streamWriter = new StreamWriter(await httpWebRequest.GetRequestStreamAsync()))
        {
            streamWriter.Write(bidRequest);
        }
        
        using (HttpWebResponse webResponse = (HttpWebResponse) await httpWebRequest.GetResponseAsync())
        {
            if (webResponse.StatusCode == HttpStatusCode.OK)
            {
                using (StreamReader streamReader = new StreamReader(webResponse.GetResponseStream()))
                {
                    response = streamReader.ReadToEnd();
                }
            }
        }

        return response;
    }
}



Клиентская часть нашей SSP. Это личный кабинет веб-издателя (площадки), который содержит статистику по всем его рекламным местам. VOX — это self-service платформа, позволяющая создавать как баннерные рекламные места (5 самых популярных в RTB размеров), так и Rich Media баннеры (fullscreen). На каждое рекламное место можно повесить заглушку (HTML или Javascript), а также добавить счетчик показов сторонней системы.

e03aaa6a36894e5c9cc0f82d3cd93f16.png

Вот на этом, пожалуй, мы и закончим обзор работы нашей SSP.

© Habrahabr.ru