Как обеспечить, чтобы сообщения с одним и тем же идентификатором человека выполнялись одноэлементно, а разные - параллельно?

У меня есть 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:

Рассмотрим две функции:

  1. Appender Функция: поддерживает упорядоченный список в cache добавив Person Id вместе с любым другим обязательным атрибутом. Не обязательно лазурная функция.
  2. Processor Функция: использование одноэлементного шаблона длительной функции (также можно хранить информацию об идентификаторе человека, который обрабатывается в cache)

Поток:

  1. Appenderпосле добавления отправляет сообщение queue только с Person Id в сообщении. Person Id будет использоваться как instance id как указано в документации.
  2. ProcessorЕсли экземпляр функции еще не существует, начнется выполнение определенного Person Id сообщения в кеше.
  3. Если экземпляр Processor уже существует, сообщение будет проигнорировано.

Проблема:

Сценарий, в котором Processor полностью опустошил кэшированный Person Id заказанное сообщение, но параллельно Appender добавляет еще одно сообщение Processor выходит, поэтому новое сообщение не выполняется. Теперь кэш будет содержать 1 сообщение без обработки, и никакая функция лазера не будет вызываться для его обработки до тех пор, пока Appender добавляет другое сообщение того же Person Id,

Может быть, я должен использовать Durable FunctionMonitor картина как-то?

Изменить 3: Другой подход, который я рассмотрел, было использование шаблона монитора. Вместо того, чтобы игнорировать сообщение, если функция с определенным instance id выполняется, он будет ждать через определенные промежутки времени. Само сообщение очереди будет просто Person Id с другими его атрибутами, размещенными в упорядоченной последовательности в cache, Это обеспечит выполнение каждого сообщения в правильной последовательности (с помощью списка, который содержится в cache). Однако следующая проблема, как упомянуто в примере синглтона, может возникнуть при использовании подхода монитора вместе с очередью как:

В этом образце есть потенциальное состояние гонки. Если два экземпляра HttpStartSingle выполняются одновременно, оба вызова функций сообщат об успешном выполнении, но фактически будет запущен только один экземпляр оркестрации. В зависимости от ваших требований, это может иметь нежелательные побочные эффекты. По этой причине важно убедиться, что никакие два запроса не могут выполнять эту функцию триггера одновременно.

Другой подход, который я рассмотрел, заключался в использовании шаблона Monitor для выполнения только одного сообщения на функцию путем объединения Edit 2. Appender подход вместе с одноэлементным шаблоном, используя идентификатор экземпляра

1 ответ

Поместите рабочие элементы в базу данных. Каждый раз, когда добавляется новый рабочий элемент, также ставится в очередь вызов функции Azure.

Затем эта функция Azure будет последовательно обрабатывать все рабочие элементы, поставленные в очередь для этого человека. Он запросит базу данных, чтобы получить всю работу для этого человека, а не только какую-либо работу.

Должен существовать механизм, обеспечивающий выполнение в любой момент времени только одного вызова функции Azure для конкретного человека. Вы можете сделать это, реализовав некоторую форму блокировки. Например, вы можете записать в таблицу базы данных информацию о том, что человек 1234 в данный момент обрабатывается. Если функция Azure вызывается с человеком 1234 и она замечает, что этот человек уже обрабатывается, она просто вернется и ничего не сделает.

Эта схема, которую я только что предложил, имеет несколько дыр, таких как условия гонки. Но это можно исправить. Я надеюсь, что эта идея поможет вам решить проблему.

Я полагаю, что мета-ошибка заключается в том, чтобы настаивать на решении проблемы с функциями, очередями или другими примитивами Azure. Обычная база данных (например, таблицы Azure или SQL) делает эту работу.

Другие вопросы по тегам