Как восстановить состояние в основанной на событии, архитектуре микросервиса, управляемой сообщениями, при сценарии отказа

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

Принимая этот контекст и представляя чрезмерно упрощенную систему упорядочения, как показано ниже:

система заказов

и следующий поток сообщений:

  • Заказ помещается из некоторого источника (веб-сайт/мобильный телефон и т.д.).
  • Служба заказов принимает заказ и публикует CreateOrderEvent
  • InventoryService реагирует на CreateOrderEvent, делает некоторые вещи инвентаря и публикует InventoryUpdatedEvent, когда это делается
  • Затем служба счета-фактуры реагирует на InventoryUpdatedEvent, отправляет счет-фактуру и публикует EmailInvoiceEvent

Все услуги завершены, и мы счастливо обрабатываем заказы... Все счастливы. Затем служба инвентаризации по какой-то причине снижается 😬

Предполагая, что события на шине событий текут в "неблокирующей" усадьбе. То есть сообщения публикуются в центральную тему и не накапливаются в очереди, если никакая служба не читает от нее (то, что я пытаюсь передать, является шиной события, где, если событие опубликовано на шине, оно будет течь "прямо", а не в очереди - игнорируйте, какая платформа/технология обмена сообщениями используется в этой точке). Это означало бы, что если служба инвентаризации снизилась в течение 5 минут, CreateOrderEvent, проходящая через шину событий в течение этого времени, теперь "ушла" или не увидена службой Inventory, потому что в нашей слишком упрощенной системе никакая другая система не заинтересована в этих событиях.

Теперь мой вопрос: как служба инвентаризации (и система в целом) восстанавливает состояние таким образом, что никакие заказы не будут упущены/не обработаны?

Ответ 1

Хороший вопрос! Таким образом, здесь играют в основном три силы:

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

Для # # и # 2 вам нужен какой-то постоянный журнал событий. Традиционная очередь сообщений/тема может предоставить это, хотя вам нужно рассмотреть случаи, когда сообщения могут обрабатываться не по порядку по транзакциям/исключениям/видам поведения. Более простой журнал, такой как Apache Bookkeeper, Apache Kafka, AWS Kinesis и т.д., Может последовательно хранить и сохранять эти типы событий и оставлять потребителям возможность обрабатывать/фильтровать дубликаты/потоки разделов и т.д.

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

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

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

На самом деле больше нужно отслеживать, что происходит, если служба "escrow" идет вниз/не работает, как она обрабатывает дубликаты, как она обрабатывает неожиданные события, учитывая, что она заявляет, как она способствует дублированию событий и т.д... но, надеюсь, достаточно, чтобы начать.

Ответ 2

Я собираюсь дать ответ архитекторам, а не деталям. Надеюсь, вы не против.

Первое предложение отделяет все понятия: события, сообщения, шину и/или очередь и асинхронный. Это открывает возможности, если вы еще не определились с программным обеспечением, которое вы используете для реализации своей шины.

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

  • Служба инвентаризации обрабатывает вытягивание сообщения из очереди. В этом методе служба выполняет резервное копирование и находит любые сообщения.
  • "Шина" гарантирует доставку. Когда происходит сбой, он ждет, пока служба не восстановит резервную копию (может быть ping, чтобы увидеть, будет ли снова или услуга может перерегистрироваться в качестве абонента (тип сценария Enterprise Service Bus).

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

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

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

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

Надеюсь, это имеет смысл, поскольку я в основном делал мозг для маневра клавиатуры в моем состоянии ADHD.; -)

Ответ 3

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

Кстати, отношения между клиентом и предприятием - это единое целое, в котором мы хотим быть тесно связанными, в отличие от всех других внутри. Поэтому в этом случае это пример "авторитета", а не автономии. Мы гарантируем SLA, представленный брендом.

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

Таким образом, цель обеспечения того, чтобы сообщения/события обрабатывались подписчиками, может быть достигнута путем обеспечения того, чтобы услуги никогда не снижались (например, концепция "виртуального актера" в MS Orleans), или добавив больше логики обработки ошибок в поставку механизм.

Последний вариант кажется более централитическим/связанным, а не автономным/развязанным. Но если вы предполагаете, что службы не всегда доступны (как и следовало бы), вам необходимо рассмотреть, чтобы удалить другое предположение о "переходных" сообщениях.

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

Кроме того, если сервисы как инкапсулированные возможности гарантируют высокий уровень обслуживания ( "никогда не вниз" ), то контроль за итогом всей системы (= предприятия) можно непрерывно адаптировать, регулируя приоритеты сообщений, а также внедряя новые службы и событий в систему.

Другим важным аспектом является тот факт, что синхронные архитектуры (= на основе стека вызовов) предоставляют три функции, которые асинхронные архитектуры (управляемые событиями) не отображаются для сокращения зависимостей: координация, продолжение и контекст (см. Hohpe, Программирование без стека вызовов ", 2006).

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

Эти современные системы CEP, которые должны иметь дело с огромными объемами данных, разными скоростями, структурами и уровнями корректности, могут быть реализованы поверх современной обработки данных и больших систем данных (например, Spark), которые будут использоваться для понимания, принятия решений и оптимизация как гибкими командами (для улучшения их обслуживания), так и командами управления на их уровне.