#azure #azure-functions #azure-durable-functions
#azure #azure-функции #azure-durable-функции
Вопрос:
Будучи довольно новичком в среде надежных функций Azure, я изо всех сил пытаюсь найти наилучший способ обработки последующих вызовов API, в котором реализованы ограничения скорости.
Способ настройки моего потока, как показано ниже:
- Функция HistorySynchronizer_HttpStart: имеет
HttpTrigger
иDurableClient
привязки в подписи и вызывает следующую функцию оркестровки: - Функция HistorySynchronizer: имеет
OrchestrationTrigger
привязку в подписи. Эта функция вызовет API (await) и вернет коллекцию. Для каждого элемента в этой коллекции он запустит новое действие:context.CallActivityAsync()
(объединение их в aList
и выполнение aTask.WhenAll()
) - Функции ProcessActivity: имеет
ActivityTrigger
привязку в подписи. Эта функция должна будет выполнить вызов конечной точки API с ограниченной скоростью. И именно эти действия я хочу ограничить (в нескольких оркестровках).
Итак, то, что я ищу, — это реализация шаблона регулирования:
- Мне нужно потокобезопасное общее состояние (я думал о долговременной сущности), которое отслеживает количество вызовов, выполненных с этим API
- Прежде чем функция ProcessActivity выполнит вызов этого API, она должна проверить у объекта Durable, может ли он вызвать API, или ему нужно подождать определенный промежуток времени перед выполнением этого вызова.
- В случае, если придется ждать, действие должно будет «спать», и я думал о долговременном таймере, но, похоже, его следует использовать в функции оркестровки, а не в функции Activity.
- В случае, если вызов API разрешен, действие должно обновить счетчик скорости в этом объекте общего состояния.
Я не вижу стандартной реализации для достижения этой цели, и я хочу перенести как можно больше этой логики проверки / ожидания из основной оркестровки.
Будет ли лучшим подходом реализовать подрегулировку для каждого вызова API, который должен регулироваться, где должна выполняться проверка, перед вызовом Activity?
С нетерпением жду любой информации.
Комментарии:
1. пожалуйста, посмотрите мой ответ здесь youtube.com/watch?v=sH4t3cs9qkM
Ответ №1:
Сэм, я вижу несколько вариантов. Я также создал видео в ответ на это. Давайте сделаем шаг назад и посмотрим, как мы могли бы это сделать, используя обычные функции (не durable).
Первый подход заключается в том, чтобы превратить функцию в функцию, запускаемую очередью, и использовать механизм очереди для управления масштабированием, используя batchSize
и newBatchThreshold
:
Другим способом было бы иметь функцию, запускаемую http, и использовать ее в host.js файл:
С помощью durable functions мы можем это сделать:
Вы специально спрашивали об управлении масштабированием за интервал времени, и вот как я бы это сделал:
- преобразуйте вашу функцию activity для запуска в очереди
- при каждом выполнении функции, запускаемой очередью, эта функция вставляет запись в хранилище таблиц, указывающую на активный запуск
- перед фактическим запуском внешнего http-вызова проверьте хранилище таблиц, чтобы узнать, сколько существует активных подключений.
- если количество текущих подключений меньше X, Обработайте сообщение (т. Е. Выполните внешний вызов), если хранилище таблиц показывает, что все подключения приняты, затем поместите сообщение обратно в очередь!
Комментарии:
1. Спасибо, Алекс, что уделил так много времени ответу на вышеуказанное. Моя цель состояла в том, чтобы как можно больше полагаться на надежные функции, поскольку у них, похоже, есть длительные спящие (таймеры), долговечные объекты (так зачем мне беспокоиться о табличном хранилище, если фреймворк что-то предоставляет). Я надеялся сделать это, не полагаясь на очереди служебной шины. Приведенный выше вариант будет скорее резервным вариантом на случай, если Durable Functions не предложит что-то из коробки
2. эй, Сэм, я не верю, что у OOB durable functions есть что-то подобное. надежные объекты — отличный вариант, у меня нет опыта работы с ними, но у меня был большой опыт работы с хранилищем таблиц из многих потоков
3. из того, что я понимаю о долговременных объектах, они доступны только в рамках оркестровки. другими словами, когда ваш клиент durable завершен, эти данные больше не будут доступны для будущего выполнения вашего приложения durable function
Ответ №2:
Есть лучший способ сделать это. Вместо того, чтобы пытаться ограничить его на своей стороне на основе функций параллельной активности или активных HTTP-запросов, почему бы вам не полагаться на сам API? Он знает, когда пришло время вернуть 429.
Я бы добавил очередь, захватил задачу, вызвал API, если есть 429, вернул сообщение о задаче в очередь с экспоненциальной политикой задержки.
Ответ №3:
У меня похожий сценарий, подобный Sam, но с одним основным отличием, которое еще больше усложняет проблему.
В этом случае существует несколько функций оркестратора, вызывающих друг друга вложенным способом.
Каждый из них в основном делает то же самое:
- Получить ресурс API из функции activity
- Просмотрите элементы ответа и вызовите одну или несколько функций подорганизаторов. (До нижней части дерева)
- Верните ответ родительскому оркестратору.
Идея состоит в том, чтобы скопировать весь Rest API в Azure data lake как часть процесса ETL. (Уровень извлечения)
Например: Клиенты => Заказы => Счета-фактуры
Теперь я не могу использовать вышеуказанные решения (работая с очередью для управления скоростью), потому что я хочу, чтобы каждый оркестратор ожидал результата действия и только затем выполнял вложенные вызовы на основе результата действия.
Я думаю о другом решении, которое будет работать с синхронизированным деревом оркестровки.
-
Создайте функцию оркестровки обертывания вокруг функции activity, которую мы хотим ограничить. (мы не можем ждать от activity) Эта функция выполнит следующее:
- добавьте собственный идентификатор экземпляра в некоторую очередь хранилища
- дождитесь внешнего события — «HttpRequestAllowed»
- продолжайте в обычном режиме. (вызовите действие, выполните следующие задачи)
-
Создайте отдельную клиентскую функцию, которая выполняет следующее:
- считайте один идентификатор экземпляра из очереди
- вызовите событие «HttpRequestAllowed» для этого идентификатора экземпляра
- подождите некоторое время (по ограничению скорости) и обработайте следующий идентификатор экземпляра
- продолжайте до конца выполнения
Таким образом, текущая настройка должна продолжать работать таким же образом, и когда не ожидается никаких внешних событий, оркестраторы будут выгружены Azure из worker до прихода нового события.