Обработка временных сбоев
Все приложения, взаимодействующие с удаленными службами и ресурсами, должны быть чувствительны ко временным сбоям. Это особенно верно для приложений, работающих в облаке, где из-за природы среды и подключения через Интернет этот тип сбоя, скорее всего, встречается чаще. Временные ошибки включают временную потерю сетевого подключения к компонентам и службам, временную недоступность службы и время ожидания, возникающие при занятой службе. Эти ошибки часто самокорректируются, поэтому, если действие повторяется после подходящей задержки, скорее всего, будет выполнено успешно.
В этой статье приведены общие рекомендации по обработке временных сбоев. Сведения об обработке временных сбоев при использовании служб Azure см . в руководстве по повторным попыткам для служб Azure.
Почему временные сбои возникают в облаке?
Временные сбои могут возникать в любой среде, на любой платформе, в любой операционной системе и в приложении любого типа. Для решений, работающих в локальной локальной инфраструктуре, производительность и доступность приложения и его компонентов обычно поддерживаются с помощью дорогой и часто недостаточной избыточности оборудования, а компоненты и ресурсы находятся близко друг к другу. Этот подход снижает вероятность сбоя, но временные ошибки по-прежнему могут возникать, так как могут возникать сбои, вызванные непредвиденными событиями, такими как внешний источник питания или сетевые проблемы, или другие сценарии аварии.
Размещение в облаке, включая системы на базе частного облака, обеспечивает повышенную общую доступность благодаря использованию общих ресурсов, резервированию, автоматической отработке отказа и динамическому распределению ресурсов между множеством стандартных вычислительных узлов. Однако из-за характера облачных сред временные ошибки чаще возникают. Для этого существует несколько причин.
Многие ресурсы в облачной среде совместно используются, и доступ к этим ресурсам подлежит регулированию для защиты ресурсов. Некоторые службы отказываются от подключений при повышении нагрузки до определенного уровня или при достижении максимальной скорости пропускной способности, чтобы разрешить обработку существующих запросов и обеспечить производительность службы для всех пользователей. Регулирование помогает поддерживать качество обслуживания для соседей и других клиентов, использующих общий ресурс.
Облачные среды используют большое количество сырьевых аппаратных единиц. Они обеспечивают производительность путем динамического распределения нагрузки между несколькими вычислительными единицами и компонентами инфраструктуры. Они обеспечивают надежность путем автоматической переработки или замены неудачных единиц. Из-за этой динамической природы временные ошибки и временные сбои подключения могут иногда возникать.
Часто существуют более аппаратные компоненты, включая сетевую инфраструктуру, например маршрутизаторы и подсистемы балансировки нагрузки, между приложением и ресурсами и службами, которые он использует. Эта дополнительная инфраструктура иногда может стать причиной дополнительной задержки подключения и временных сбоев соединения.
Сетевые условия между клиентом и сервером могут быть переменными, особенно при обмене данными через Интернет. Даже в локальных расположениях тяжелые нагрузки трафика могут замедлить обмен данными и вызвать периодические сбои подключения.
Сложности
Временные ошибки могут оказать большое влияние на предполагаемую доступность приложения, даже если это было тщательно проверено во всех обозримых обстоятельствах. Чтобы обеспечить надежную работу облачных приложений, необходимо убедиться, что они могут реагировать на следующие проблемы:
Приложение должно иметь возможность обнаруживать ошибки при их возникновении и определять, могут ли ошибки быть временными, долгосрочными или являются ли сбои терминала. Различные ресурсы, скорее всего, возвращают различные ответы при возникновении сбоя, и эти ответы также могут отличаться в зависимости от контекста операции. Например, ответ на ошибку при чтении приложения из хранилища может отличаться от ответа на ошибку при записи в хранилище. Многие ресурсы и службы имеют хорошо документированные контракты временных сбоев. Тем не менее, если такая информация недоступна, может быть трудно обнаружить характер ошибки и быть ли это, скорее всего, временным.
Приложение должно иметь возможность повторить операцию, если она определяет, что ошибка, скорее всего, будет временной. Кроме того, необходимо отслеживать количество повторных попыток операции.
Приложение должно использовать соответствующую стратегию для повторных попыток. Стратегия указывает количество повторных попыток приложения, задержки между каждой попыткой и действиями, выполняемыми после неудачной попытки. Необходимое количество попыток и задержка между каждым из них часто трудно определить. Стратегия будет отличаться в зависимости от типа ресурса и от текущих условий работы ресурса и приложения.
Общие рекомендации
Следующие рекомендации помогут вам разработать подходящие временные механизмы обработки ошибок для приложений.
Определение наличия встроенного механизма повторных попыток
Многие службы предоставляют пакет SDK или клиентскую библиотеку с механизмом обработки временных сбоев. Политика повторов, как правило, специально подгоняется под характер и требования целевой службы. Кроме того, интерфейсы REST для служб могут возвращать сведения, которые помогут определить, подходит ли повторная попытка и как долго ждать до следующей попытки повтора.
Вы должны использовать встроенный механизм повторных попыток, если он доступен, если у вас нет конкретных и хорошо понятных требований, которые делают другое поведение повторных попыток более подходящим.
Определение того, подходит ли операция для повторных попыток
Выполняйте операции повторных попыток только в том случае, если ошибки являются временными (как правило, обозначаемыми характером ошибки) и когда есть по крайней мере некоторая вероятность успешного выполнения операции при повторном выполнении. Нет смысла повторять операции, которые пытаются выполнить недопустимую операцию, например обновление базы данных на элемент, который не существует, или запрос к службе или ресурсу, который получил неустранимая ошибка.
Как правило, реализуйте повторные попытки только в том случае, если вы можете определить полный эффект этого и когда условия хорошо понятны и могут быть проверены. В противном случае пусть вызывающий код реализует повторные попытки. Помните, что ошибки, возвращенные из ресурсов и служб за пределами вашего управления, могут развиваться с течением времени, и вам может потребоваться вернуться к логике временного обнаружения ошибок.
При создании служб или компонентов рекомендуется реализовать коды ошибок и сообщения, которые помогают клиентам определить, должны ли они повторить неудачные операции. В частности, укажите, должен ли клиент повторить операцию (возможно, возвращая значение isTransient ) и предложить подходящую задержку перед следующей попыткой повтора. Если вы создаете веб-службу, рассмотрите возможность возврата пользовательских ошибок, определенных в контрактах служб. Несмотря на то, что универсальные клиенты могут не читать эти ошибки, они полезны при создании пользовательских клиентов.
Определение соответствующего количества повторных попыток и интервала
Оптимизируйте число повторных попыток и интервал для типа варианта использования. Если вы не повторяете достаточно времени, приложение не может завершить операцию и, вероятно, завершится ошибкой. Если повторяться слишком много раз или слишком коротким интервалом между попытками, приложение может хранить такие ресурсы, как потоки, подключения и память в течение длительных периодов, что негативно влияет на работоспособность приложения.
Адаптируйте значения для интервала времени и количества попыток повторных попыток к типу операции. Например, если операция является частью взаимодействия с пользователем, интервал должен быть коротким и предпринять попытку только нескольких повторных попыток. Используя этот подход, вы можете избежать того, чтобы пользователи ждали ответа, который содержит открытые подключения и может снизить доступность для других пользователей. Если операция является частью длительного или критического рабочего процесса, где отмена и перезапуск процесса является дорогостоящим или временным, это позволяет ожидать больше времени между попытками и повторными попытками.
Помните, что определение соответствующих интервалов между повторными попытками является наиболее сложной частью разработки успешной стратегии. В типичных стратегиях применяются следующие типы интервала между повторными попытками.
Экспоненциальная задержка. Приложение ожидает некоторое время до первого повтора, а затем экспоненциально увеличивает время между каждой последующей повторным попыткой. Например, он может повторить операцию через 3 секунды, 12 секунд, 30 секунд и т. д.
Интервалы с приращениями. Приложение ожидает некоторое время до первого повтора, а затем добавочно увеличивает время между каждой последующей повторным попыткой. Например, она может повторить операцию через 3 секунды, 7 секунд, 13 секунд и т. д.
Постоянные интервалы. Для всех повторных попыток применяется одинаковый интервал. Например, она может повторить операцию каждые 3 секунды.
Немедленный повтор. Иногда временный сбой является кратким, возможно, вызван событием, например столкновением сетевого пакета или пиком аппаратного компонента. В этом случае повторная попытка сразу же подходит, так как она может завершиться успешно, если ошибка очищается в течение времени, когда приложение собирается и отправляет следующий запрос. Однако никогда не должно быть более одной немедленной попытки повторных попыток. Вы должны переключиться на альтернативные стратегии, такие как экспоненциальные обратные или резервные действия, если немедленная повторная попытка завершается сбоем.
Случайный выбор. Любая из стратегий повторных попыток, перечисленных ранее, может включать случайность, чтобы предотвратить несколько экземпляров клиента, отправляя последующие попытки повторных попыток одновременно. Например, один экземпляр может повторить операцию через 3 секунды, 11 секунд, 28 секунд и т. д., а другой экземпляр может повторить операцию через 4 секунды, 12 секунд, 26 секунд и т. д. Случайное использование — это полезный метод, который можно объединить с другими стратегиями.
В качестве общего руководства используйте экспоненциальную стратегию резервного копирования для фоновых операций и используйте стратегии повтора немедленного или регулярного интервала для интерактивных операций. В обоих случаях необходимо выбрать задержку и число повторных попыток таким образом, чтобы максимальная задержка для всех повторных попыток находилась в пределах требуемой общей задержки.
Учитывайте сочетание всех факторов, которые способствуют общему максимальному времени ожидания для повторной операции. К этим факторам относятся время, необходимое для неудачного подключения к получению ответа (обычно заданное значением времени ожидания в клиенте), задержка между попытками повторных попыток и максимальное количество повторных попыток. Общее время выполнения может привести к длительному общему времени операции, особенно при использовании экспоненциальной стратегии задержки, в которой интервал между повторными попытками быстро увеличивается после каждого сбоя. Если процесс должен соответствовать определенному соглашению об уровне обслуживания (SLA), общее время операции, включая все тайм-ауты и задержки, должно быть в пределах ограничений, определенных в соглашении об уровне обслуживания.
Не реализуйте чрезмерно агрессивные стратегии повторных попыток. Это стратегии, которые имеют слишком короткие интервалы или повторные попытки, которые слишком часты. Они могут негативно повлиять на целевой ресурс или службу. Эти стратегии могут предотвратить восстановление ресурса или службы из перегруженного состояния, и он будет продолжать блокировать или отклонять запросы. Этот сценарий приводит к порочному кругу, где все больше запросов отправляются в ресурс или службу. Следовательно, его способность к восстановлению еще больше сокращается.
Учитывайте время ожидания операций при выборе интервалов повторных попыток, чтобы избежать немедленного запуска последующей попытки (например, если период времени ожидания аналогичен интервалу повтора). Кроме того, следует ли сохранить общий возможный период (время ожидания и интервалы повторных попыток) ниже определенного общего времени. Если операция имеет необычно короткое или длительное время ожидания, время ожидания может повлиять на время ожидания и частоту повторных попыток операции.
Используйте тип исключения и все содержащиеся в ней данные или коды ошибок и сообщения, возвращаемые службой, для оптимизации количества повторных попыток и интервала между ними. Например, некоторые исключения или коды ошибок (например, HTTP-код 503, служба недоступна, с заголовком Retry-After в ответе) могут указывать, сколько времени может длиться ошибка, или что служба завершилась ошибкой и не будет отвечать на любую последующую попытку.
Избегайте антипаттернов
В большинстве случаев избегайте реализаций, включающих повторяющиеся слои кода повторных попыток. Избегайте проектов, которые включают каскадные механизмы повторных попыток или реализующие повторную попытку на каждом этапе операции, которая включает иерархию запросов, если у вас нет конкретных требований, требующих этого. В этих исключительных случаях используйте политики, предотвращающие чрезмерное количество повторных попыток и периодов задержки, и убедитесь, что вы хорошо осознаете последствия. Например, предположим, что один компонент отправляет запрос другому, который затем обращается к целевой службе. Если вы реализуете повторные попытки с числом трех на обоих вызовах, в общей сложности для службы выполняется девять повторных попыток. Многие службы и ресурсы реализуют встроенный механизм повтора. Вы должны изучить, как отключить или изменить эти механизмы, если необходимо реализовать повторные попытки на более высоком уровне.
Никогда не применяйте механизм с бесконечными повторными попытками. Это, скорее всего, не позволит ресурсу или службе восстановиться из перегруженных ситуаций и вызвать регулирование и отклонить подключения в течение длительного времени. Используйте ограниченное число повторных попыток или реализуйте шаблон, например средство автоматического останова, чтобы разрешить службе восстановиться.
Никогда не выполняйте немедленный повтор больше одного раза.
Избегайте использования регулярного интервала повторных попыток при доступе к службам и ресурсам в Azure, особенно при наличии большого количества попыток повторных попыток. Лучший подход в этом сценарии — это экспоненциальная стратегия обратного выключения с возможностью взлома цепи.
Запретить несколько экземпляров одного клиента или нескольких экземпляров разных клиентов одновременно отправлять повторные попытки. Если этот сценарий, скорее всего, произойдет, введите случайность в интервалы повторных попыток.
Тестирование стратегии повторных попыток и реализации
Полностью протестируйте стратегию повторных попыток в максимально широком наборе обстоятельств, особенно если приложение и целевые ресурсы или службы, которые он использует, находятся под крайней нагрузкой. Чтобы проверить поведение во время тестирования, можно сделать следующее.
Внесите в службу временные и не временные ошибки. Например, отправьте недопустимые запросы или добавьте код, который обнаруживает тестовые запросы и дает отклик с различными типами ошибок. Примеры, использующие TestApi, см. в разделе "Тестирование внедрения ошибок" с помощью TestApi и введение в TestApi — часть 5. API внедрения управляемого кода.
Создайте макет ресурса или службы, возвращающего диапазон ошибок, возвращаемых реальной службой. Охватывайте все типы ошибок, которые стратегия повторных попыток предназначена для обнаружения.
Для пользовательских служб, создаваемых и развертываемых, принудительно возникают временные ошибки путем временной отключения или перегрузки службы. (Не пытайтесь перегружать общие ресурсы или общие службы в Azure.)
Для API на основе HTTP рекомендуется использовать библиотеку в автоматических тестах, чтобы изменить результат HTTP-запросов, добавив дополнительное время округления или изменив ответ (например, код состояния HTTP, заголовки, текст или другие факторы). Это позволяет детерминированное тестирование подмножества условий сбоя для временных сбоев и других типов сбоев.
Выполняйте высокие коэффициенты нагрузки и параллельные тесты, чтобы обеспечить правильную работу механизма повтора и стратегии в этих условиях. Эти тесты также помогут убедиться, что повторные попытки не оказывают негативного влияния на работу клиента или вызывают перекрестное загрязнение между запросами.
Управление конфигурациями политики повторных попыток
Политика повторных попыток — это сочетание всех элементов стратегии повторных попыток. Он определяет механизм обнаружения, определяющий, является ли ошибка временным, типом интервала для использования (например, регулярным, экспоненциальным обратным отключением и случайной), фактическими значениями интервалов и числом повторных попыток.
Реализуйте повторные попытки во многих местах, даже в самом простом приложении и в каждом слое более сложных приложений. Вместо жесткого написания элементов каждой политики в нескольких расположениях рекомендуется использовать центральную точку для хранения всех политик. Например, сохраните такие значения, как интервал и количество повторных попыток в файлах конфигурации приложения, считывает их во время выполнения и программно создает политики повторных попыток. Это упрощает управление параметрами и изменение и настройку значений для реагирования на изменение требований и сценариев. Однако создайте систему для хранения значений, а не повторного чтения файла конфигурации каждый раз и используйте подходящие значения по умолчанию, если значения не могут быть получены из конфигурации.
В приложении Azure Облачные службы рекомендуется хранить значения, используемые для создания политик повторных попыток во время выполнения в файле конфигурации службы, чтобы изменить их без необходимости перезапускать приложение.
Используйте встроенные или стандартные стратегии повторных попыток, доступные в клиентских API, которые вы используете, но только если они подходят для вашего сценария. Обычно эти стратегии являются универсальными. В некоторых сценариях они могут быть все, что вам нужно, но в других сценариях они не предлагают полный спектр вариантов в соответствии с вашими конкретными требованиями. Чтобы определить наиболее подходящие значения, необходимо выполнить тестирование, чтобы понять, как параметры влияют на приложение.
Журнал и отслеживание временных и ненаправных ошибок
В рамках стратегии повторных попыток включите обработку исключений и другие инструментирования, которые регистрируют повторные попытки. Случайные временные сбои и повторные попытки ожидаются и не указывают на проблему. Однако регулярные и растущие числа повторных попыток часто являются индикатором проблемы, которая может привести к сбою или снижению производительности и доступности приложений.
Журнал временных ошибок в виде записей предупреждений, а не как записей ошибок, чтобы системы мониторинга не обнаруживали их как ошибки приложения, которые могут активировать ложные оповещения.
Рассмотрите возможность сохранения значения в записях журнала, которые указывают на то, вызваны ли повторные попытки регулированием в службе или другими типами сбоев, таких как сбои подключения, чтобы их можно было отличить во время анализа данных. Увеличение числа ошибок регулирования часто указывает на ошибку проектирования приложения или на необходимость перехода на платную службу, предоставляющую выделенное оборудование.
Рассмотрите возможность измерения и ведения журнала общего времени ожидания операций, которые включают механизм повторных попыток. Эта метрика является хорошим показателем общего эффекта временных сбоев во время отклика пользователя, задержке процесса и эффективности вариантов использования приложения. Также зайдите в журнал количество повторных попыток, которые происходят, чтобы понять факторы, которые способствуют времени отклика.
Рассмотрите возможность реализации системы телеметрии и мониторинга, которая может вызывать оповещения, когда количество и скорость сбоев, среднее количество повторных попыток или общее время, истекшее до успешного выполнения операций.
Управление операциями, которые постоянно завершаются сбоем
Рассмотрим способ обработки операций, которые продолжают завершать сбой при каждой попытке. Такие ситуации неизбежны.
Хотя стратегия повторных попыток определяет максимальное число попыток, которое должна быть выполнена операция, она не препятствует повторному повтору операции с тем же числом повторных попыток. Например, если служба обработки заказов завершается сбоем со неустранимой ошибкой, которая окончательно выходит из действия, стратегия повторных попыток может обнаружить время ожидания подключения и считать это временным сбоем. Код повторяет операцию с заданным числом раз, а затем откажется. Однако, когда другой клиент помещает заказ, операция выполняется снова, даже если она будет завершатся ошибкой каждый раз.
Чтобы предотвратить постоянные повторные попытки для операций, которые постоянно завершаются сбоем, следует рассмотреть возможность реализации шаблона разбиения цепи. Если этот шаблон используется, если количество сбоев в течение указанного периода времени превышает пороговое значение, запросы возвращаются вызывающему объекту немедленно в виде ошибок, и нет попытки получить доступ к ресурсу или службе сбоем.
Приложение может периодически тестировать службу с очень длинными интервалами между запросами, чтобы определить, когда она станет доступной. Соответствующий интервал зависит от таких факторов, как критичность операции и характер службы. Это может быть что-нибудь от нескольких минут до нескольких часов. После успешного выполнения теста приложение может возобновить обычные операции и передать запросы в только что восстановленную службу.
В то же время вы можете вернуться к другому экземпляру службы (возможно, в другом центре обработки данных или приложении), использовать аналогичную службу, которая предлагает совместимые функции (возможно, проще) или выполнить некоторые альтернативные операции на основе надежды, что служба будет доступна в ближайшее время. Например, может потребоваться сохранить запросы для службы в очереди или хранилище данных и повторить их позже. Или вы можете перенаправить пользователя на альтернативный экземпляр приложения, снизить производительность приложения, но по-прежнему предложить приемлемые функциональные возможности или просто вернуть пользователю сообщение, чтобы указать, что приложение в настоящее время недоступно.
Другие вопросы
При выборе значений количества повторных попыток и интервалов повторных попыток для политики следует учитывать, является ли операция в службе или ресурсе частью длительной или многоэтапной операции. Это может быть трудно или дорого компенсировать все остальные операционные шаги, которые уже завершились успешно, когда один завершается сбоем. В этом случае очень длинный интервал и большое количество повторных попыток может быть приемлемым, если эта стратегия не блокирует другие операции путем хранения или блокировки дефицитных ресурсов.
Рассмотрите, может ли повторная попытка одной и той же операции вызвать несоответствия в данных. Если некоторые части многоэтапного процесса повторяются, а операции не являются идемпотентными, могут возникнуть несоответствия. Например, если операция, которая увеличивает значение, повторяется, он создает недопустимый результат. Повторение операции, отправляющей сообщение в очередь, может привести к несоответствию в потребителе сообщения, если потребитель не может обнаружить повторяющиеся сообщения. Чтобы предотвратить эти сценарии, создайте каждый шаг как идемпотентную операцию. Дополнительные сведения см. в шаблонах Idempotency.
Рассмотрим область операций, которые выполняются повторно. Например, можно упростить реализацию кода повторных попыток на уровне, охватывающего несколько операций, и повторить их все при сбое. Однако это может привести к проблемам идемпотентности или ненужным операциям отката.
Если вы выберете область повторных попыток, которая охватывает несколько операций, учитывайте общую задержку всех из них при определении интервалов повторных попыток, при мониторинге истекшего времени операции и перед созданием оповещений о сбоях.
Рассмотрим, как стратегия повторных попыток может повлиять на соседей и других клиентов в общем приложении, а также при использовании общих ресурсов и служб. Агрессивные политики повторных попыток могут привести к увеличению числа временных сбоев для других пользователей и приложений, совместно использующих ресурсы и службы. Аналогичным образом, ваше приложение может повлиять на политики повторных попыток, реализованные другими пользователями ресурсов и служб. Для критически важных для бизнеса приложений может потребоваться использовать службы класса Premium, которые не являются общими. Это обеспечивает более контроль над нагрузкой и последующим регулированием этих ресурсов и служб, что может помочь оправдать дополнительные затраты.