Проведя немного больше исследований, я наткнулся на эту статью, из которой я вытащил некоторые цитаты, которые, на мой взгляд, полезны для того, чего я хочу достичь (и для любых будущих читателей). Это дает возможность принять модель реактивного программирования вместо модели императивного программирования.
Event-источников
Идея здесь состоит в том, чтобы представить переход состояния каждого приложения в форме неизменяемого события. Затем события сохраняются в форме журнала или журнала по мере их возникновения (также называемой «хранилищем событий»). Они также могут быть запрошены и сохранены на неопределенный срок, чтобы представить, как состояние приложения в целом развивалось с течением времени.
Это помогает достичь того, что если микросервис выходит из строя, а другие относящиеся к нему события публикуются, и события потребляются, скажем, другими экземплярами этого микросервиса, когда этот микросервис возвращается, он может обратиться к нему, event store
чтобы получить все события, которые он пропустил за период, когда он пошел вниз.
Apache Kafka как брокер событий
Рассмотрим использование Apache Kafka, который может хранить и отправлять тысячи событий в секунду и имеет встроенные механизмы репликации и отказоустойчивости. Он имеет постоянное хранилище событий, которые могут храниться на диске неограниченное количество раз и использоваться в любое время (но не удаляться) из темы (необычная очередь Кафки), в которую они были доставлены.
Затем событиям назначаются смещения, которые однозначно идентифицируют их в теме - Kafka может самостоятельно управлять смещениями, легко предоставляя семантику доставки «не более одного раза» или «не менее одного раза», но они также могут быть согласованы, когда потребитель события присоединяется к теме позволяя микросервисам начать потреблять события из любого произвольного места во времени - обычно с того места, где остановился потребитель. Если смещение последнего использованного события транзакционно сохраняется в локальном хранилище сервисов после успешного завершения сценариев использования, это смещение можно легко использовать для достижения семантики доставки события «ровно один раз».
Фактически, когда потребители идентифицируют себя с Kafka, Kafka будет записывать, какие сообщения были доставлены тому или иному потребителю, чтобы он не доставлял его снова.
Саги
Для более сложных вариантов использования, где связь между различными сервисами действительно необходима, ответственность за завершение варианта использования должна быть хорошо распознана - сценарий использования децентрализован и заканчивается только тогда, когда все задействованные службы подтверждают свою задачу как успешно выполненную, в противном случае весь сценарий использования должен потерпеть неудачу и корректирующие меры должны быть инициированы для отката любого недопустимого локального состояния.
Это когда сага вступает в игру. Сага - это последовательность локальных транзакций. Каждая локальная транзакция обновляет базу данных и публикует сообщение или событие для запуска следующей локальной транзакции в саге. Если локальная транзакция терпит неудачу из-за нарушения бизнес-правила, тогда сага выполняет серию компенсирующих транзакций, которые отменяют изменения, сделанные предыдущими локальными транзакциями. Прочитайте это для получения дополнительной информации.