Многие службы используют шаблон регулирования для управления используемыми ресурсами, что накладывает ограничения на скорость доступа к другим приложениям или службам. Вы можете использовать шаблон ограничения скорости для предотвращения или минимизации ошибок регулирования, связанных с этими ограничениями регулирования, и для более точного прогнозирования пропускной способности.
Шаблон ограничения скорости подходит во многих сценариях, но особенно полезно для крупномасштабных повторяющихся автоматических задач, таких как пакетная обработка.
Контекст и проблема
Выполнение большого количества операций с помощью регулирования службы может привести к увеличению трафика и пропускной способности, так как вам потребуется отслеживать отклоненные запросы, а затем повторить эти операции. По мере увеличения количества операций ограничение регулирования может потребовать нескольких проходов повторной отправки данных, что приводит к увеличению влияния на производительность.
В качестве примера рассмотрим следующее наивное повторение в процессе ошибки для приема данных в Azure Cosmos DB:
- Приложение должно принять 10 000 записей в Azure Cosmos DB. Каждая запись стоит 10 единиц запросов (ЕЗ) для приема, требуя от общей сложности 100 000 единиц запросов для завершения задания.
- У экземпляра Azure Cosmos DB есть 20 000 подготовленных ресурсов.
- Вы отправляете все 10 000 записей в Azure Cosmos DB. 2000 записей записей записываются успешно, и 8000 записей отклоняются.
- Вы отправляете оставшиеся 8000 записей в Azure Cosmos DB. 2000 записей успешно написаны, и 6000 записей отклоняются.
- Вы отправляете оставшиеся 6000 записей в Azure Cosmos DB. 2000 записей успешно написаны, и 4000 записей отклоняются.
- Вы отправляете оставшиеся 4000 записей в Azure Cosmos DB. 2000 записей успешно написаны, и 2000 записей отклоняются.
- Вы отправляете оставшиеся 2000 записей в Azure Cosmos DB. Все записи записываются успешно.
Задание приема выполнено успешно, но только после отправки 30 000 записей в Azure Cosmos DB, даже если весь набор данных состоит только из 10 000 записей.
Существуют дополнительные факторы, которые следует учитывать в приведенном выше примере:
- Большое количество ошибок также может привести к дополнительной работе по журналу этих ошибок и обработке результирующих данных журнала. Этот наивный подход будет обрабатывать 20 000 ошибок, и ведение журнала этих ошибок может привести к обработке, памяти или стоимости ресурсов хранилища.
- Не зная ограничений регулирования службы приема данных, наивный подход не может задать ожидания в течение длительного времени обработки данных. Ограничение скорости позволяет вычислить время, необходимое для приема.
Решение
Ограничение скорости может уменьшить трафик и потенциально повысить пропускную способность, уменьшая количество записей, отправляемых в службу в течение определенного периода времени.
Служба может регулироваться на основе различных метрик со временем, например:
- Количество операций (например, 20 запросов в секунду).
- Объем данных (например, 2 ГиБ в минуту).
- Относительная стоимость операций (например, 20 000 единиц запросов в секунду).
Независимо от метрики, используемой для регулирования, реализация ограничения скорости будет включать управление числом и(или) размером операций, отправленных службе в течение определенного периода времени, оптимизируя использование службы, не превышающих ее емкость регулирования.
В сценариях, когда API-интерфейсы могут обрабатывать запросы быстрее, чем любые регулируемые службы приема, вам потребуется управлять тем, как быстро можно использовать службу. Однако только обработка регулирования как проблемы с несоответствием скорости данных и просто буферизация запросов приема до тех пор, пока регулирование не сможет догнать службу, рискует. Если приложение завершает работу в этом сценарии, вы рискуете потерять любую из этих буферных данных.
Чтобы избежать этого риска, рассмотрите возможность отправки записей в систему устойчивого обмена сообщениями, которая может обрабатывать полную частоту приема. (Такие службы, как Центры событий Azure могут обрабатывать миллионы операций в секунду). Затем можно использовать один или несколько процессоров заданий для чтения записей из системы обмена сообщениями с контролируемой скоростью, которая находится в пределах ограничений управляемой службы. Отправка записей в систему обмена сообщениями может сохранять внутреннюю память, позволяя отменять только записи, которые можно обрабатывать в течение заданного интервала времени.
Azure предоставляет несколько устойчивых служб обмена сообщениями, которые можно использовать с этим шаблоном, в том числе:
При отправке записей период времени, используемый для выпуска записей, может быть более детализирован, чем период регулирования службы. Системы часто задают регулирование на основе интервалов времени, с которыми можно легко понять и работать. Однако для компьютера под управлением службы эти временные интервалы могут быть очень длинными по сравнению с тем, насколько быстро он может обрабатывать информацию. Например, система может регулироваться в секунду или в минуту, но обычно код обрабатывается по порядку наносекунд или миллисекунд.
Хотя это не обязательно, часто рекомендуется отправлять меньшие объемы записей чаще для повышения пропускной способности. Таким образом, вместо того, чтобы пытаться пакетировать вещи для выпуска один раз в секунду или один раз в минуту, вы можете быть более детализировано, чем для поддержания потребления ресурсов (память, ЦП, сети и т. д.), выполняющихся более равномерно, предотвращая потенциальные узкие места из-за внезапных всплесков запросов. Например, если служба разрешает 100 операций в секунду, реализация ограничения скорости может даже выпустить запросы путем выпуска 20 операций каждые 200 миллисекунд, как показано на следующем графике.
Кроме того, иногда это необходимо для нескольких несогласованных процессов для совместного использования регулируемых служб. Для реализации ограничения скорости в этом сценарии можно логически секционировать емкость службы, а затем использовать распределенную систему взаимного исключения для управления монопольными блокировками этих секций. Затем несогласованные процессы могут конкурировать за блокировки для этих секций всякий раз, когда они нуждаются в емкости. Для каждой секции, для которой хранится блокировка, она предоставляет определенное количество емкости.
Например, если регулирование системы разрешает 500 запросов в секунду, можно создать 20 секций, которые стоят 25 запросов в секунду. Если процесс требуется для выдачи 100 запросов, он может попросить распределенную систему взаимного исключения для четырех разделов. Система может предоставить две секции в течение 10 секунд. Затем процесс будет ограничивать скорость до 50 запросов в секунду, завершить задачу в два секунды, а затем освободить блокировку.
Один из способов реализации этого шаблона — использовать служба хранилища Azure. В этом сценарии создается один 0-байтовый большой двоичный объект на логическую секцию в контейнере. Затем приложения могут получать эксклюзивные аренды непосредственно против этих БОЛЬШИХ двоичных объектов в течение короткого периода времени (например, 15 секунд). Для каждой аренды предоставляется приложение, оно сможет использовать емкость этого раздела. Затем приложение должно отслеживать время аренды, чтобы, когда срок действия истек, он может прекратить использование емкости, которую он предоставил. При реализации этого шаблона часто требуется, чтобы каждый процесс пытался арендовать случайный раздел, когда он нуждается в емкости.
Чтобы уменьшить задержку, можно выделить небольшое количество монопольной емкости для каждого процесса. Затем процесс будет стремиться получить аренду на общую емкость, если она должна превышать зарезервированную емкость.
В качестве альтернативы служба хранилища Azure вы также можете реализовать эту систему управления арендой с помощью таких технологий, как Zookeeper, Consul, etcd, Redis/Redsync и другие.
Проблемы и рекомендации
При выборе способа реализации этого шаблона следует учитывать следующее:
- Хотя шаблон ограничения скорости может уменьшить количество ошибок регулирования, приложению по-прежнему потребуется правильно обрабатывать любые ошибки регулирования, которые могут возникнуть.
- Если в приложении есть несколько рабочих потоков, которые обращаются к одной и той же регулированию службы, вам потребуется интегрировать все эти потоки в стратегию ограничения скорости. Например, вы можете поддерживать массовую загрузку записей в базу данных, а также запрашивать записи в той же базе данных. Вы можете управлять емкостью, гарантируя, что все рабочие потоки закиваются с помощью одного механизма ограничения скорости. Кроме того, можно зарезервировать отдельные пулы емкости для каждого рабочего потока.
- Регулирование службы может использоваться в нескольких приложениях. В некоторых случаях можно координировать использование (как показано выше). Если вы начнете видеть больше ожидаемого количества ошибок регулирования, это может быть признаком состязания между приложениями, обращаюющимися к службе. В этом случае может потребоваться временно сократить пропускную способность, введенную механизмом ограничения скорости, пока использование других приложений не снизится.
Когда следует использовать этот шаблон
Используйте этот шаблон в следующих случаях:
- Сокращение ошибок регулирования, вызванных службой с ограничением скорости.
- Уменьшите трафик по сравнению с наивным повтором при подходе к ошибке.
- Уменьшите потребление памяти путем отмены записей только в том случае, если их можно обработать.
Проектирование рабочей нагрузки
Архитектор должен оценить, как шаблон ограничения скорости можно использовать в проектировании рабочей нагрузки для решения целей и принципов, описанных в основных принципах Платформы Azure Well-Architected Framework. Например:
Принцип | Как этот шаблон поддерживает цели основных компонентов |
---|---|
Решения по проектированию надежности помогают рабочей нагрузке стать устойчивой к сбоям и обеспечить восстановление до полнофункционального состояния после сбоя. | Эта тактика защищает клиента, признавая и учитывая ограничения и затраты на взаимодействие со службой, когда служба хочет избежать чрезмерного использования. - RE:07 Самосохранение |
Как и любое решение по проектированию, рассмотрите любые компромиссы по целям других столпов, которые могут быть представлены с этим шаблоном.
Пример
В следующем примере приложения пользователи могут отправлять записи различных типов в API. Существует уникальный обработчик заданий для каждого типа записи, выполняющего следующие действия:
- Проверка
- Обогащение
- Вставка записи в базу данных
Все компоненты приложения (API, обработчик заданий А и обработчик заданий B) — это отдельные процессы, которые могут масштабироваться независимо. Процессы не взаимодействуют напрямую друг с другом.
Эта схема включает следующий рабочий процесс:
- Пользователь отправляет 10 000 записей типа A в API.
- API заквящает эти 10 000 записей в очереди A.
- Пользователь отправляет 5000 записей типа B в API.
- API заквещает эти 5000 записей в очереди B.
- Обработчик заданий видит очередь A содержит записи и пытается получить монопольную аренду на BLOB-объект 2.
- Обработчик заданий B видит очередь B содержит записи и пытается получить монопольную аренду blob-объектов 2.
- Обработчик заданий A не может получить аренду.
- Обработчик заданий B получает аренду на BLOB-объекте 2 в течение 15 секунд. Теперь он может ограничить скорость запросов к базе данных со скоростью 100 в секунду.
- Обработчик заданий B отменяет записи 100 из очереди B и записывает их.
- Один второй проходит.
- Обработчик заданий A видит очередь A имеет больше записей и пытается получить монопольную аренду на BLOB-объект 6.
- Обработчик заданий B видит очередь B имеет больше записей и пытается получить монопольную аренду на BLOB-объект 3.
- Обработчик заданий A получает аренду blob-объекта 6 в течение 15 секунд. Теперь он может ограничить скорость запросов к базе данных со скоростью 100 в секунду.
- Обработчик заданий B получает аренду на большой двоичный объект 3 в течение 15 секунд. Теперь он может ограничить скорость запросов к базе данных со скоростью 200 в секунду. (Она также содержит аренду для BLOB-объектов 2.)
- Обработчик заданий А отменяет запись 100 записей из очереди А и записывает их.
- Обработчик заданий B отменяет записи 200 из очереди B и записывает их.
- Один второй проходит.
- Обработчик заданий A видит очередь A имеет больше записей и пытается получить монопольную аренду на BLOB-объект 0.
- Обработчик заданий B видит очередь B имеет больше записей и пытается получить монопольную аренду на BLOB-объект 1.
- Обработчик заданий A получает аренду blob-объекта 0 в течение 15 секунд. Теперь он может ограничить скорость запросов к базе данных со скоростью 200 в секунду. (Она также содержит аренду для BLOB-объектов 6.)
- Обработчик заданий B получает аренду на большой двоичный объект 1 в течение 15 секунд. Теперь он может ограничить скорость запросов к базе данных со скоростью 300 в секунду. (Она также имеет аренду для больших двоичных объектов 2 и 3.)
- Обработчик заданий А отменяет 200 записей из очереди А и записывает их.
- Обработчик заданий B отменяет 300 записей из очереди B и записывает их.
- и т. д.
Через 15 секунд одно или оба задания по-прежнему не будут завершены. По истечении срока аренды процессор также должен уменьшить количество запросов, которые он отменяет и записывает.
Реализации этого шаблона доступны на разных языках программирования:
- Реализация Go доступна на сайте GitHub.
- Реализация Java доступна на сайте GitHub.
Связанные ресурсы
При реализации этого шаблона следует принять во внимание следующие шаблоны и рекомендации.
- Регулирование. Шаблон ограничения скорости, рассмотренный здесь, обычно реализуется в ответ на службу, которая регулируется.
- Повторные попытки. Когда запросы на регулирование службы приводят к ошибкам регулирования, обычно это подходит для повторных попыток после соответствующего интервала.
Выравнивание нагрузки на основе очередей аналогично, но отличается от шаблона ограничения скорости несколькими ключевыми способами:
- Ограничение скорости не обязательно требует использования очередей для управления нагрузкой, но требуется использовать надежную службу обмена сообщениями. Например, шаблон ограничения скорости может использовать такие службы, как Apache Kafka или Центры событий Azure.
- Шаблон ограничения скорости вводит концепцию распределенной системы взаимного исключения для секций, которая позволяет управлять емкостью для нескольких несогласованных процессов, взаимодействующих с одной и той же регулированием службы.
- Шаблон выравнивания нагрузки на основе очереди применяется в любое время, когда между службами имеется несоответствие производительности или повышение устойчивости. Это делает его более широким, чем ограничение скорости, что в частности касается эффективного доступа к регулированием службы.