company_banner

Как не держать лишнее железо и справляться с ростом нагрузки: внедрение graceful degradation в Яндекс.Маркете

    Привет, меня зовут Евгений. Я разрабатываю инфраструктуру поиска Яндекс.Маркета. Хочу рассказать, как graceful degradation помогает нам обрабатывать больше запросов, чем физически могут выдержать наши сервера, и что происходит с поиском в Маркете, если один из дата-центров отключается.

    Проблема

    Все критичные сервисы в Яндексе должны переживать отключение одного из дата-центров (ДЦ), поэтому обычно они размещаются минимум в трёх ДЦ.

    Обычное состояние
    Обычное состояние

    Но когда все ДЦ работают, каждый из них оказывается задействован лишь на 60%. Ещё 10% резервируются для экспериментов и непредвиденного роста, а оставшиеся 30% используются только в случае, если один из ДЦ отключается, и нужно перераспределить запросы.

    ДЦ 2 отключён
    ДЦ 2 отключён

    Если сервис работает на сотнях серверов, 30% — это огромное количество железа. А поскольку отключаются ДЦ очень редко, резервные мощности почти всегда простаивают.

    Нам хотелось бы меньше греть воздух, ведь если сократить количество железа в каждом ДЦ хотя бы на 10%, речь уже шла бы о внушительных суммах. При этом, если просто вытащить часть железа, а затем при пиковой нагрузке какой-то из ДЦ отключится, оставшиеся мощности могут не справиться. Резко вырастет время ответа пользователю, а некоторые запросы будут вообще оставаться без ответа.

    ДЦ 1 и ДЦ 3 не справляются с нагрузкой
    ДЦ 1 и ДЦ 3 не справляются с нагрузкой

    Применяем graceful degradation

    Graceful degradation или изящная деградация — это подход к построению систем, при котором система продолжает выполнять свою основную функцию, даже если отдельные её элементы вышли из строя.

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

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

    Чтобы запустить graceful degradation, нам надо было решить две задачи:

    1. Разработать механизм уменьшения нагрузки.

    2. Сделать автоматизацию включения механизма.

    Механизм уменьшения нагрузки

    Уменьшить нагрузку можно по-разному. Один из вариантов — отвечать ошибкой на некоторые запросы. Но тогда надо понять, на что можно так отвечать, а на что нет. То есть нужен какой-то параметр «важность», которого мы не знаем. Если спросить у наших клиентов, что важно, они ответят, что важны все запросы, и ничего нельзя отбрасывать. Поэтому этот путь нам не подошёл.

    Другой вариант — использовать облегчённый алгоритм ранжирования. Минус в том, что это долго и сложно — новый алгоритм надо обучить и потом постоянно переобучать. Кроме того, состояние нашей системы может быть только «вкл.» или «выкл.», а нам хотелось бы иметь механизм плавного уменьшения нагрузки.

    Таким образом, мы выбрали третий вариант — снижать качество. Основное преимущество этого подхода — возможность уменьшать нагрузку на 5%, 10% и так далее.

    Допустим, вы ищете себе новый телефон и заходите в категорию «Смартфоны» на Яндекс.Маркете. Я уже подробно описывал, как работает наш поиск: запрос отправляется во фронтенд, надо показать пользователю 48 лучших предложений из категории с телефонами для конкретного региона. Фронтенд делает свой запрос в поисковый бэкенд.

    Бэкенд получает запрос и раcпределяет его на 8 серверов с шардами. В шардах хранятся предложения от магазинов.

    Общая схема обработки поискового запроса
    Общая схема обработки поискового запроса

    На каждом шарде поиск проходит несколько стадий. На стадии фильтрации ищется примерно 50 000 предложений, это число зависит от категории. На этапе ранжирования для каждого предложения вычисляется релевантность, учитывается цена, рейтинг товара, рейтинг магазина и ещё более 2000 факторов. ML по факторам вычисляет вес каждого предложения. Затем берётся только 48 лучших. Meta Search получает эти 48 предложений с каждого шарда, то есть всего 48*8=384 предложения. Предложения снова ранжируются, опять берётся 48 лучших. Последние 48 уже показываются пользователю. То есть чтобы показать нашим пользователям 48 телефонов, мы обрабатываем 400 000 предложений.

    Количество обрабатываемых документов без graceful degradation
    Количество обрабатываемых документов без graceful degradation

    В случае с graceful degradation, когда надо уменьшить нагрузку, мы можем скомандовать: теперь обрабатывай 95% документов, а теперь 90% или 80%. Если обрабатывать 95%, то есть 400 000*0.95=380 000 документов, то из них всё равно выбираются 48 лучших предложений для выдачи. И в среднем только 2 предложения будут отличаться от изначальной выдачи без снижения качества. При таком маленьком изменении большинство пользователей даже не заметят разницы.

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

    Автоматизация включения механизма

    Автоматизация работает за счёт постоянного мониторинга загрузки CPU. Если нагрузка становится выше 90%, автоматика начинает снижать качество. На 90% снижение небольшое, но если нагрузка продолжает расти, процент деградации повышается линейно и доходит до максимума при 100% загрузки CPU. Такой подход позволяет снижать качество минимально.

    Общий алгоритм выглядит так:

    При выключении ДЦ: балансеры перераспределяют запросы в оставшиеся ДЦ => нагрузка на CPU повышается => при превышении порогового значения происходит снижение качества по заданной формуле.

    При включении ДЦ: балансеры перераспределяют запросы на все ДЦ => нагрузка на CPU снижается => понижение качества прекращается.

    Повышение нагрузки при выключении ДЦ. Линии на верхнем графике показывают загрузку CPU в отдельных ДЦ. Нагрузка выросла с 82% до 98%. Нижний график показывает процент срезанных документов.
    Повышение нагрузки при выключении ДЦ. Линии на верхнем графике показывают загрузку CPU в отдельных ДЦ. Нагрузка выросла с 82% до 98%. Нижний график показывает процент срезанных документов.

    Внедрение

    Для внедрения мы провели несколько экспериментов и понижали качество на небольшом проценте пользователей. В течение недели мы постоянно отслеживали уменьшение нагрузки и одновременно количество переходов на магазины-партнёры. Имея на руках цифры, мы договорились с бизнесом на максимальное снижение кликов в 1% при снижении качества. Исходя из этого мы посчитали, сколько серверов можем отдать другим проектам или выключить для резерва. У нас получилось 15% всех мощностей поиска.

    В конце, когда всё было готово, мы провели эксперимент с отключением дата-центра, чтобы убедиться, что всё работает как надо.

    Выводы

    Graceful degradation — хороший способ не держать в резерве много железа на случай большой аварии вроде отключения дата-центра, а также для кратковременных повышений нагрузки, например, нашествия поисковых ботов.

    Яндекс
    Как мы делаем Яндекс

    Комментарии 18

      +1
      Уменьшить нагрузку можно по-разному… мы выбрали третий вариант — снижать качество
      — и это заметно. Недавно что то искал в Маркете — выдача не более 10 страниц, дальше товары отсутствуют. Чтобы найти то, «точно не знаю что», надо либо крутить фильтры (с неизвестным в смысле релевантности результатом), либо искать в другом месте. Лично я был разочарован — ждал от команды Яндекса большего.
        0
        А можете, пожалуйста, привести пример вашего запроса, по которому не было результата на первых 10 страницах? И номер обращения в поддержку, если писали. Было бы полезно.
          0
          Точно не помню, что то серверное искал и конечно ни в какую поддержку не обращался (я обычный покупатель — голосую ногами). Но вот сейчас захожу в каталог Маркета и выбираю: «Компьютерная техника — Компьютерные комплектующие — Рэковые корпуса» сортировка по цене по возрастанию, на 15 странице листание завершилось на товаре с ценником «3 230 ₽» (что очевидно далеко не конец списка в данной категории).

          Если теперь выбрать сортировку по убыванию цены, то первый товар в списке «1 395 210 ₽» и листание также заканчивается на 15 странице на товаре с ценой «91 428 ₽».

          Надеюсь что помог команде тестировщиков проекта Яндекс.Маркет)
          +1
          Я заводил десятки обращений — и ничего никогда не менялось. Хотите кейсы, их есть у меня? Вот у меня в закладках лежит Аккумуляторная дисковая пила Bosch BITURBO GKT 18V-52 GC Professional, (06016B4000), продавалась в магазине b-tools.ru.

          Пробуем сейчас «найти ее в других магазинах» (на самом деле она все еще продается, в том же самом — я проверял — b-tools.ru/product/bosch-gkt-18v-52-gc-akkumulyatornaya-diskovaya-pila-06016b4000 — оно конечно «уточняйте наличие», но в корзину я ее положить могу, и я такие вопросы с магазином в любом случае решил бы сам). Но мы ничего не находим.

          И что самое противное — все что найдено, не имеет никакого отношения к тому, что ищем. Т.е. 99% результатов поиска я иначе как спам рассматривать не могу (ну точнее так — где-то на 8м месте есть один похожий товар, а на второй странице — еще два). Качество поиска, где на три страницы три релевантных результата вы как оцените?
            +2
            К вопросу о «наличии», яндекс показывает то, что ему магазин выгрузит в специальной XML-ке. Что кореллирует с данными на сайте по усмотрению магазина. В остальном — качество поиска отвратительное, да.
              +1
              Я догадываюсь, что они не парсят сайты магазинов, да. Но скажем так, это скорее путает, чем помогает, в текущем виде — потому что я вижу магазин, и вижу там товар, но не могу его найти (если на сайте магазина есть признак «наличие уточняйте» — было бы логично, чтобы и у Маркета такой признак тоже был).

              Но в общем-то, у меня претензия к поиску не в этом, а скорее в том, что имеет место попытка найти «что-то похожее по названию» вместо того, чтобы найти точное совпадение по параметрам (если уж не конкретную модель). Ну т.е. смотрите, Bosch GKT 18V-52 GC — это вот что:
              — ручная циркулярная пила
              — аккумуляторная (у Bosch три линейки аккумуляторов, в том числе две — 18В, несовместимые друг с другом)
              — погружная
              — для работы по шине (погружная обычно означает шину, но не наоборот)
              — по дереву (есть специальные пилы по металлу, там много чего другое)

              И мне вместо нее в поиске вываливают просто циркулярные пилы, какие попало. Ну т.е. вот из этих 5 пунктов только один совпадает в 99% случаев. А почему? А потому, что там просто нет этих признаков, если открыть карточку товара, то вы не найдете там признаков «погружная», «по шине» или «для дерева» — их там просто нет.

              Ну и в итоге мы имеем то что имеем — три страницы результатов, из них одна — сетевая пила Боша, которые более-менее подходит, аккумуляторная Макита (слишком дорого, ибо нужно покупать и аккумуляторы тоже), Макита по металлу. И это все, все остальное вообще не имеет отношения к делу.

              Зачастую в таких случаях намного лучше было бы ответить, что ничего не нашли.
              0
              И что самое противное — все что найдено, не имеет никакого отношения к тому, что ищем. Т.е. 99% результатов поиска я иначе как спам рассматривать не могу
              Такие жалобы я вижу на Хабре далеко не в первый раз. Уверен, что BarakAdama и другие сотрудники Яндекса их тоже видят. Уж сколько времени прошло, а воз и ныне там…
                +1
                Вообще, мне кажется что плохая поддержка — это самый большой недостаток этого продукта (это не относится к Яндекс Маркету, у гугля, или скажем у карт примерно такие же проблемы). Ну т.е. я реально много раз заводил обращения — результат с моей точки зрения близок к нулю.

                У меня даже пост в черновиках на эту тему валяется, пока сомневаюсь, стоит ли его публиковать (на тему улучшения такого сорта поиска техническими средствами). Я при этом прекрасно понимиаю, что реализация изменений в большом продукте может быть делом сложным и не быстрым.
                  0
                  реализация изменений в большом продукте может быть делом сложным и не быстрым.
                  … что не может служить поводом этого не делать.
                  Поэтому публиковать Ваш «пост в черновиках», на мой взгляд, непременно сто́ит.
                  Главное — после публикации разослать ссылку на статью Яндексу, Гуглю, Картам и.т.д., чтобы заставить их реагировать как положено, а не как им удобнее:
                  я реально много раз заводил обращения — результат с моей точки зрения близок к нулю.
                    0
                    Ну я в общем-то уже его опубликовал. Хотя не думаю что это как-то улучшит поддержку всех названных компаний, да и пост в общем не про нее.
                      +1
                      Отлично, спасибо!
                      Теперь обязательно отправьте ссылку на статью в Яндекс.Маркет и другим сервисам, указав, что за 7 часов статью прочитали 2000 человек.
                      Это работает (хотя и не всегда).
          +1
          Автоматизация работает за счёт постоянного мониторинга загрузки CPU. Если нагрузка становится выше 90%, автоматика начинает снижать качество.

          То есть такая система будет хорошо работать только в случае если на сервис выделено отдельное железо?
            0
            Этот подход будет хорошо работать, если невозможно быстро поднять новые инстансы сервиса. То есть, даже если вы в AWS, но запуск нового инстанса занимает много времени, то лучше сделать механизм уменьшения нагрузки.
              0
              Разумеется, это одно из ключевых условий
              +1
              Нам хотелось бы меньше греть воздух, ведь если сократить количество железа в каждом ДЦ хотя бы на 10%, речь уже шла бы о внушительных суммах. При этом, если просто вытащить часть железа, а затем при пиковой нагрузке какой-то из ДЦ отключится, оставшиеся мощности могут не справиться.

              По-моему тут что-то недоговорили. Если проблема только в энергопотреблении (как заявлено) то можно простаивающее железо и выключать, а включать только в аварийной ситуации (понятно, не мгновенно, но не думаю что это вызовет проблемы, всё-таки это по идее редкое событие). Или датацентры ежедневно вводятся/выводятся из строя?
              Но за само железо в таком случае всё равно придётся платить, да, почему-то об этом не сказано.

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

                Действительно, достаточно лишь снизить нагрузку, но начальству не объяснить

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

                Самое читаемое