Рассмотрение Axon в новом проекте

Через несколько месяцев я начну новый проект.
Проект будет содержать множество бизнес-логики, разбросанных по нескольким subdomains. Да, мы будем использовать принципы Domain Driven Design. Техника будет состоять из Spring, Spring Boot & Hibernate стека.

Я искал некоторые библиотеки Java, чтобы охватить такие инфраструктурные вещи, как:

  • domain event publication
  • event store
  • event deduplication
  • resequencers на стороне потребителя
  • projections
  • reliable publishing
  • reliable delivery & redelivery
  • ...

Я наткнулся на Axon Framework. Я уже слышал об этом, не знал в деталях. Так что я прочитал несколько сообщений в блогах, немного документации и посмотрел несколько трансляций на Youtube.

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

Обработка команд

Axon использует CommandHandlers с void методами. Можно ли заставить их возвращать значение (например, сгенерированный бизнес-идентификатор) или объекты для уведомления о бизнес-операции?
Для меня не проблема, что этим методом будет блокировка ввода-вывода.


Публикация событий локального и удаленного домена

Я хочу иметь четкое разделение событий домена local и remote. Local domain события должны быть видны и потребляться только в локальном поддомене. Можно ли настроить синхронизацию потребления событий и / или асинхронность? События моего локального домена могут быть «жирными». Им разрешено переносить больше данных, потому что они не пересекают границы домена.

Remote domain events будет "тонким", поэтому для удаленных доменов потребуется только минимальный объем данных. Операционные события этого типа всегда должны обрабатываться асинхронно.

Можно ли преобразовать событие локального (толстого) домена в событие удаленного (тонкого) домена на границе домена? Под «краем» я подразумеваю инфраструктурную сторону. Таким образом, модели предметной области не требуется различать события локального и удаленного домена.


CQRS синхронно

Мое приложение будет состоять из 1 (возможно 2) core domains и several subdomains. Некоторые домены содержат много бизнес-логики и потребуют CQRS.
Другой домен будет более грубым. Можно ли делать CQRS синхронно?
Я хочу начать с этого, прежде чем добавлять технические сложности, такие как обработка асинхронности. Это возможно с Axon?
Это также означает, что события домена будут храниться в хранилище событий без использования event sourcing.

Можно ли использовать Axon event store без источника событий? То же самое и с проекциями, я просто хочу проецировать события предметной области для построения моей модели чтения.


Модульный монолит

Мы будем использовать modular monolith.
Не очень модно в наши дни со всеми microservices штучками. Хотя я убежден в наличии монолита, в котором каждый домен полностью разделен (код приложения и схема БД), где операции будут обрабатываться с конечной согласованностью, а события домена содержат необходимые данные. Позже, при необходимости, будет проще перейти на microservices architecture.

Является ли Axon фреймворком, который вписывается в модульную монолитную архитектуру? Что нужно учитывать?


Полностью разделенная модель предметной области (не зависящая от персистентности)

Модель предметной области будет полностью отделена от модели данных. Нам нужен репозиторий, который считывает модель данных (с использованием Hibernate) и использует data mapper для создания агрегата, когда он должен быть загружен.
Также необходим другой способ, агрегат необходимо преобразовать и сохранить в модель данных (с использованием средства отображения данных).
Кроме того, события домена агрегатов необходимо сохранять в хранилище событий и публиковать в локальных или удаленных обработчиках событий.

Это имеет некоторые последствия:

  • нам нужно иметь полный контроль над реализацией репозитория, который взаимодействует с одним или несколькими DAO (репозиториями данных Spring), чтобы извлекать необходимые данные из сущностей Hibernate и создавать на их основе агрегат. В конце концов, агрегат можно смоделировать в виде двух или даже трех реляционных таблиц.

  • нам не нужна аннотация Hibernate в модели предметной области

Возможен ли такой подход с Axon? Я вижу только примеры, использующие прямой JPA (модель предметной области сопоставляет сущности от 1 до 1) или источники событий.
Этот подход действительно мешает нам, поскольку модель отдельной предметной области дает гораздо больше возможностей, чем ее прямое сопоставление к объектам данных.

Ниже приведен пример того, чего я хочу достичь:

Агрегирование (без JPA) в некотором пакете модели предметной области:

public class ScoringResultAggregate {
  // members, constructor, operation omitted for brevity
}

Hibernate Entity в некотором пакете инфраструктуры:

@Entity
@Table(name ="SOME_TABLE_NAME)
public class ScoringResultEntity {
  // member and getters & setters; no domain logic
}

Интерфейс репозитория, принадлежащий модели предметной области:

public interface ScoringResultRepository {
  void save(ScoringResultAggregate scoringResultAggregate);

  ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber);
}

Адаптер, реализующий интерфейс репозитория; отвечает за отображение агрегата из / в модель данных (JPA):

class ScoringResultAdapterRepository implements ScoringResultRepository {
  private ScoringResultJpaRepository scoringResultJpaRepository;

  ScoringResultJPARepository(ScoringResultJpaRepository scoringResultJpaRepository) {
    this.scoringResultJpaRepository= scoringResultJpaRepository;

  public void save(ScoringResultAggregate scoringResultAggregate) {
    // converts aggregate to ScoringResultEntity and saves the state into DB
  }

  public ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber) {
    // loads an ScoringResultEntity from DB and converts it into an aggregate
  }
}


Axon Server

Axon server выглядит очень многообещающе. Хотя, разве это полезно только для event sourcing? Можно ли его использовать вместе с базой данных Sql, где хранятся агрегаты (постоянство состояния), а события домена сохраняются на сервере Axon Server?



Много вопросов. Надеюсь, кто-нибудь с опытом работы с Axon сможет мне помочь :-)


person user2054927    schedule 19.01.2020    source источник


Ответы (2)


Я чувствую, что Джаспер говорит правильные вещи, но я также думаю, что могу выделить их немного больше:

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

  • Публикация событий локального и удаленного домена - Джаспер четко заявляет об этом, и он прав. Вы испытываете желание сформировать ограниченный контекст, для которого Axon Server (Enterprise) поддерживает. Если вы не используете Axon, вам придется построить эту инфраструктуру самостоятельно.

  • CQRS синхронно - Axon предоставляет дескрипторы для асинхронного и синхронного обмена сообщениями. Основное отличие состоит в том, что вы заблокируете результат отправки ваших сообщений. Например, CommandGateway имеет методы send и sendAndWait, таким образом предоставляя вам синхронизацию и отправку команд async. Наконец, совершенно нормально использовать Axon Server в качестве хранилища событий без использования Event Sourcing. Event Sourcing - это выбор при использовании Axon, а не требование.

  • Модульный монолит - AxonIQ как компания активно поддерживает такой подход к созданию программного обеспечения. Так что да, вы можете это сделать, и нет, я не могу придумать ничего, о чем вам следует подумать перед тем, как это сделать.

  • Полностью разделенная модель предметной области (не зависящая от персистентности). Из вашей модели запроса вы полностью контролируете, как вы хотите сопоставить свою модель данных с фактической моделью, которую вы будете использовать. Агрегат в терминах Axon следует рассматривать как вашу командную модель, для которой вы можете выбрать подход к хранилищу с источником событий или подход к хранилищу с сохранением состояния. Реализация с сохранением состояния, предоставленная Axon Framework, работает на основе JPA, поэтому вам потребуется установить некоторые аннотации рядом с аннотациями аксонов в вашей командной модели. Если вам нужно разделить это, я могу представить, что вы создадите свой собственный вариант Repository и AggregateFactory. Опять же, подход Event Sourcing полностью очистит вашу модель предметной области от аннотаций персистентности, поэтому, честно говоря, я бы пошел по этому пути.

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

person Steven    schedule 20.01.2020
comment
Привет, Стивен, спасибо, что уделили время, чтобы ответить на мои вопросы. Для ясности я добавил упрощенный пример модели разделенной предметной области. Что касается Event Sourcing, я очень редко использую случаи, когда требуется ES. Вот почему агрегаты будут «храниться в состоянии», а не «сохранять события». CQRS будет использоваться, хотя по большей части синхронно (изначально). Вы хоть представляете, сколько работы (и сложности) включает в себя настраиваемый репозиторий и AggregateFactory? - person user2054927; 20.01.2020
comment
Честно говоря, @ user2054927, я думаю, что создание событий для вашего агрегата будет идеально соответствовать вашему вопросу о полностью разделенной модели предметной области (не зависящей от персистентности), поскольку он использует совершенно другую модель для предметной области, в отличие от подхода персистентности. Еще одно преимущество использования источников событий состоит в том, что вы используете свои события в качестве основы для любой модели в вашем приложении. Тем не менее, это, конечно, ваш выбор, это только мое мнение. - person Steven; 21.01.2020
comment
Если честно, реализация ваших собственных Repository и AggregateFactory может потребовать значительных усилий, но фреймворк позволяет такую ​​модификацию при желании. Я бы рекомендовал задать вопрос непосредственно в AxonIQ, если вы считаете, что это правильный путь. Уверены, что они готовы обсудить с вами подход. - person Steven; 21.01.2020

Я надеюсь, что смогу ответить на некоторые из них, но я также не очень опытен в использовании Axon:

Возвращаемые значения из обработчика команд - Да, это возможно. У нас был пример, в котором мы возвращаем сгенерированный совокупный идентификатор (я не уверен на 100% в этом ответе)

Публикация событий локального и удаленного домена - Да, Axon Server ENTERPRISE (!) поддерживает мульти-контекстную сборку, предназначенную для этой цели. https://axoniq.io/product-overview/axon-server-enterprise

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

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

Модульный монолит - не должно быть технических проблем.

Полностью разделенная модель домена (агностик персистентности). Вопрос не совсем ясен, но в Axon Server сохраняются только события. Агрегаты создаются последовательностью агрегатов. Не используйте для этого никакие другие данные. Агрегат используется для обработки команд с проверками состояния и применения новых событий.

Если система получает командное сообщение, Axon Framework проверяет идентификатор агрегата и повторно создает агрегат, воспроизводя все существующие события для этого агрегата. Затем вызывается метод для @CommandHandler и тип сообщения команды на агрегате с состоянием системы. Не делай этого в одиночку.

С другой стороны. Создавайте собственные пользовательские проекции (модели просмотра), прослушивая события (@EventHandler), и сохраняйте данные в своем собственном формате в любых моделях / репозиториях данных. Вы можете, например, создать REST api поверх этого, чтобы использовать данные.

Axon Server. Используйте его там, где он создан. Используйте его как хранилище событий, а не для других целей.

См. Дополнительную информацию и почему: https://www.youtube.com/watch?v=zUSWsJteRfw

person Jasper Huzen    schedule 19.01.2020