Как устроена платформа динамиче­ского ценообразо­вания Райдтеха — показываем на практике

Всем привет! Меня зовут Саша Борзых, я работаю в отделе эффективности платформы Яндекс Такси, руковожу сектором разработки ценообразования.

В статье расскажу, как мы переделали платформу динамического ценообразования, сокращая time to market, то есть уменьшая время с момента появления идеи до ее проверки в продакшене. Посмотрим, что у нас получилось и какой опыт из этого можно почерпнуть. Поделюсь нашей игрой Surge, в которой можно в тестовом формате понять, как работает ценообразование сервисов в разных ситуациях.

Как работает бизнес Такси

Такси — такой вид организации рынка, когда у вас с одной стороны пользователи, которые хотят получить услугу, а с другой — исполнители заказов, которые могут эту услугу предоставить. В этом бизнес Такси похож на другие наши сервисы: в Еде есть курьеры, в Лавке есть курьеры, в Доставке тоже есть курьеры. Мы организуем рынок внутри платформы.

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

Любому маркетплейсу важно адекватно поддерживать баланс за счет цены, и мы ищем равновесную цену, при которой у нас всегда есть свободные исполнители, а цены настолько низкие, насколько возможно.

Что такое Surge

Surge (мы говорим «сурж») — это коэффициент повышения спроса. Его расчетом занята целая система, которая в реальном времени следит за тем, что происходит в бизнесе: сколько желающих уехать, сколько исполнителей на линии и так далее. И эта система выставляет соответствующие коэффициенты, поддерживает баланс спроса и предложения.

В ядре Surge — формула, которая принимает на вход множество параметров: точки А и Б заказа, число исполнителей в окрестности, тариф, число желающих уехать из точки А... На выходе — число, коэффициент, который нужно применить к базовой цене поездки или услуги. Пользователи Яндекс Go видят это так: открывают приложение, там появляется значок молнии, и фича «Индекс спроса» показывает, почему цена сейчас выше.

Водители в приложении Яндекс Про видят тепловую карту Surge — она у них фиолетовая. Карта влияет на поведение водителей: если они видят, что сейчас в их зоне повышенный спрос, — это мотивирует их оставаться там. И наоборот, если в их зоне спроса нет, а где-то в двух километрах он возник, водители перемещаются туда.

Если хотите посмотреть, как работает Surge на практике, зайдите в нашу игру и проверьте, сможете ли вы поддерживать баланс цен.

Старый и новый флоу разработки

В отделе эффективности платформы, где создаются Surge и Dispatch (система назначения водителей на заказ), типичная команда разработки состоит из тимлида, нескольких разработчиков и аналитика, который обычно одновременно и product owner. Вместе они постоянно думают, как что улучшить: смотрят метрики, выдвигают гипотезы, работают, в общем.

Разработка нового функционала выглядит так:

Большинство задач, создаваемых в Surge, — это изменение формулы расчета. Конечно, сам сервис — это не только формула. Там есть кеши, источники данных, разные статистики. Но большая часть всех задач от всех аналитиков — именно на расчет формулы. И мы подумали: почему бы не отделить формулу от основного сервиса? Дадим аналитикам инструменты для ее изменения, и если они касаются только формулы, они смогут быстро воплощать гипотезы без привлечения разработки.

В этом случае после появления идеи и заведения тикета аналитики сами меняют код расчета. Изменения проходят аудит: другие аналитики смотрят, всё ли в порядке с формулой. И если да — мы включаем ее и радуемся. Сравним старый флоу и оптимизированный.

ДоПосле
— идея;— идея;
— тикет;— тикет;
— обсуждение с разработкой;— изменение кода расчета;
— планирование;— аудит изменений;
— разработка с feature-flag;
— code review;— включение;
— релиз;— успех.
— включение;
— успех;
— тикет удаления feature-flag.

И мы эту очень заманчивую схему реализовали! Основной упор при этом сделали на то, чтобы отселить всё, связанное с формулой расчета Surge, в отдельный сервис. Аналитики правят формулу, а разработчики занимаются рантаймом: тем, чтобы формула выполнялась, в нее прокидывались дополнительные данные из сторонних сервисов. Так и поделили ответственность.

Архитектура новой платформы

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

Подобьём требования для создания платформы:

  • Быстрый расчет. Нужно уметь считать Surge быстрее, чем за 300 мс. Нагрузка на Surge в Такси — больше 10 000 RPS, для достижения этой скорости мы всё напишем на C++.
  • Низкий time to market. Это смысл всей затеи: делать большую часть работы аналитиков без привлечения разработки.
  • Возможность dry run. Dry run — режим проведения эксперимента, когда новый код запускается параллельно с основным, не влияя на расчеты в проде. Аналитик смотрит на логи продового и нового вычислений, подтверждает, что это ожидаемое поведение, и копирует изменения уже в прод.
  • Показ актуальной карты спроса в Яндекс Про. Усложняется тем, что исполнителей на линии много: сегодня RPS на отдачу карты спроса больше 200‌ 000.
  • Мониторинг. Нужно с минимальными задержками понимать, когда в системе что-то не так. Сам сервис Calculator, может быть, и не «пятисотит», но если при этом коэффициент Surge считается некорректно, то это однозначно приведет к дисбалансу рынка. Нас завалит заказами, если Surge низкий, а если наоборот — заказы упадут.

Так выглядит ландшафт новой платформы:

  • сервис Calculator занимается расчетом Surge;
  • сервис Calculator-storage хранит результаты этих расчетов;
  • фронтенд-интерфейс позволяет аналитикам в админке менять код расчетов;
  • во внешнем S3-хранилище лежат карты Surge, которые отображаются в приложении, — отдельный сервис Renderer отдает эти карты в приложение Яндекс Про.

Поговорим отдельно о компонентах. В основе платформы лежит библиотека JS-pipeline, созданная специально для этой задачи, но тем не менее не привязанная конкретно к Surge. Библиотека подробно описана на .

JS-pipeline просто дает нам запускать в плюсовом сервисе JS-код, написанный аналитиком, при помощи движка V8. А сервис Admin-pipeline хранит внутри себя весь JS-код, написанный аналитиками, со всей историей драфтов. Аналитик сделал изменение — создается драфт, некий патч к основному коду, другой аналитик проверяет его на предмет аналитической вшивости, а разработчики проверяют на undefined и всё остальное, в чём они понимают больше. И убедившись, что с изменением все хорошо, нажимают на кнопочку в интерфейсе.

Для админки сервис Admin-pipeline просто предоставляет REST-интерфейс с очень небольшой нагрузкой — 1 RPS. При этом библиотека JS-pipeline периодически выкачивает из этой админки, из ее базы, актуальный код.

Сервис Calculator общается с сервисом базового прайсинга. Когда клиент Яндекс Go открывает приложение и вбивает точки А и Б, этот запрос падает в сервис базового прайсинга, а он идет в Calculator, чтобы узнать тот самый коэффициент повышенного спроса, который нужно применить к цене. Calculator внутри использует библиотеку JS-pipeline и реализует весь код, необходимый для работы этой формулы.

Иногда аналитики просят добавить в формулу новые сущности или данные, полученные из сторонних сервисов, например, какие исполнители сейчас находятся рядом с точкой А и расстояние до них. Так как из JS мы не даем ходить во внешний мир, то это делают разработчики: пишут код на C++, который пробрасывает эти данные для формулы.

Сервис Calculator общается с сервисом Calculator-storage, где хранятся расчеты Surge. А еще Calculator пишет свои вычисления в Message Broker. У нас это Logbroker, у вас может быть Kafka, не принципиально.

Внутри Calculator — просто ручка с огромной обвязкой. Есть ручка Calc-surge, и базовый прайсинг приходит именно в нее. Мы параллельно запускаем два пайплайна: текущий продовый, который видят все, и измененный продовый, который аналитик хочет выкатить экспериментально. Пайплайны запускаются параллельно, мы дожидаемся результатов и наружу отдаем продовый расчет, а себе в Logbroker пишем результаты обоих и складываем продовые значения в Calculator-storage. Этот сервис держит 10 000 RPS.

Сервис Calculator-storage агрегирует расчеты Surge, сохраняет их себе в Redis и периодически генерирует карту спроса по расчетам в разных точках: интерполирует, рисует карту и складывает ее в хранилище S3. S3 выбран потому, что карты получаются довольно тяжелыми — 30–70 МБ, и удобнее использовать объектное хранилище, чем, например, складывать напрямую себе в Postgres. Сервис держит порядка 400 RPS, поскольку не все расчеты, которые приходят в Calculator, нужно сохранять для генерации карты.

И последний сервис — Renderer — выкачивает из S3 карты, которые сгенерировал Calculator-storage, и в виде PNG-тайлов отдает клиенту Яндекс Про.

Почему именно PNG? Причины две:

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

Renderer сейчас отдает все карты спроса всем пользователям Яндекс Про и держит порядка 200 000 RPS.

Профиты новой платформы

У нас получился калькулятор, который можно использовать в любом похожем сервисе со спросом и предложением:

  • Можно буквально скопировать калькулятор себе и получить аналогичный, например, для Доставки.
  • После этого можно создать пайплайн в админке Admin-pipeline и сказать, что ваш калькулятор будет запускать пайплайны из нее.
  • При необходимости можно доработать Renderer так, чтобы изменить отображение карт спроса, дописать логику: если пришел исполнитель из Еды — одно отображение, из Такси — другое. Это возможно, поскольку все наши исполнители работают через Яндекс Про.

Немаловажный блок посвящен аналитике. Как перемещаются данные, показано на картинке:

  • клиент Яндекс Go обращается в базовый прайсинг — прайсинг идет в Calculator;
  • Calculator все логи пишет в Message Broker;
  • логи перекладываются в ClickHouse;
  • Atlas web UI по данным ClickHouse отображает метрики уже перед аналитиком.

Метрики выглядят просто. В ClickHouse лежат все расчеты по всем географиям. Surge — просто некая цифра, и можно взять, например, все расчеты в конкретном городе и построить два графика: экспериментальный пайплайн и продовый. Аналитики видят, что в экспериментальном пайплайне есть изменение, открывают UI, он строит по данным из ClickHouse два графика. Специалисты сравнивают, видят, что Surge начал считаться иначе (как они и ожидали), и переносят изменение в продовый пайплайн.

Цифры и выводы

27 процессов уже используют платформу JS-pipeline. Хотя сама библиотека очень активно применяется в Surge, но не привязана к нему напрямую. В Райдтехе ее используют для расчета цен и в других местах.

С новым флоу аналитик, не дергая разработчиков, за 30 минут проводит эксперимент, который раньше занимал минимум 3 часа. Если раньше аналитик хотел поменять в формуле синус на косинус — требовалось завести пул-реквест, пройти тесты, зарелизиться, включить. А за счет того, что мы сделали обособленную библиотеку, стало возможно интегрировать в код сервиса, написанного на C++, отдельную часть на JS, которую можно будет в рантайме менять и использовать в любых областях и для любых задач. По похожей схеме у нас в Такси работает, например, Dispatch, делая скоринг водителей на заказы.

Ключевой вывод: очень полезно исследовать то, как у вас устроены процессы, и то, какими задачами вы по большей части заняты. Начав изучать это, вы, возможно, откроете, что часть задач в написании кода можно переложить на аналитиков или продактов. Научите их джаваскрипту — и таким образом снизите time to market.

Смотрите, как работает Surge на практике, в .

Другие публикации

  • 📹
  • mobile
  • Такси

Yet another Flutter DI