Как настроить основных и отказоустойчивых подписчиков MQTT для очереди заданий с AWS IoT?

11

У меня есть система, где клиент (назовем его ClientA) может публиковать запросы на определенную тему MQTT. Брокером, в случае необходимости, является Amazon Web Services. Затем у меня есть другой клиент (назовем его MainSubscriber), который всегда подписан на одну и ту же тему, чтобы он мог получать запросы от ClientA и выполнять некоторую работу, которая, в конце концов, превращается в операцию базы данных. База данных, если это имеет значение, - DynamoDB.

Поскольку основной подписчик может быть не всегда доступен / онлайн, существует желание иметь отказоустойчивого подписчика, который будет резервным резервным резервным копированием основного подписчика. Идея состоит в том, что если основной подписчик не обрабатывает запрос своевременно, то отказоустойчивый подписчик включается и выполняет эквивалентную работу / работу с базой данных. Проблема заключается в том, что «работа» и получающаяся «операция с базой данных» не должны дублироваться как основным, так и отказоустойчивым подписчиками.

Вот чертеж архитектуры логической системы для этой системы.

                   -----> MainSubscriber ----
                  /                          \
ClientA --> Broker                            ---> Database
                  \                          /
                   ---> FailoverSubscriber --

Очевидно, что с такой системой есть некоторые проблемы:

  1. Как основной подписчик указывает отказоустойчивому подписчику, что он работает над запросом?
  2. Как отказоустойчивый подписчик обнаруживает, что основной подписчик не принял запрос и должен начать работу над ним?
  3. Как тогда отказоустойчивый подписчик удерживает основного подписчика в случае, если он внезапно возвращается в оперативный режим и принимает запрос?
  4. Как бороться с проблемами синхронности между основным и отказоустойчивым абонентами?

Я бы не стал изобретать велосипед, если для такой схемы уже существует существующее решение. Итак, мой первый вопрос: есть ли что-то уже там?

Если нет, то я думал об использовании DynamoDB со строго согласованным чтением, чтобы выступать в качестве посредника между основным и отказоустойчивым подписчиком. Итак, мой второй вопрос: существуют ли какие-либо хорошо разработанные схемы для этого?

Пол Гринберг
источник
Вы исследовали, может ли здесь быть полезна очередь сообщений, такая как Amazon SQS ? Кажется, что он интегрирован с AWS IoT и выглядит подходящим для проблемы стиля «рабочая очередь».
Aurora0001

Ответы:

8

В соответствии с документацией AWS SQS (как вы сказали, брокером является AWS), это должно быть нативно:

Сразу после получения сообщения оно остается в очереди. Чтобы предотвратить повторную обработку сообщения другими пользователями, Amazon SQS устанавливает тайм-аут видимости - период времени, в течение которого Amazon SQS не позволяет другим потребляющим компонентам получать и обрабатывать сообщение.

Проблема заключается в поиске правильного времени ожидания видимости в соответствии с вашим максимальным временем обработки.

У вас все еще есть небольшой шанс, что оба подписчика обработают одно и то же сообщение, в этом случае ваш код подписчика должен попытаться создать идемпотентный вывод для базы данных (по крайней мере, тот же первичный ключ) и должен корректно обработать ошибку при попытке вставить одну и ту же запись.

Tensibai
источник
7

Возможно, вы захотите взглянуть на концепцию очередей недоставленных сообщений AWS SQS . Из документов AWS:

Очередь недоставленных сообщений - это очередь, на которую другие (исходные) очереди могут ориентироваться для сообщений, которые не могут быть успешно обработаны (использованы). Вы можете отложить и изолировать эти сообщения в очереди недоставленных сообщений, чтобы определить, почему их обработка не удалась.

Итак, если вы укажете основному подписчику прослушивать из обычной очереди, а вторичному подписчику - из очереди недоставленных сообщений, проблема аварийного переключения должна быть решена.

Кроме того, с этим, 1, 2 и 3 ваших проблем позаботятся. В этом случае основным и дополнительным абонентам не нужно разговаривать друг с другом.

Кроме того, основываясь на ответе Tensibai, убедитесь, что ваш код подписчика написан так, чтобы получать по одному сообщению за раз, если несколько абонентов прослушивают одну и ту же очередь из-заvisibility timeout


Недостатком было бы то, что это привело бы к задержке обработки, сообщения попадали в очередь недоставленных сообщений только через некоторое время.

Так что, если вы этого не хотите, вы можете продолжить с ответом Тенсибая. И если вы можете это терпеть, вместо того, чтобы иметь дополнительную таблицу «Динамо» для проверки статуса, тогда вы можете использовать это.

Dawny33
источник