Краткая предыстория
Oceanus – это унифицированная структура управления HTTP-сервисами, разработанная отделом инфраструктуры Meituan. Она основана на расширениях Nginx и ngx_lua. В основном она обеспечивает регистрацию и обнаружение сервисов, динамическую балансировку нагрузки, визуальное управление, настраиваемую маршрутизацию, защиту от маршрутизации, повторное использование идентификатора сеанса, и понижение рейтинга автоматических выключателей., статистика перехвата и производительности одним ключом и другие функции. В этой статье в основном описывается, как Oceanus реализует настраиваемую маршрутизацию HTTP-запросов с помощью абстрагирования политик, запросов, рендеринга и группового динамического обновления. С быстрым развитием бизнеса компании сценарии маршрутизации становятся все более сложными. Например:
- Для всплесков групповых покупок вам необходимо гибко управлять потоком измерения давления и реализовать многомерное измерение давления онлайн-сервисов на одном узле, в каждой компьютерной комнате и в каждом регионе.
- Бизнесу на вынос необходимо изолировать трафик, перенаправить трафик в северном регионе в группу а, а трафик в южном регионе — в группу б.
- Винному туристическому бизнесу необходимо использовать оттенки серого в новой версии приложения, чтобы тысячная часть пользователей могла попробовать новую версию, а другие пользователи могли получить доступ к старой версии.
- Отделу контроля качества необходимо указать группу пересылки с помощью запрошенных пользовательских параметров, чтобы создать стабильную и высокодоступную тестовую среду.
Поскольку ранние бизнес-сценарии компании были относительно простыми, все они поддерживались инструкциями Nginx. Например, если службе необходимо пересылать запросы с исходным IP-адресом 10.4.242.16 на внутренний узел 10.4.232.110, а другие запросы на внутренние узлы 10.4.232.111 и 10.4.232.112, можно выполнить следующую конфигурацию. :
upstream backend_aaa {
server 10.4.232.110:8080 weight=10;
}
upstream backend_bbb {
server 10.4.232.111:8080 weight=10;
server 10.4.232.112:8080 weight=10;
}
location /abc {
if($remote_ip = "10.4.242.16") {
proxy_pass http://backend_aaa; #路由到backend_aaa集群
}
proxy_pass http://backend_bbb; #路由到backend_bbb集群
}
Хотя описанный выше метод не требует дополнительной разработки, а производительность близка к нативному фреймворку Nginx, сценарии использования относительно ограничены, поскольку инструкция if поддерживает только относительно простые типы условий.Официальное описание выглядит следующим образом:
Если служба хочет перенаправить запрос IP-сегмента 10.4.242.16/34 на 10.4.232.110, команда if вряд ли сможет это поддержать. Однако для описанных выше сложных бизнес-сценариев команда if не поддерживается. Кроме того, этот метод имеет следующие два недостатка:
- Настройка правила не поддерживает динамическую: если вы хотите настроить клиента 10.4.242.16 на 10.4.242.17, вам необходимо перезагрузить Nginx, а операция перезагрузки снизит возможности параллелизма Nginx и даже приведет к запросам 504 или 502 во время пиковые часы работы.
- Слишком много пробелов в инструкциях: когда инструкция if используется вместе с инструкциями set и rewrite, во многих случаях возникает неожиданное поведение, а в тяжелых случаях даже segfault.Лучший способ — избегать их использования.
Чтобы решить вышеуказанные проблемы, Oceanus начал исследовать, как реализовать настраиваемую маршрутизацию HTTP-трафика.
Отраслевые исследования
В ходе предварительных исследований было обнаружено, что в отрасли существует набор фреймворков с открытым исходным кодом ABTestingGateway (далее именуемый AB):
Как показано на рисунке выше, платформа AB использует Redis для хранения данных политики, ключ — это поле Host, а значение — объект политики, включая тип политики, интервал соответствия и восходящий поток для распространения. Добавление, удаление, изменение и запрос политик можно реализовать через API веб-сервиса, построенного на Nginx.Во время выполнения связанные политики получаются из lua-shared-dict или Redis в соответствии с запрошенным полем Host и выбираются в соответствии с к типу политики (iprange/uidrange/uidsuffix/uidappoint). Соответствующий сценарий Lua получает соответствующие параметры (IP, UID) из запроса, чтобы проверить, соответствует ли политика. Если они совпадают, восходящий контекст запроса изменяется на выполнить цель разгрузки. По сравнению с инструкцией if инфраструктура AB имеет следующие два преимущества:- Корректировка политики вступает в силу динамически: изменениями политики в существующих типах политик можно динамически управлять через HTTP API.
- Богатые стратегии разгрузки: поддержка IP-сегмента, сегмента UID и других стратегий, а также возможность расширения библиотеки стратегий путем добавления новых типов стратегий.
Поскольку инфраструктура AB поддерживает только 4 типа стратегий, если бизнесу необходимо контролировать переадресацию на основе файлов cookie запросов и пользовательских заголовков, необходимо разработать новые типы стратегий и опубликовать их в Интернете. Кроме того, типы политик тесно связаны с бизнес-сценариями, что приводит к крайне плохой масштабируемости системы AB, что затрудняет быструю поддержку требований к маршрутизации новых сервисов.
Будь то команда Nginx if или инфраструктура AB, ее либо нужно перезагрузить, чтобы она вступила в силу, либо она не может поддерживать требования отклонения в некоторых бизнес-сценариях, поэтому трудно быть эффективным средством для решения отклонения на уровне компании. рамки. Ввиду их недостатков, Oceanus разработал набор хорошо масштабируемых динамических сред разгрузки на уровне приложений, которые не только динамически поддерживают требования к разгрузке различных бизнес-сценариев, но и обеспечивают производительность переадресации запросов. решить механизм разгрузки несколько основных вопросов.
Основной дизайн и реализация индивидуальной маршрутизации Oceanus
Что касается механизма диверсии, то мы в основном говорим о нем со следующих четырех аспектов:
- Абстракция стратегии: разумно определите структуру стратегии и примените ее к как можно большему количеству бизнес-сценариев.
- Эффективный запрос политик: ассоциация детализации интерфейса, управление измерениями приложений.
- Рендеринг стратегии во время выполнения: визуализация шаблона стратегии, оценка его соответствия стратегии и реализация динамической маршрутизации.
- Динамическое обновление группы: добавление, удаление и изменение групповых данных не требуют перезагрузки.
Определение структуры политики
Взяв в качестве примера структуру AB, она поддерживает только четыре сценария: iprange, uidrange, uidsuffix и uidappoint Тип политики и метод сопоставления слишком специфичны, поэтому она не может поддерживать более общие бизнес-сценарии. Начиная с сути шунтирования, то есть до полной кастомизированной маршрутизации трафика по характеристикам запроса. Комбинируя несколько компонентов инструкции Nginx if: переменные, зависящие от условного суждения, значение, которое должно быть сопоставлено для условного суждения, условное выражение и proxy_pass, который должен выполняться после сопоставления, политика должна содержать описание функции запроса, настраиваемое описание маршрутизации и описание обоих отношений. . Описание функции запроса включает ключевое слово функции и режим передачи контекста ключевого слова.Настраиваемое описание маршрута представлено восходящим потоком, который может быть предварительно задан или задан динамически, а связь между ними представлена общим выражением. Тогда стратегия должна содержать следующие атрибуты:
- имя: имя политики, которое не имеет практического значения и может быть определено в соответствии с бизнес-сценариями.
- ключ: ключевое слово, которое зависит от распределения.Например, когда маршрутизация распределяется по региону города, ключом является regionid.
- passway: метод передачи ключевого слова в протоколе HTTP, который может быть одним из параметров, файлов cookie, заголовка и тела.
- условие: шаблон выражения, поддерживает четыре арифметические операции/модуль, операторы отношения, логические операторы и т. д.
- группа: Кластер внутренних служб, то есть целевой узел, который пересылает запрос после сопоставления с политикой, который обычно является частью узла в кластере приложений, к которому относится политика.
- категория: Тип политики, если это 1, это означает частную политику службы; если это 2, это означает общедоступную политику, которая в основном используется для управления данными политики.
- переключатель: Переключатель политики, используемый для управления тем, является ли текущая политика онлайновой или автономной.
- серый список: список оттенков серого, используемый для онлайн-проверки изменений политики в оттенках серого.
Среди них поля переключателя и серого списка в основном используются для онлайн- и офлайн-операций политики, которые не будут подробно обсуждаться здесь. Далее основное внимание уделяется тому, как приведенное выше определение политики выражает бизнес-сценарий:
Примечания: Примените apk1 и apk2 для настройки двух частных политик соответственно, а apk3 использует общедоступную политику. Как показано на рисунке выше, структура политики может поддерживать независимо от того, какие характеристики запроса используются для распределения трафика. Возьмите в качестве примера частную политику Gray-Deploy, добавьте ее на платформу управления Oceanus, как показано на следующем рисунке: Примечание. Неосновные поля стратегии, такие как переключатель, серый список и т. д., здесь опущены.Как реализовать эффективный запрос политик?
Топология политики
Стратегии дивергенции делятся на частные стратегии и публичные стратегии. Частные политики ориентированы на службы и тесно связаны с группами, созданными службой. Приватные политики разных сервисов полностью независимы и могут быть одинаковыми или разными. Служба может быть настроена с несколькими частными политиками, а также может быть связана с несколькими узлами.Политики между расположениями полностью независимы.Местоположение может включать одну или несколько частных политик службы. Если данные политики напрямую связаны с Host+location_path, будет большая избыточность данных, когда разные местоположения связаны с одной и той же частной политикой. Поэтому мы связываем конкретные данные политики через идентификатор службы (ключ приложения, который однозначно идентифицирует службу приложения). Host+location_path связывает только список имен политик, используемых текущим расположением, и политики поддерживают указанный порядок. Общедоступные политики не имеют ничего общего с конкретными службами, а имя политики глобально уникально.Вы можете использовать имя политики для связывания данных политики. Таким образом, топологическая связь стратегии описывается следующим образом:
Как показано на рисунке выше, на примере приложения apk1 связаны два интерфейса Location, а именно /api и /list, всего развернуто 8 узлов и созданы 2 группы ups-cq и ups-gray, из которых узел 10.5.23.6 и 10.5.24.72 относятся к группе ups-cq, а узлы 10.7.46.32 и 10.7.72.232 относятся к группе ups-grey. Приложение настроено с двумя частными политиками стресс-тестирования и серого развертывания, где стресс-тестирование политики включено интерфейсом / API, трафик, соответствующий политике, направляется в пакет ups-cq, политика серого развертывания включено интерфейсом/списком, а политика сопоставления — Трафик направляется в ups-grey.Получить путь к местоположению во время выполнения
Когда Nginx анализирует конфигурацию Location, разные типы Locations различаются по разным полям, а путь к Location в конфигурации не записывается. Если вы хотите получить его во время выполнения, обычно есть два способа: один — обратно восстановить путь в соответствии с соответствующими полями, а другой — добавить переменные в фреймворк. Так как Nginx не отмечает случай игнорирования case при обработке обычного Location, то есть процесс парсинга необратим, поэтому выбираем второй способ. В массив переменных ngx_http_core_variables основного модуля добавляется встроенная переменная, и записывается исходный путь Location.Атрибуты переменных определяются следующим образом:
{ngx_string("loc_mod"), NULL, ngx_http_variable_loc_mod,
0, NGX_HTTP_VAR_NOCACHEABLE, 0},
{ngx_string("loc_name"), NULL, ngx_http_variable_loc_name,
0, NGX_HTTP_VAR_NOCACHEABLE, 0}
Для связи между loc_mod и loc_name используется символ пробела, а формат соответствует платформе управления Oceanus.
Механизм асинхронного обновления
Чтобы обеспечить эффективность получения данных политики во время выполнения, мы синхронизируем весь объем данных политики с локальной общей памятью посредством асинхронного извлечения по времени. Основываясь на соображениях стабильности и гибкости, мы приняли стратегию хранения реляционной базы данных MySQL. Механизм обновления показан на следующем рисунке:
- Oceanus случайным образом выбирает рабочий процесс на этапе init_worker и встраивает таймер.
- Выбранный рабочий процесс будет периодически извлекать данные политики из MySQL асинхронно и без блокировки.
- Рабочий процесс таймера анализирует извлеченные данные политики и обновляет их в области буфера записи в текущей общей памяти в соответствии с топологическими отношениями политики.После завершения обновления он переключает область буфера чтения и записи, чтобы гарантировать, что последняя политика вступает в силу немедленно.
- Когда рабочий процесс обрабатывает запрос, он получает данные политики из буфера чтения в текущей разделяемой памяти.
Чтобы решить проблему гонки между рабочими таймерами и другими рабочими процессами при чтении и записи данных политики, мы внедрили механизм двойного буфера для реализации чтения и записи данных политики без блокировок на бизнес-уровне. Кроме того, если установить время таймера равным 0, гарантируется, что данные политики будут инициализированы в общей памяти до того, как все рабочие процессы обработают запросы.
Механизм запроса политики
Алгоритм запроса показан на следующем рисунке:
- Рабочий процесс получает запрошенный хост из контекста запроса и location_path соответствующего местоположения.
- В соответствии с Host+location_path запросите имя включенной политики в общей памяти.
- Если это общедоступная политика, запрашивайте данные политики непосредственно на основе имени политики.
- Если это частная политика, получите Upstream, связанный с Location, из контекста запроса, то есть appkey идентификатора приложения, и получите конкретные данные политики из области кэша чтения общей памяти.
Примечание. Публичные политики начинаются с «oceanus», что отличается от названия частных политик.
рендеринг стратегии во время выполнения
После запроса политики, включенной запросом, Oceanus должен оценить, соответствует ли она во время выполнения.В качестве примера частной политики поток выполнения показан на следующем рисунке:
- На этапе перезаписи Oceanus встраивает обратный вызов через rewrite_by_lua_file, чтобы инициировать обработку запроса и войти в основной процесс разгрузочной среды.
- Получите запрошенную политику с помощью вышеуказанного механизма запроса политики, проанализируйте ее и получите ключ и проход политики.
- Получить значение ключа из контекста, соответствующего запросу в соответствии с проходом.
- Используйте условие стратегии рендеринга значения, полученное в 3, и замените заполнитель в условии значением.
- На основе Lua VM результат условия вычисляется по нагрузке, то есть истинно или ложно.
- Получите значение и групповые данные условия из политики.
- Если условие истинно, перезапишите запрошенный вышестоящий контекст группой, в противном случае ничего не делайте.
Динамическое обновление группы
Динамизирование списка группировок является важной частью структуры сортировки. Механизм обновления показан на следующем рисунке:
- Пакетные данные хранятся с помощью ZooKeeper, а изменения постепенно синхронизируются с помощью механизма наблюдателя.
- Oceanus также будет регулярно запрашивать полную синхронизацию.
- Oceanus синхронизирует все изменения в памяти Nginx через локальные вызовы HTTP.
- Прежде чем рабочий процесс обработает запрос на изменение, он сначала захватит блокировку, прочитает очередь сообщений в общей памяти и синхронизирует исторические изменения, сделанные другими рабочими процессами.
- Синхронизируйте это изменение с основным контекстом восходящего потока текущего рабочего процесса, чтобы завершить обновление текущего рабочего процесса.
- Инкапсулируйте изменения в виде сообщений и добавляйте их в очередь в общей памяти.
- Другие рабочие процессы читают очередь сообщений по таймеру или перед обработкой сообщения об изменении самостоятельно, чтобы завершить обновление.
Резюме и перспективы
С помощью маневрового механизма Oceanus, который широко используется в нескольких направлениях бизнеса, таких как еда на вынос Meituan, винные путешествия, кейтеринг в магазине и т. д., отдел инфраструктуры помогает деловым соотечественникам решать потребности нескольких индивидуальных маршрутов, таких как набор услуг, стресс-тестирование ссылок, публикация в оттенках серого, построение среды плавательных дорожек и т. д. В настоящее время механизм разгрузки Oceanus фокусируется только на направлении переадресации трафика и не поддерживает более сложные действия по переадресации, такие как корректировка запрошенного параметра, заголовка и файла cookie в соответствии с политикой, а также не поддерживает динамическую маршрутизацию на основе запрошенный URL. Конечно, чтобы решить эти проблемы, вы можете связаться с нами и добиться прогресса вместе.
об авторе
Чжоу Фэн, старший инженер Meituan, присоединился к отделу инфраструктуры Meituan в июле 2015 г. Он отвечал за единую службу управления ключами, интеллектуальную службу защиты от сканирования и балансировку нагрузки HTTP.В настоящее время он в основном отвечает за соответствующую работу по управлению службами HTTP. Oceanus, и стремится исследовать И исследовать услуги в направлении автоматизации, интеллекта и высокой производительности.
Объявление о приеме на работу: если вы заинтересованы в управлении службами HTTP, отслеживании ссылок распределенных сеансов и других системах в крупномасштабной распределенной среде, вы искренне можете отправить свое резюме по адресу: zhangzhitong#meituan.com.
использованная литература
- ngx_http_rewrite_module:Nginx.org/en/docs/red-glowing…
- Рамка АБ:GitHub.com/CNS Re/AB TE — это…