Как обеспечить, чтобы сообщения с одним и тем же идентификатором человека выполнялись одноэлементно, а разные - параллельно?
У меня есть azure function
который я хочу обработать несколько сообщений в parallel
но такие, что сообщения с одинаковыми Person Id
выполнены в singleton
манера.
Сценарий 1: у меня есть n
количество сообщений, каждое из которых имеет одинаковый Person Id
, Каждое сообщение должно быть выполнено в той последовательности, в которой оно было получено, но в singleton
мода.
Сценарий 2: у меня есть n
количество сообщений. Некоторые из них имеют Person Id:1
, Некоторые из них имеют Person Id:2
, Сообщения с разными личными идентификаторами могут быть выполнены в parallel
но сообщения с одинаковыми Person Id
должен быть выполнен в той последовательности, в которой они прибыли, и в singleton
мода.
Как мне этого добиться?
Изменить: мое приложение работает на Consumption Plan
поэтому я не могу предсказать, как и когда мое приложение будет масштабироваться. Функция Azure изначально получает аренду для всех разделов. Похоже, что функция Azure изначально получает аренду для всех разделов, когда приложение не масштабируется. Решение, предложенное @juunas в комментариях, беспокоит меня, что мое приложение никогда не масштабируется и может закончить выполнение пакетов последовательно одним экземпляром функции Azure, потому что моя функция не будет получать миллионы точек данных последовательно. Эвристика для масштабирования под Consumption Plan
не известны.
Возможно, каким-то образом совмещать концентратор событий в упорядоченной гарантии с долговечными функциями параллельного шаблона?
Изменить 2:
Рассмотрим две функции:
Appender
Функция: поддерживает упорядоченный список вcache
добавив Person Id вместе с любым другим обязательным атрибутом. Не обязательно лазурная функция.Processor
Функция: использование одноэлементного шаблона длительной функции (также можно хранить информацию об идентификаторе человека, который обрабатывается вcache
)
Поток:
Appender
после добавления отправляет сообщениеqueue
только сPerson Id
в сообщении.Person Id
будет использоваться какinstance id
как указано в документации.Processor
Если экземпляр функции еще не существует, начнется выполнение определенногоPerson Id
сообщения в кеше.- Если экземпляр
Processor
уже существует, сообщение будет проигнорировано.
Проблема:
Сценарий, в котором Processor
полностью опустошил кэшированный Person Id
заказанное сообщение, но параллельно Appender
добавляет еще одно сообщение Processor
выходит, поэтому новое сообщение не выполняется. Теперь кэш будет содержать 1 сообщение без обработки, и никакая функция лазера не будет вызываться для его обработки до тех пор, пока Appender
добавляет другое сообщение того же Person Id
,
Может быть, я должен использовать Durable Function
Monitor
картина как-то?
Изменить 3: Другой подход, который я рассмотрел, было использование шаблона монитора. Вместо того, чтобы игнорировать сообщение, если функция с определенным instance id
выполняется, он будет ждать через определенные промежутки времени. Само сообщение очереди будет просто Person Id
с другими его атрибутами, размещенными в упорядоченной последовательности в cache
, Это обеспечит выполнение каждого сообщения в правильной последовательности (с помощью списка, который содержится в cache
). Однако следующая проблема, как упомянуто в примере синглтона, может возникнуть при использовании подхода монитора вместе с очередью как:
В этом образце есть потенциальное состояние гонки. Если два экземпляра HttpStartSingle выполняются одновременно, оба вызова функций сообщат об успешном выполнении, но фактически будет запущен только один экземпляр оркестрации. В зависимости от ваших требований, это может иметь нежелательные побочные эффекты. По этой причине важно убедиться, что никакие два запроса не могут выполнять эту функцию триггера одновременно.
Другой подход, который я рассмотрел, заключался в использовании шаблона Monitor для выполнения только одного сообщения на функцию путем объединения Edit 2. Appender
подход вместе с одноэлементным шаблоном, используя идентификатор экземпляра
1 ответ
Поместите рабочие элементы в базу данных. Каждый раз, когда добавляется новый рабочий элемент, также ставится в очередь вызов функции Azure.
Затем эта функция Azure будет последовательно обрабатывать все рабочие элементы, поставленные в очередь для этого человека. Он запросит базу данных, чтобы получить всю работу для этого человека, а не только какую-либо работу.
Должен существовать механизм, обеспечивающий выполнение в любой момент времени только одного вызова функции Azure для конкретного человека. Вы можете сделать это, реализовав некоторую форму блокировки. Например, вы можете записать в таблицу базы данных информацию о том, что человек 1234 в данный момент обрабатывается. Если функция Azure вызывается с человеком 1234 и она замечает, что этот человек уже обрабатывается, она просто вернется и ничего не сделает.
Эта схема, которую я только что предложил, имеет несколько дыр, таких как условия гонки. Но это можно исправить. Я надеюсь, что эта идея поможет вам решить проблему.
Я полагаю, что мета-ошибка заключается в том, чтобы настаивать на решении проблемы с функциями, очередями или другими примитивами Azure. Обычная база данных (например, таблицы Azure или SQL) делает эту работу.