задний план
В микросервисной архитектуре большая система разделена на несколько небольших служб, и большое количество вызовов RPC между небольшими службами часто может привести к сбою вызовов RPC из-за нестабильности сети и других причин.В настоящее время использование механизма повторных попыток может улучшить окончательный успех скорости запросов, уменьшить влияние сбоев и сделать систему более стабильной.
риск повторной попытки
Повторная попытка может улучшить стабильность службы, но в нормальных условиях каждый не будет легко повторять попытку или не осмелится повторить попытку, главным образом потому, что повторная попытка может усилить сбой.
Во-первых, повторение увеличит нагрузку непосредственно ниже по течению. Следующая диаграмма B предполагается, что служба сервисный вызов, количество повторных попыток, установленных как R (запрос, включая первый), когда высокая нагрузка, скорее всего, вызов не удается, то отказ вызова повторяется BA, B содержимое И Услуги называют быстрым ростом большим, худший случай может быть преувеличен до R раз, не только запрос был успешным, может привести к нагрузке B продолжает расти, даже ударил напрямую связанный.
Что еще более пугает, так это то, что повторная попытка также будет иметь эффект усиления ссылки, что объясняется в сочетании со следующим рисунком:
Предположим, текущий сценарий заключается в том, что серверная часть A вызывает серверную часть B, а серверная часть B вызывает интерфейс БД, а число повторных попыток установлено равным 3. Если Backend B вызывает DB Frontend и запрос терпит неудачу 3 раза, Backend B вернет отказ Backend A. Но бэкенд A также имеет логику повторных попыток: бэкенд A трижды пытается бэкэнд B, и каждый раз бэкенд B будет запрашивать интерфейс БД 3 раза, таким образом, интерфейс БД будет запрашиваться 9 раз, что на самом деле является экспоненциальным расширением. Предполагая, что нормальный трафик равен n, канал имеет в общей сложности m уровней, а количество повторных попыток на каждом уровне равно r, тогда последний уровень получает наибольший объем трафика, который равен n * r ^ (m - 1) . Эффект этого экспоненциального усиления ужасен, и он может привести к нарушению работы нескольких уровней канала и лавине всей системы.
Стоимость повторного использования
Кроме того, стоимость использования повторных попыток относительно высока. Ранее внутренняя структура и платформа управления службами ByteDance не поддерживали повторную попытку. усиление эффекта повторной попытки не учитывается, что очень небезопасно.В компании было много аварий, вызванных повторной попыткой, и когда происходит авария, необходимо изменить код, чтобы выйти в онлайн, чтобы закрыть повторную попытку, что привело к аварии восстановление не быстрое..
Кроме того, есть некоторые компоненты для повторных попыток бизнеса, которые используют открытый исходный код. Эти компоненты обычно считают прямую защиту вниз по течению, но не учитывайте меняющиеся повторные попытки, что требует от службы для изменения кода вызова RPC, и бизнес-код вторжения И все еще статические конфигурации вы должны перевернуть онлайн, когда вам нужно изменить конфигурацию.
Основываясь на вышеизложенном, чтобы позволить деловым сторонам гибко и безопасно использовать повторные попытки, наша команда промежуточного этапа прямых трансляций ByteDance разработала и внедрила компонент управления повторными попытками, который имеет следующие преимущества:
- Возможность предотвращения повторных штормов на уровне канала.
- Простота использования гарантирована, а стоимость доступа к услугам низкая.
- Гибкость для динамической настройки конфигурации.
Конкретная схема реализации описана ниже.
повторить управление
Динамическая конфигурация
Как обеспечить легкий доступ бизнес-стороне — это первая проблема, которую необходимо решить. Если это по-прежнему общая библиотека компонентов, все равно неизбежно вторжение большого количества пользовательских кодов, и ее трудно динамически настроить.
Среда разработки ByteDance Golang поддерживает режим промежуточного программного обеспечения, который может регистрировать несколько пользовательских промежуточных программ и вызывать их рекурсивно по очереди.Обычно он используется для завершения некоммерческой логики, такой как печать журналов, отчетность и мониторинг, и может эффективно интегрировать бизнес и некоммерческие код, функции развязаны. Поэтому мы решили использовать метод промежуточного ПО для реализации функции повтора, определить промежуточное ПО и реализовать повторные вызовы RPC внутри, а также сохранить информацию о конфигурации повторных попыток в распределенном центре хранения конфигурации с опережением байтов, чтобы промежуточное ПО могло читать. настроить центр и повторить попытку, пользователю не нужно изменять код, вызывающий RPC, а нужно только ввести глобальное ПО промежуточного слоя в службу.
Как показано на общей схеме архитектуры ниже, мы предоставляем веб-страницу и фон для настройки. Пользователи могут легко настраивать и изменять RPC на странице, посвященной управлению службами, и автоматически вступают в силу. Внутренняя логика реализации прозрачна для пользователей и для бизнес-кода. , Нет вторжения.
Измерение конфигурации основано на характеристиках вызовов RPC ByteDance.Выберите [служба вызывающего абонента, кластер вызывающего абонента, вызываемая служба, вызываемый метод] в качестве кортежа и настройте в соответствии с кортежем. Промежуточное ПО инкапсулирует метод чтения конфигурации, который будет автоматически прочитан и вступит в силу при вызове RPC.
Этот метод промежуточного программного обеспечения позволяет деловым сторонам легко получить доступ, что намного удобнее, чем предыдущий метод общей библиотеки компонентов, и имеет возможность динамической настройки после одного доступа, что может легко настроить или закрыть конфигурацию повторной попытки.
стратегия отсрочки
После того, как режим доступа определен, могут быть реализованы определенные функции компонента повторных попыток.Среди основных функций, включенных в компонент повторных попыток, в дополнение к базовой конфигурации, такой как количество повторных попыток и общая задержка, также есть стратегия отсрочки. обязательный.
Для некоторых временных ошибок, таких как дрожание сети и т. д., которые могут быть повторены немедленно или будут неудачными, обычно нужно немного подождать и повторить попытку, если вероятность успеха будет выше, а также может нарушить время повторных попыток в восходящем направлении, потому что меньше At одновременно все повторные попытки, вызванные пиковым мгновенным расходом ниже по течению. Решите, как долго ждать и повторить попытку после того, как метод называется стратегией отката, мы достигли общих стратегий отката, таких как:
- Линейная отсрочка: повторите попытку каждый раз после ожидания фиксированного времени.
- Случайная отсрочка: повторите попытку после ожидания случайного времени в пределах определенного диапазона.
- Экспоненциальная отсрочка: при непрерывных повторных попытках каждое время ожидания кратно предыдущему.
предотвратить шторм повторных попыток
Как безопасно повторить попытку и предотвратить шторм повторных попыток — самая большая проблема, с которой мы сталкиваемся.
Ограничение повторных попыток с одной точки
Во-первых, выполненных в одном температуре, сервис не может повторить попытку нижестоящего потока, вероятно, приведет к нижестоятельному потоку и висит. В дополнение к ограничиванию верхнего предела количества повторных попыток, установленных пользователем, но также важно ограничить скорость успеха запроса повторной попытки.
Реализовано очень простое решение, основанное на идее прерывателей цепи, оно ограничивает соотношение отказ/успешность запроса и добавляет функцию прерывателя цепи для повторной попытки. Для этого мы используем общий метод скользящего окна. Как показано на рисунке ниже, скользящее окно сохраняется в памяти для каждого типа вызова RPC. Например, окно разделено на 10 сегментов, и каждый сегмент записывает запрос RPC. данные результата в течение 1 с (успешно). ,Неудачно). Когда наступает новая секунда, создается новая корзина, и самая старая корзина удаляется, сохраняя только 10 секунд данных. Когда новый запрос для этого RPC терпит неудачу, определяется, может ли он быть повторен в зависимости от того, превышает ли пороговое значение неудача/успех в течение первых 10 секунд. Пороговое значение по умолчанию равно 0,1, то есть нисходящий поток может выдерживать до 1,1-кратного увеличения количества запросов в секунду, и пользователи могут настроить предохранитель и пороговое значение в соответствии со своими потребностями.
Ограничить повторы ссылок
Как упоминалось ранее, в многоуровневой ссылке, если каждый уровень сконфигурирован с повторными попытками, это может привести к экспоненциальному увеличению количества вызовов, хотя после того, как повторные попытки были сорваны, повторные попытки больше не являются экспоненциальным увеличением (количество повторных попыток расширение каждого отдельного узла ограничено в 1,1 раза), но количество вызовов все равно будет увеличиваться по мере увеличения количества ссылок, поэтому безопасность повторных попыток по-прежнему необходимо рассматривать на уровне ссылок.
Суть антиповторного шторма на канальном уровне заключается в ограничении повторных попыток на каждом уровне, в идеале только на нижнем уровне. Google SRE указывает, как Google использует специальные коды ошибок внутри:
- Оговаривается специальный код статуса, который означает: вызов не удался, но больше не пробуйте.
- После неудачной повторной попытки на одном уровне генерируется код состояния, который возвращается на верхний уровень.
- После того, как верхний уровень получает код состояния, он прекращает повторные попытки нисходящего потока и передает код ошибки своему верхнему уровню.
Таким образом, в идеале только нижний уровень будет повторять попытку, а его восходящий уровень не будет повторять попытку после получения кода ошибки.Общий коэффициент усиления канала равен r раз (количество повторных попыток для одного уровня). Однако эта стратегия полагается на то, что бизнес-сторона передает код ошибки, что имеет определенное вторжение в бизнес-код, и обычно код бизнес-стороны сильно отличается, и методы и сценарии вызова RPC также различаются. код ошибки, полученный от нисходящего потока, не передается восходящему потоку по таким причинам, как отсутствие модификации.
К счастью, протокол RPC, используемый внутри ByteDance, имеет поля расширения.Мы предприняли много попыток в промежуточном программном обеспечении, чтобы инкапсулировать логику обработки и передачи кода ошибки и передать идентификатор кода ошибки nomore_retry в поле расширения ответа RPC, что сообщает восходящий поток Не повторяйте попытку. Промежуточное программное обеспечение завершает управление всем жизненным циклом генерации, идентификации и передачи кодов ошибок и не требует от бизнес-стороны изменения собственной логики RPC.Решение кодов ошибок прозрачно для бизнеса.
В ссылке нажмите каждый уровень, чтобы подключиться к компоненту повторных попыток, чтобы каждый уровень мог остановить повторную попытку, идентифицируя этот бит флага, и передать его уровень за уровнем, а верхний уровень также останавливает повторную попытку, так что уровень ссылки может быть достигнута защита, для достижения эффекта «повторить попытку будет только уровень, ближайший к месту возникновения ошибки».
Обработка тайм-аута
При тестировании схемы загрузки кода ошибки мы обнаружили, что ситуация с тайм-аутом может привести к сбою схемы передачи кода ошибки.
Для сценария A -> B -> C, если предположить, что B -> C истекает время ожидания, а B повторяет попытку запроса C, очень вероятно, что A -> B также истекает время ожидания в это время, поэтому A не получает ошибку код, возвращенный B, но также будет повторена попытка B. В это время, хотя B повторяет попытку C и генерирует код ошибки повторной попытки, он больше не может быть передан A. В этом случае A по-прежнему будет повторять B, и если каждый уровень в ссылке истечет, все равно будет эффект экспоненциального расширения ссылки.
Следовательно, для того, чтобы справиться с этой ситуацией, в дополнение к нижестоятельному переносу метки тяжелой пробной ошибки, мы также достигли «запроса повторной попытки без повторений».
Для запроса на повторную попытку мы помещаем в Запрос специальный флаг повторной попытки.В ссылке A -> B -> C выше, когда B получает запрос от A, он сначала считывает этот флаг, чтобы определить, повторяется ли запрос или Если это так, он вызовет C без повторной попытки, даже если вызов завершится ошибкой, в противном случае он повторит попытку C, если вызов C завершится ошибкой. В то же время B также загрузит флаг повтора, и запрос, который он отправляет, также будет иметь этот флаг, и его нисходящий поток не будет повторять запрос.
Таким образом, даже если A не может получить возврат B из-за тайм-аута, после отправки запроса на повторную попытку B, B может воспринять это и не будет повторять попытку C, так что A запрашивает не более r раз, а B запрашивает не более r + r - 1. Если Если ниже уровень ниже, C запрашивает не более r + r + r - 2 раз, а i-й слой запрашивает не более i * r - (i-1) раз. В худшем случае случае это кратный рост, а не экспоненциальный рост. В дополнение к фактическому ограничению повторных попыток слияния, увеличение намного меньше.
Ограничьте увеличение одной точки, повторив попытку предохранителя, и убедитесь, что повторная попытка выполняется только на самом низком уровне, повторив попытку обратной связи с флагом ошибки, и обеспечьте повторную попытку, повторив запрос нисходящей линии связи с флагом. стратегии могут эффективно уменьшить эффект усиления повторных попыток.
Оптимизация сцены тайм-аута
В распределенной системе результат запроса RPC имеет три состояния: успех, сбой и тайм-аут.Сложнее всего обработать тайм-аут. Но тайм-ауты часто бывают наиболее частыми.Мы подсчитали распределение ошибок RPC для некоторых важных сервисов в бизнес-линии потокового вещания ByteDance и обнаружили, что наибольшая доля приходится на ошибки тайм-аута.
В сценарии повторной попытки по тайм-ауту, хотя добавление флага повторной попытки к запросу на повторную попытку может предотвратить экспоненциальное расширение, оно не может повысить процент успешных запросов. Как показано на рисунке ниже, если время ожидания A и B равно 1000 мс, когда нагрузка C очень высока, B истечет время ожидания при доступе к C, затем B повторит попытку C, но время превысило 1000 мс, и время A также истекло и здесь отключено.Соединение с B, поэтому B повторяет попытку C на этот раз бесполезно, независимо от того, успешно это или нет.С точки зрения A, этот запрос не удался.
Существенной причиной такой ситуации является то, что период тайм-аута на канале установлен необоснованно, периоды тайм-аута восходящего и нисходящего потоков установлены одинаковыми, и даже период тайм-аута восходящего потока меньше, чем период тайм-аута нисходящего потока. На практике бизнес обычно не настраивает период тайм-аута RPC, поэтому он может быть тайм-аутом по умолчанию для восходящего и нисходящего потоков, и продолжительность одинакова. Чтобы справиться с этой ситуацией, нам нужен механизм для оптимизации стабильности при тайм-ауте и сокращения бесполезных повторных попыток.
Как показано на рисунке ниже, обычный сценарий повторной попытки — это ожидание Resp1 (или получение результата тайм-аута) перед инициацией второго запроса.Общее время равно t1 + t2. Согласно нашему анализу, служба А может ждать после отправки Req1 долгое время, например, 1 с, но pct99 или pct999 этого запроса обычно могут быть только в пределах 100 мс.Если оно превышает 100 мс, существует высокая вероятность того, что доступ будет в итоге тайм-аут. , можно тупо не ждать, а попробовать еще раз заранее?
Основываясь на этой идее, мы внедрили и внедрили схему Backup Requests. Как показано на рисунке ниже, мы предварительно устанавливаем порог t3 (меньше, чем время ожидания, обычно pct99 для задержки запроса RPC), когда Req1 отправляется и не возвращается в течение времени t3, тогда мы напрямую инициируем повторный запрос Req2. , что вполне возможно, так как одновременно выполняются два запроса. Затем дождитесь возврата запроса. Пока Resp1 или Resp2 возвращает успешный результат, запрос может быть завершен немедленно, поэтому общее время равно t4, что указывает время от первого запроса до возврата первого успешного результата. Время, по сравнению с ожиданием тайм-аута перед выдачей запроса, этот механизм может значительно сократить общую задержку.
По сути, Backup Requests — это идея использования объема трафика для обмена вероятностью успеха (или низкой задержкой).Конечно, мы будем контролировать скорость увеличения его объема трафика.Перед инициацией повторной попытки первый запрос будет Зарегистрирован один сбой, и проверьте, превышает ли текущая частота сбоев пороговое значение предохранителя, чтобы общая скорость доступа оставалась под контролем.
Объединить DDL
Идея Backup Requests может уменьшить часть недействительных запросов при одновременном сокращении общей задержки запросов, но не все бизнес-сценарии подходят для настройки Backup Requests, поэтому мы комбинируем DDL для контроля недействительных повторных попыток.
DDL — это аббревиатура от "Deadline Request Call Chain Timeout". Мы знаем, что TTL в протоколе TCP/IP используется для оценки того, находится ли пакет данных в сети слишком долго и должен ли он быть отброшен. Подобно DDL, это представляет собой полную цепочку Тайм-аут вызова в стиле пути можно использовать для определения необходимости продолжения текущего запроса RPC. Как показано на рисунке ниже, основная команда ByteDance реализовала функцию DDL, и в цепочку вызовов запросов RPC будет добавлен период ожидания, а время обработки этого уровня будет вычитаться после каждого уровня, если оставшееся время меньше или равно 0 , то вам не нужно запрашивать нисходящий поток, просто возвращайте отказ напрямую.
Метод DDL может эффективно уменьшить недопустимые вызовы на ниже по течению. Мы также объединяем данные DDL в управлении повторением. Перед началом каждой повторении будет судить, будет судить о том, будет ли оставшееся значение DDL больше чем 0. Если условия Не встречаются, то нет необходимости повторяться вниз по течению, что может минимизировать бесполезные повторные попытки.
Фактический эффект усиления связи
Упомянутое ранее усиление ссылочного индекса является идеальным анализом, но реальная ситуация намного сложнее, потому что есть много влияющих факторов:
Стратегия | инструкция |
---|---|
Повторить удар | Остановить повторную попытку, если запрос не удался/успех > 0,1 |
флаг ошибки загрузки ссылки | Загрузите флаг ошибки после того, как нижний уровень не сможет повторить попытку, а верхний уровень не повторит попытку. |
Флаг повторной попытки нисходящей линии связи | Специальная отметка повторного запроса, нижний уровень не будет повторять повторный запрос. |
DDL | Не инициировать повторные запросы, когда оставшегося времени недостаточно |
рама взорвана | Такие механизмы, как слияние и защита от перегрузок самой микрослужбы, также будут влиять на эффект повторных попыток. |
Комбинируя различные факторы, конечную фактическую ситуацию с методом нельзя объяснить простой формулой расчета.Мы построили многоуровневую линию вызова, а также протестировали и записали использование управления повторными попытками при различных типах ошибок и разной частоте ошибок в Интернете. компонент, было обнаружено, что после подключения компонента управления повторными попытками увеличение количества повторных попыток можно эффективно контролировать на уровне канала, что значительно снижает вероятность системных лавин, вызванных повторными попытками.
Суммировать
Как упоминалось выше, на основе идеи управления услугами мы разработали функцию управления повторными попытками, которая поддерживает динамическую настройку.Метод доступа в основном не требует вторжения бизнес-кодов и использует комбинацию нескольких стратегий для управления эффект усиления повторной попытки на уровне ссылки с учетом простоты использования, гибкости и безопасности.Многие сервисы, в том числе прямые трансляции, были доступны и использованы в ByteDance и проверены онлайн, что хорошо влияет на повышение стабильности сервиса сам. В настоящее время решение проверено и продвигается в прямом эфире ByteDance и других компаниях, и в будущем оно будет обслуживать больше сервисов ByteDance.
Присоединяйтесь к нам
Мы являемся командой ByteDance для прямых трансляций среднего уровня, отвечающей за базовые исследования услуг и разработку бизнеса прямых трансляций различных приложений, таких как Douyin, Douyin Volcano, Xigua Video и Toutiao.Бизнес быстро развивается, и группа пользователей огромный. Если вы увлечены технологиями, вы можете присоединиться к команде прямых трансляций ByteDance и решать различные технические проблемы вместе с нами. В настоящее время у нас есть потребности в наборе персонала в Пекине, Шэньчжэне, Ханчжоу и других местах.Для внутренних направлений вы можете связаться с электронной почтой:tech@bytedance.com; Тема письма: Имя - Годы работы - Прямая трансляция - Платформа
Добро пожаловать в "Техническая команда ByteDance"
Контактный адрес электронной почты для доставки резюме "tech@bytedance.com"