Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Когда служба становится недоступной или занятой, частые повторные попытки клиента могут предотвратить восстановление и ухудшение проблемы. Повторные попытки на неопределенный срок неэффективны, так как запросы обычно остаются действительными только в течение ограниченного времени.
Контекст и проблема
В облаке службы иногда сталкиваются с проблемами и становятся недоступными для клиентов или применяют ограничения регулирования или скорости. Хотя хорошей практикой для клиентов будет повторять неудавшиеся подключения к службам, не стоит делать это слишком часто или продолжительное время. Повторные попытки в течение короткого периода времени вряд ли будут успешными, так как служба, скорее всего, не восстановлена. Чрезмерные попытки подключения во время восстановления могут перегрузить службу и усилить исходную проблему. Эта ситуация иногда называется эффектом грохочущего стада.
В следующем примере показан сценарий, в котором клиент подключается к серверному API. Если запрос не удается, клиент немедленно повторяет попытку и продолжает пытаться бесконечно. Этот тип поведения часто более тонкий, чем в этом примере, но тот же принцип применяется.
public async Task<string> GetDataFromServer()
{
while(true)
{
var result = await httpClient.GetAsync(string.Format("http://{0}:8080/api/...", hostName));
if (result.IsSuccessStatusCode) break;
}
// ... Process result.
}
Решение
Клиентские приложения должны следовать рекомендациям, чтобы предотвратить повторные штормы.
Ограничение количества попыток повтора и длительности.
while(true)Написание цикла может показаться простым, но обычно вы не хотите повторяться в течение длительного периода времени. Условия, которые привели к тому, что запрос был инициирован, вероятно, изменились. Большинству приложений требуется повторить попытку в течение нескольких секунд или минут.Приостановка между повторными попытками и увеличение времени ожидания. Если служба недоступна, повторная попытка немедленно вряд ли будет успешна. Постепенно увеличивайте время между попытками, например с помощью экспоненциальной стратегии отката.
Обрабатывайте ошибки сервиса аккуратно. Если служба не отвечает, определите, следует ли отменить попытку и вернуть ошибку пользователю или вызывающему компоненту. При разработке приложения учитывайте эти сценарии сбоев.
Используйте шаблон разбиения цепи. Этот шаблон разработан специально для предотвращения повторных штормов.
Соблюдать заголовки ответа. Если сервер предоставляет
retry-afterзаголовок ответа, не пытайтесь повторить попытку до истечения указанного периода времени.Используйте официальные пакеты SDK для взаимодействия со службами Azure. Эти пакеты SDK обычно имеют встроенные политики повторных запросов и защиту от создания или участия в нагрузках на систему из-за многократных повторов. Если вы взаимодействуете со службой, которая не имеет пакета SDK или этот пакет неправильно обрабатывает логику повторных попыток, рассмотрите возможность использования библиотеки, например Polly для .NET или Retry для JavaScript, чтобы правильно реализовать логику повторных попыток и избежать написания кода самостоятельно.
Используйте слой абстракции при наличии. Если вы используете среду, поддерживающую ее, используйте сетку службы или другой слой абстракции для отправки исходящих вызовов. Как правило, эти средства, такие как Dapr, поддерживают политики повторных попыток и автоматически следуют передовой практике, например, уменьшая частоту попыток после нескольких неудачных попыток. Такой подход устраняет необходимость самостоятельной записи кода повторных попыток.
При наличии следует учитывать пакетные запросы и использовать пул запросов. Многие пакеты SDK обрабатывают пакетную обработку запросов и пул подключений от вашего имени, что сокращает общее количество попыток исходящего подключения, которое делает ваше приложение. Избегайте слишком частых повторных попыток подключения.
Службы также должны защитить себя от повторных штормов.
Добавьте уровень шлюза для блокировки подключений во время инцидентов. Этот подход соответствует шаблону bulkhead. Azure предоставляет множество служб шлюза для различных типов решений, включая Azure Front Door, Azure Application Gateway и Azure API Management.
Ограничение запросов на шлюзе. Такой подход предотвращает перегрузку внутренних компонентов чрезмерными запросами.
Отправка сигналов клиентам. При ограничении отправьте заголовок
retry-after, чтобы помочь клиентам понять, когда пытаться повторно подключиться. Клиенты не обязаны учитывать эти заголовки, но многие это делают.
Соображения
Общие сведения о типах ошибок. Некоторые типы ошибок не указывают на сбой службы, а вместо этого указывают на недопустимый запрос от клиента. Например, если клиентское приложение получает
400 Bad Requestответ об ошибке, повторите тот же запрос, скорее всего, не поможет, так как сервер уже уведомил вас о том, что ваш запрос недействителен.Определите соответствующую длительность повторных попыток. Клиенты должны учитывать наиболее подходящее время для повторной попытки подключения. Период времени должен соответствовать бизнес-требованиям, а также обеспечивать возможность разумно возвращать ошибку пользователю или вызывающему абоненту. Большинству приложений требуется повторить попытку в течение нескольких секунд или минут.
Обнаружение проблемы
С точки зрения клиента, симптомы этой проблемы могут включать очень длинное время отклика или обработку и телеметрию, которая указывает на повторяющиеся попытки повторить подключение.
С точки зрения службы симптомы этой проблемы могут включать несколько запросов от одного клиента в течение короткого периода времени или нескольких запросов от одного клиента при восстановлении от сбоев. Служба также может испытывать трудности с восстановлением после сбоя. Или у сервиса могут возникнуть каскадные сбои сразу после устранения неисправности.
Пример диагностики
Следующие разделы демонстрируют подход к обнаружению потенциального шторма повторных запросов с точки зрения как клиента, так и сервиса.
Определение шаблонов с помощью телеметрии клиента
Application Insights записывает данные телеметрии из приложений и делает эти данные доступными для запроса и визуализации. Он отслеживает исходящие подключения в виде зависимостей и позволяет пользователям получать доступ к этой информации и определять, когда клиент выполняет несколько исходящих запросов к одной службе.
На следующем снимке экрана показан график на вкладке "Метрики" на портале Application Insights. В нем показана метрика отказов зависимостей, разделенная по имени удаленной зависимости. Этот сценарий имеет более 21 000 неудачных попыток подключения к зависимости в течение короткого времени.
Определение шаблонов с помощью телеметрии сервера
Серверные приложения могут обнаруживать большое количество подключений из одного клиента. В следующем примере Azure Front Door выступает в качестве шлюза для приложения и настроен для записи всех запросов в рабочую область Log Analytics.
Чтобы определить IP-адреса клиента, которые отправляют большое количество запросов в приложение в течение последнего дня, выполните следующий запрос Kusto в Log Analytics.
AzureDiagnostics
| where ResourceType == "FRONTDOORS" and Category == "FrontdoorAccessLog"
| where TimeGenerated > ago(1d)
| summarize count() by bin(TimeGenerated, 1h), clientIp_s
| order by count_ desc
При выполнении этого запроса во время вспышки повторных попыток отображается большое количество попыток подключения с одного IP-адреса.