Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Привет, меня зовут Евгений. Я работаю в инфраструктуре поиска Яндекс.Маркета. Хочу рассказать сообществу Хабра о внутренней кухне Маркета – а рассказать есть что. Прежде всего, как устроен поиск Маркета, процессы и архитектура. Как мы справляемся с внештатными ситуациями: что случится, если упадёт один сервер? А если таких серверов будет 100?

А ещё вы узнаете, как мы внедряем новую функциональность на куче серверов сразу. И как тестируем сложные сервисы прямо в production, не доставляя пользователям никаких неудобств. В общем, как устроен поиск Маркета, чтобы всем было хорошо.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Un peu de nous : quel problème nous résolvons

Когда вы вводите текст, ищете товар по параметрам или сравниваете цены в разных магазинах, все запросы прилетают на сервис поиска. Поиск – это самый большой сервис в Маркете.

Nous traitons toutes les demandes de recherche : provenant des sites market.yandex.ru, beru.ru, du service Supercheck, Yandex.Advisor, des applications mobiles. Nous incluons également des offres de produits dans les résultats de recherche sur yandex.ru.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Par service de recherche, j'entends non seulement la recherche elle-même, mais également une base de données contenant toutes les offres du marché. L’ampleur est la suivante : plus d’un milliard de demandes de recherche sont traitées chaque jour. Et tout doit fonctionner rapidement, sans interruption et toujours produire le résultat souhaité.

Что есть что: архитектура Маркета

Кратко опишу текущую архитектуру Маркета. Условно можно описать её схемой ниже:
Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne
Допустим, к нам приходит магазин-партнёр. Говорит, хочу продать игрушку: вот этого злобного кота с пищалкой. И ещё злобного кота без пищалки. И просто кота. Тогда магазину нужно подготовить предложения, по которым Маркет осуществляет поиск. Магазин формирует специальный xml с предложениями и сообщает путь к этому xml через партнерский интерфейс. Затем индексатор периодически скачивает этот xml, проверяет на наличие ошибок и сохраняет всю информацию в огромную базу данных.

Таких сохранённых xml много. Из этой базы данных создается поисковый индекс. Индекс хранится во внутреннем формате. После создания индекса сервис Раскладки выкладывает его на поисковые серверы.

В итоге, в базе появляется злобный кот с пищалкой, а на сервере – индекс кота.

Je vais vous expliquer comment nous recherchons un chat dans la partie sur l'architecture de recherche.

Architecture de recherche de marché

Мы живем в мире микросервисов: каждый входящий запрос на marché.yandex.ru вызывает очень много подзапросов, и в их обработке участвуют десятки сервисов. На схеме изображены только некоторые:

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne
Упрощённая схема обработки запроса

У каждого сервиса есть замечательная штука – свой балансер с уникальным именем:

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

L'équilibreur nous offre une plus grande flexibilité dans la gestion du service : vous pouvez par exemple éteindre les serveurs, ce qui est souvent nécessaire pour les mises à jour. L'équilibreur voit que le serveur est indisponible et redirige automatiquement les demandes vers d'autres serveurs ou centres de données. Lors de l'ajout ou de la suppression d'un serveur, la charge est automatiquement redistribuée entre les serveurs.

Le nom unique de l'équilibreur ne dépend pas du centre de données. Lorsque le service A fait une demande à B, l'équilibreur B redirige par défaut la demande vers le centre de données actuel. Si le service n'est pas disponible ou n'existe pas dans le centre de données actuel, alors la demande est redirigée vers d'autres centres de données.

Единый FQDN для всех дата-центров позволяет сервису А вообще абстрагироваться от локаций. Его запрос в сервис B всегда будет обработан. Исключение составляет случай, когда сервис лежит во всех дата-центрах.

Но не всё так радужно с этим балансером: у нас появляется дополнительная промежуточная компонента. Балансер может работать нестабильно, и эта проблема решается избыточными серверами. Также происходит дополнительная задержка между сервисами A и В. Но на практике она меньше 1 мс и для большинства сервисов это некритично.

Борьба с неожиданностями: балансировка и отказоустойчивость сервиса поиска

Представьте, что случился коллапс: надо найти кота с пищалкой, но падает сервер. Или 100 серверов. Как выкрутиться? Неужели оставим пользователя без кота?

Ситуация страшная, но мы к ней готовы. Расскажу по порядку.

Поисковая инфраструктура находится в нескольких дата-центрах:

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

При проектировании мы закладываем возможность отключения одного дата-центра. Жизнь полна неожиданностей – например, экскаватор может перерубить подземный кабель (да, было и такое). Мощностей в оставшихся дата-центрах должно быть достаточно, чтобы выдержать пиковую нагрузку.

Рассмотрим отдельно взятый дата-центр. В каждом дата-центре одинаковая схема работы балансеров:

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne
Un équilibreur représente au moins trois serveurs physiques. Cette redondance est faite pour la fiabilité. Les équilibreurs fonctionnent sur HAProx.

Nous avons choisi HAProx en raison de ses hautes performances, de ses faibles besoins en ressources et de ses nombreuses fonctionnalités. Notre logiciel de recherche s'exécute à l'intérieur de chaque serveur.

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

C'est ce qui se passe en réalité : les serveurs crashent. Il est donc nécessaire de surveiller en permanence l’état de tous les serveurs. Si le serveur ne répond plus, il est automatiquement déconnecté du trafic. À cette fin, HAProxy dispose d’un bilan de santé intégré. Il est envoyé à tous les serveurs une fois par seconde avec une requête HTTP « /ping ».

Autre fonctionnalité de HAProxy : agent-check vous permet de charger tous les serveurs de manière uniforme. Pour ce faire, HAProxy se connecte à tous les serveurs, et ils renvoient leur poids en fonction de la charge actuelle de 1 à 100. Le poids est calculé en fonction du nombre de requêtes dans la file d'attente de traitement et de la charge sur le processeur.

Теперь о поиске кота. На поиск прилетают запросы вида /search?text=en colère+chat. Чтобы поиск был быстрым, весь индекс кота должен помещаться в оперативную память. Даже чтение из SSD недостаточно быстрое.

Autrefois, la base de données d'offres était petite et la RAM d'un serveur suffisait. Au fur et à mesure que la base d'offres s'est élargie, tout ne rentrait plus dans cette RAM et les données étaient divisées en deux parties : le fragment 1 et le fragment 2.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne
Но так всегда бывает: любое решение, даже хорошее, порождает другие проблемы.

L'équilibreur allait toujours vers n'importe quel serveur. Mais sur la machine d'où la requête est arrivée, il n'y avait que la moitié de l'index. Le reste était sur d'autres serveurs. Par conséquent, le serveur a dû se rendre sur une machine voisine. Après avoir reçu les données des deux serveurs, les résultats ont été combinés et reclassés.

Поскольку балансер распределяет запросы равномерно, то все серверы занимались переранжированием, а не только отдавали данные.

Le problème survenait si un serveur voisin n'était pas disponible. La solution consistait à spécifier plusieurs serveurs avec des priorités différentes comme serveur « voisin ». Tout d’abord, la requête a été envoyée aux serveurs du rack actuel. S'il n'y avait pas de réponse, la demande était envoyée à tous les serveurs de ce centre de données. Et enfin, la demande s'est adressée à d'autres centres de données.
По мере роста количества предложений данные разделили на четыре части. Но и это был не предел.

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

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

Les serveurs sont regroupés en clusters. Chaque cluster contient huit moteurs de recherche et un serveur d'extraits de code.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne
На сниппетном сервере работает key-value база данных со статическими данными. Они нужны для выдачи документов, например, описания кота с пищалкой. Данные специально вынесены на отдельный сервер, чтобы не загружать память поисковых серверов.

Étant donné que les ID de document sont uniques au sein d’un seul index, une situation peut survenir dans laquelle il n’y a aucun document dans les extraits de code. Eh bien, ou que pour un identifiant, il y aura un contenu différent. Par conséquent, pour que la recherche fonctionne et que les résultats soient renvoyés, il était nécessaire d’assurer une cohérence dans l’ensemble du cluster. Je vais vous expliquer ci-dessous comment nous surveillons la cohérence.

Сам поиск устроен следующим образом: поисковый запрос может прийти на любой из восьми серверов. Допустим, он пришел на сервер 1. Этот сервер обрабатывает все аргументы и понимает, что и как надо искать. В зависимости от входящего запроса сервер может делать дополнительные запросы во внешние сервисы за нужной информацией. За одним запросом может последовать до десяти запросов во внешние сервисы.

Après avoir collecté les informations nécessaires, la recherche commence dans la base de données des offres. Pour ce faire, des sous-requêtes sont effectuées sur les huit serveurs du cluster.

После получения ответов результаты объединяются. В конце для формирования выдачи могут понадобиться еще несколько подзапросов на сниппетный сервер.

Les requêtes de recherche au sein du cluster ressemblent à : /shard1?text=en colère+chat. Кроме того, между всеми серверами внутри кластера раз в секунду постоянно делаются подзапросы вида: /statut.

Demande /statut détecte une situation où le serveur n'est pas disponible.

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

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

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

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

Но переход на другую архитектуру еще не завершён. Сейчас мы хотим избавиться от выделенного сниппетного сервера. А затем вообще отойти от кластерной структуры. Это позволит нам продолжать легко масштабироваться. Дополнительный бонус – значительная экономия железа.

Et maintenant, des histoires effrayantes avec des fins heureuses. Considérons plusieurs cas d'indisponibilité du serveur.

Случилось ужасное: недоступен один сервер

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

Через проверку статуса /statut les serveurs voisins comprennent que l’un d’eux n’est pas disponible. Par conséquent, pour maintenir l'exhaustivité, tous les serveurs du cluster par requête /ping ils commencent à répondre à l'équilibreur qu'ils sont également indisponibles. Il s'avère que tous les serveurs du cluster sont morts (ce qui n'est pas vrai). C’est le principal inconvénient de notre système de clusters – c’est pourquoi nous voulons nous en éloigner.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Les requêtes qui échouent avec une erreur sont renvoyées par l'équilibreur sur d'autres serveurs.
Также балансер перестает отправлять на мёртвые серверы пользовательский трафик, но продолжает проверять их статус.

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

Ещё хуже: недоступно много серверов

Une partie importante des serveurs du centre de données est supprimée. Que faire, où courir ? L'équilibreur vient à nouveau à la rescousse. Chaque équilibreur stocke constamment en mémoire le nombre actuel de serveurs actifs. Il calcule en permanence la quantité maximale de trafic que le centre de données actuel peut traiter.

Когда падает много серверов в дата-центре, балансер понимает, что этот дата-центр не может обработать весь трафик.

Тогда избыточный трафик начинает случайным образом распределятся в другие дата-центры. Всё работает, все счастливы.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Как мы это делаем: публикация релизов

Теперь о том, как мы публикуем внесённые в сервис изменения. Здесь мы пошли по пути упрощения процессов: выкатка нового релиза почти полностью автоматизирована.
Когда набирается определённое количество изменений в проекте, автоматически создается новый релиз и запускается его сборка.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Ensuite, le service est déployé pour des tests, où la stabilité de fonctionnement est vérifiée.

Parallèlement, des tests automatiques de performances sont lancés. Ceci est géré par un service spécial. Je n'en parlerai pas maintenant - sa description mérite un article séparé.

Если публикация в testing прошла успешно, автоматически запускается публикация релиза в prestable. Prestable – это специальный кластер, куда направляется нормальный пользовательский трафик. Если он возвращает ошибку, балансер делает перезапрос в production.

В prestable замеряется время ответов и сравнивается с предыдущим релизом в production. Если всё нормально, то подключается человек: проверяет графики и результаты нагрузочного тестирования и затем запускает выкатку в production.

Tout le meilleur va à l’utilisateur : tests A/B

Il n’est pas toujours évident que les modifications apportées à un service apporteront de réels avantages. Pour mesurer l’utilité des changements, les gens ont mis au point des tests A/B. Je vais vous expliquer un peu comment cela fonctionne dans la recherche Yandex.Market.

Все начинается с добавления нового CGI-параметра, который включает новую функциональность. Пусть нашим параметром будет: market_new_functionality=1. Затем в коде включаем эту функциональность при наличии флага:

If (cgi.experiments.market_new_functionality) {
// enable new functionality
}

Новая функциональность выкатывается в production.

Pour automatiser les tests A/B, il existe un service dédié qui fournit des informations détaillées décrit ici. В сервисе создается экcперимент. Задается доля трафика, например, 15 %. Проценты задаются не для запросов, а для пользователей. Также указывается время эксперимента, например, неделя.

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

En conséquence, le service ajoute automatiquement un argument market_new_functionality=1 à 15% des utilisateurs. Il calcule également automatiquement les métriques sélectionnées. Une fois l’expérience terminée, les analystes examinent les résultats et tirent des conclusions. Sur la base des résultats, une décision est prise de passer à la production ou au raffinement.

Ловкая рука Маркета: тестирование в production

Часто случается, что надо проверить работу новой функциональности в production, но при этом нет уверенности, как она себя поведет в «боевых» условиях под большой нагрузкой.

Есть решение: флаги в CGI параметрах можно использовать не только для A/B-тестирования, но и для проверки новой функциональности.

Мы сделали инструмент, который позволяет мгновенно изменять конфигурацию на тысячах серверов, не подвергая сервис рискам. Он называется «Стоп-кран». Первоначальная идея заключалась в возможности быстро отключать какую-то функциональность без раскладки. Затем инструмент расширился и усложнился.

Le diagramme de flux de service est présenté ci-dessous :

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

Через API задаются значения флагов. Сервис управления сохраняет эти значения базе данных. Все серверы ходят в базу раз в десять секунд, выкачивают значения флагов и применяют эти значения на каждый запрос.

Dans le robinet Stop, vous pouvez définir deux types de valeurs :

1) Expressions conditionnelles. Appliquer lorsqu'une des valeurs est vraie. Par exemple:

{
	"condition":"IS_DC1",
	"value":"3",
}, 
{
	"condition": "CLUSTER==2 and IS_BERU", 
	"value": "4!" 
}

La valeur « 3 » sera appliquée lorsque la demande sera traitée à l'emplacement DC1. Et la valeur est « 4 » lorsque la demande est traitée sur le deuxième cluster du site beru.ru.

2) Безусловные значения. Применяются по умолчанию, если не выполнено ни одно из условий. Например:

valeur, valeur!

Si une valeur se termine par un point d'exclamation, elle reçoit une priorité plus élevée.

L'analyseur de paramètres CGI analyse l'URL. Applique ensuite les valeurs du Stop Tap.

Применяются значения со следующими приоритетами:

  1. С повышенным приоритетом из Стоп-крана (восклицательный знак).
  2. Значение из запроса.
  3. Значение по умолчанию из Cтоп-крана.
  4. Значение по умолчанию в коде.

Il existe de nombreux indicateurs qui sont indiqués sous forme de valeurs conditionnelles - ils suffisent pour tous les scénarios que nous connaissons :

  • Centre de données.
  • Окружение: production, testing, shadow.
  • Lieu : marché, beru.
  • Numéro de cluster.

Avec cet outil, vous pouvez activer de nouvelles fonctionnalités sur un certain groupe de serveurs (par exemple, dans un seul centre de données) et tester le fonctionnement de cette fonctionnalité sans risque particulier pour l'ensemble du service. Même si vous avez commis une grave erreur quelque part, que tout a commencé à s'effondrer et que l'ensemble du centre de données est tombé en panne, les équilibreurs redirigeront les demandes vers d'autres centres de données. Les utilisateurs finaux ne remarqueront rien.

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

Ce service a aussi ses inconvénients : les développeurs l'aiment beaucoup et essaient souvent de pousser toutes les modifications dans le Stop Tap. Nous essayons de lutter contre les abus.

Подход со Стоп-краном хорошо работает, когда у вас уже есть стабильный код, готовый к выкатке в production. При этом у вас ещё остаются сомнения, и вы хотите проверить код в «боевых» условиях.

Однако Стоп-кран не подходит для тестирования в процессе разработки. Для разработчиков есть отдельный кластер, который называется «теневой кластер».

Test secret : cluster fantôme

Les requêtes de l'un des clusters sont dupliquées vers le cluster fantôme. Mais l'équilibreur ignore complètement les réponses de ce cluster. Le schéma de son fonctionnement est présenté ci-dessous.

Comment fonctionne la recherche Yandex.Market et que se passe-t-il si l'un des serveurs tombe en panne

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

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

résultats

Итак, как же мы выстроили поиск Маркета?

Чтобы всё шло гладко, мы выделяем функциональности в отдельные сервисы. Так можно и масштабировать только те компоненты, которые нам нужны, и делать компоненты более простыми. Отдельный компонент легко отдать в другую команду и разделить обязанности по работе над ним. И значительная экономия железа при таком подходе – очевидный плюс.

Нам также помогает теневой кластер: можно разрабатывать сервисы, тестировать их в процессе и при этом не беспокоить пользователя.

Ну и проверка в production, конечно. Нужно изменить конфигурацию на тысяче серверов? Легко, используем Стоп-кран. Так можно сразу выкатить готовое сложное решение и сделать откат на стабильную версию, если возникнут проблемы.

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

Source: habr.com

Ajouter un commentaire