У меня есть система, где клиент (назовем его ClientA) может публиковать запросы на определенную тему MQTT. Брокером, в случае необходимости, является Amazon Web Services. Затем у меня есть другой клиент (назовем его MainSubscriber), который всегда подписан на одну и ту же тему, чтобы он мог получать запросы от ClientA и выполнять некоторую работу, которая, в конце концов, превращается в операцию базы данных. База данных, если это имеет значение, - DynamoDB.
Поскольку основной подписчик может быть не всегда доступен / онлайн, существует желание иметь отказоустойчивого подписчика, который будет резервным резервным резервным копированием основного подписчика. Идея состоит в том, что если основной подписчик не обрабатывает запрос своевременно, то отказоустойчивый подписчик включается и выполняет эквивалентную работу / работу с базой данных. Проблема заключается в том, что «работа» и получающаяся «операция с базой данных» не должны дублироваться как основным, так и отказоустойчивым подписчиками.
Вот чертеж архитектуры логической системы для этой системы.
-----> MainSubscriber ----
/ \
ClientA --> Broker ---> Database
\ /
---> FailoverSubscriber --
Очевидно, что с такой системой есть некоторые проблемы:
- Как основной подписчик указывает отказоустойчивому подписчику, что он работает над запросом?
- Как отказоустойчивый подписчик обнаруживает, что основной подписчик не принял запрос и должен начать работу над ним?
- Как тогда отказоустойчивый подписчик удерживает основного подписчика в случае, если он внезапно возвращается в оперативный режим и принимает запрос?
- Как бороться с проблемами синхронности между основным и отказоустойчивым абонентами?
Я бы не стал изобретать велосипед, если для такой схемы уже существует существующее решение. Итак, мой первый вопрос: есть ли что-то уже там?
Если нет, то я думал об использовании DynamoDB со строго согласованным чтением, чтобы выступать в качестве посредника между основным и отказоустойчивым подписчиком. Итак, мой второй вопрос: существуют ли какие-либо хорошо разработанные схемы для этого?
Ответы:
В соответствии с документацией AWS SQS (как вы сказали, брокером является AWS), это должно быть нативно:
Проблема заключается в поиске правильного времени ожидания видимости в соответствии с вашим максимальным временем обработки.
У вас все еще есть небольшой шанс, что оба подписчика обработают одно и то же сообщение, в этом случае ваш код подписчика должен попытаться создать идемпотентный вывод для базы данных (по крайней мере, тот же первичный ключ) и должен корректно обработать ошибку при попытке вставить одну и ту же запись.
источник
Возможно, вы захотите взглянуть на концепцию очередей недоставленных сообщений AWS SQS . Из документов AWS:
Итак, если вы укажете основному подписчику прослушивать из обычной очереди, а вторичному подписчику - из очереди недоставленных сообщений, проблема аварийного переключения должна быть решена.
Кроме того, с этим, 1, 2 и 3 ваших проблем позаботятся. В этом случае основным и дополнительным абонентам не нужно разговаривать друг с другом.
Кроме того, основываясь на ответе Tensibai, убедитесь, что ваш код подписчика написан так, чтобы получать по одному сообщению за раз, если несколько абонентов прослушивают одну и ту же очередь из-за
visibility timeout
Недостатком было бы то, что это привело бы к задержке обработки, сообщения попадали в очередь недоставленных сообщений только через некоторое время.
Так что, если вы этого не хотите, вы можете продолжить с ответом Тенсибая. И если вы можете это терпеть, вместо того, чтобы иметь дополнительную таблицу «Динамо» для проверки статуса, тогда вы можете использовать это.
источник