Избавьтесь от сложного кода: Spring Boot и CQRS — золотая комбинация!
Избавьтесь от сложного кода: Spring Boot и CQRS — золотая комбинация!

Привет всем, я Букай Чен~

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

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

Узнайте о CQRS

Что такое CQRS?

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

Основная цель CQRS — упростить задачи, гарантируя, что каждая задача отвечает за одну операцию (команду или запрос, но никогда за обе).

Происхождение и эволюция

CQRS не является совершенно новой концепцией. Его корни уходят в CQS (разделение командных запросов), принцип, популяризированный Бертраном Мейером, создателем языка программирования Eiffel. В то время как CQS в первую очередь касается методов, заявляя, что методы должны выполнять команды или отвечать на запросы, CQRS распространяет этот принцип на архитектурный уровень приложения, предполагая, что команды и запросы обрабатываются различными архитектурными компонентами.

Зачем использовать CQRS?

  • Масштабируемость: CQRS обеспечивает горизонтальное масштабирование,Потому что вы можете развернуть несколько экземпляров службы команд или запросов в зависимости от ваших потребностей. Операции с интенсивным чтением и записью можно масштабировать независимо.,Тем самым оптимизируя использование ресурсов.
  • Гибкость: четкое различие между командами и запросами означает, что разработчики могут выбрать наиболее подходящий механизм сохранения, стратегию и оптимизацию для каждой команды и запроса. Например,Хотя реляционная база данных может использоваться для транзакционных командных операций.,Но денормализованное хранилище представлений и даже системы полнотекстового поиска могут предоставлять услуги запросов.
  • Ремонтопригодность: хорошо реализовано Шаблон CQRS упрощает базу кода. Разделение моделей по операциям чтения и записи.,Разработчики могут сосредоточиться на каждой детали операции,не отвлекаясь от неактуальных вопросов. Такая изоляция обычно приводит к более чистому коду.,Легче поддерживать и расширять.
  • Повышенная безопасность: CQRS, по сути, способствует улучшению методов обеспечения безопасности. Путем отделения команд и операций запроса,Упрощает реализацию строгой проверки и проверки авторизации операций записи.,При этом оптимизируется производительность операций чтения.

CQRS в микросервисах

Рост архитектуры микросервисов усилил потребность в CQRS. В распределенных системах, где службы часто должны быть автономными и сильно развязанными, CQRS обеспечивает четкий путь. Подпишитесь на общедоступный аккаунт: Колонка технологий Ма Юаня, отвечайте, используя ключевые слова: BAT, и получайте реальные вопросы для интервью от крупных компаний! Каждый микросервис может использовать шаблон CQRS, гарантируя, что его внутренние механизмы обработки команд и запросов будут абстрагированы от других сервисов. Это также хорошо согласуется с доменно-ориентированным дизайном (DDD), где события домена могут запускать команды в различных микросервисах.

потенциальные ловушки

Хотя CQRS предлагает множество преимуществ, он также сталкивается с проблемами:

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

CQRS и микросервисы Spring

Экосистема Spring имеет богатый набор инструментов и платформ, которые идеально подходят для реализации шаблона CQRS в среде микросервисов.

Настройка Spring Boot

Первым шагом является настройка базового проекта Spring Boot. Если вы новичок в Spring Boot, вы можете легко инициализировать свой проект с помощью Spring Initializr. Базовые зависимости включают Spring Web, Spring Data JPA и любой коннектор базы данных, который вам нравится.

Команды, обработчики команд и агрегаты

В системе CQRS на основе Spring команды представляют собой намерение изменить какое-то состояние, а обработчики команд обрабатывают эти команды.

Пример команды:

Язык кода:javascript
копировать
public class CreateUserCommand {
    private final String userId;
    private final String username;

    // Constructor, getters, and other methods...
}

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

Язык кода:javascript
копировать
@Service
public class CreateUserCommandHandler implements CommandHandler<CreateUserCommand> {
    
    @Autowired
    private UserRepository userRepository;

    @Override
    public void handle(CreateUserCommand command) {
        User user = new User(command.getUserId(), command.getUsername());
        userRepository.save(user);
    }
}

В контексте доменно-ориентированного проектирования (DDD) изменения состояния обычно происходят в агрегатах. Эти агрегаты гарантируют, что все правила домена будут соблюдены, прежде чем любые изменения будут сохранены.

Запросы и обработчики запросов

Аналогично, запросы представляют собой запросы на чтение некоторого состояния, а обработчики запросов обрабатывают эти запросы.

Пример запроса:

Язык кода:javascript
копировать
public class GetUserByIdQuery {
    private final String userId;

    // Constructor, getters, and other methods...
}

Соответствующий обработчик запроса:

Язык кода:javascript
копировать
@Service
public class GetUserByIdQueryHandler implements QueryHandler<GetUserByIdQuery, User> {
    
    @Autowired
    private UserRepository userRepository;

    @Override
    public User handle(GetUserByIdQuery query) {
        return userRepository.findById(query.getUserId()).orElse(null);
    }
}

Интеграция источников событий с платформой Axon

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

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

Асинхронная связь с Apache Kafka

Учитывая распределенный характер микросервисов, часто бывает полезно реализовать асинхронную связь между сервисами. Apache Kafka можно интегрировать в экосистему Spring, чтобы создать мощную событийно-ориентированную архитектуру, которая особенно полезна при настройке CQRS.

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

Источник событий и CQRS

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

Природа источников событий

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

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

Преимущества организации мероприятий

  • Аудиторский след: событие Отслеживаемость обеспечивает естественный журнал аудита изменений. Это имеет решающее значение для прослеживаемости и исторических записей, а поле имеет решающее значение.
  • Временный запрос: Вы можете определить системусуществовать из статуса в любой момент времени. Это очень полезно для отладки и понимания прошлых состояний.
  • повтор события: по событию повтора,Вы можете восстановить представления, оптимизированные для чтения. Если вы хотите создать новую проекцию или восстановить поврежденную проекцию.,Это особенно полезно.

Интегрируйте источник событий с CQRS

CQRS и источник событий дополняют друг друга следующим образом:

  • Развязка: Поскольку команда и запрос существуют CQRS То же, что развязка,Источник по событию,событие (имеется в виду изменение состояния) и фактическое отделение состояния. Это способствует созданию слабосвязанной архитектуры.
  • Масштабируемость: изолированный характер чтения и записи CQRS идеально подходит для системы драйверов событий. Модель команд обрабатывает команды и генерирует события, а модель запросов обрабатывает запросы и может обновляться путем прослушивания этих событий.
  • случайно: через возможность воспроизвести событиеиз,Могут восстанавливать состояние системы при возникновении сбоя,Можно даже мигрировать на новую изсистему.

Реализовано с использованием фреймворков Spring и Axon.

Как упоминалось ранее, платформа Axon обеспечивает простой способ реализации CQRS и источников событий в приложениях Spring:

Агрегации и обработка событий. В Axon агрегаты отвечают за обработку команд и генерацию событий. После обработки команд они применяют события, вызывающие изменения состояния.

Язык кода:javascript
копировать
@Aggregate
public class Account {
    @AggregateIdentifier
    private String accountId;
    private int balance;

    @CommandHandler
    public void handle(WithdrawMoneyCommand cmd) {
        if (cmd.getAmount() > balance) {
            throw new InsufficientFundsException();
        }
        apply(new MoneyWithdrawnEvent(cmd.getAccountId(), cmd.getAmount()));
    }

    @EventSourcingHandler
    public void on(MoneyWithdrawnEvent evt) {
        this.balance -= evt.getAmount();
    }
}

Хранение событий: Axon предоставляет механизм хранения и извлечения событий. Эти события можно воспроизвести, чтобы восстановить состояние агрегата.

Проекции: Проекции в Axon обеспечивают сторону запросов CQRS. Они прослушивают события и обновляют оптимизированные для чтения представления. Таким образом, ваша модель запроса всегда обновляется с учетом последних изменений.

Проблемы и соображения

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

накладные расходы на сложность

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

Кривая обучения: для команд, впервые знакомых с этими режимами, предусмотрен этап обучения. Концептуальный переход от традиционных систем на основе CRUD может оказаться сложной задачей.

согласованность данных

Окончательная согласованность. Учитывая изолированный характер моделей команд и запросов, немедленной согласованностью часто жертвуют ради окончательной согласованности. Это означает, что может пройти задержка, прежде чем изменения, сделанные на стороне команды, отразятся на стороне запроса.

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

Управление версиями событий

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

  • Несответствие решения: Работа с разными версиями одного и того же типа событий может оказаться сложной.
  • eventUpgrade: По мере развития событийиз,система должна иметь возможность обновлять старое событие до новой версии,Без изменения хранилища изсобытие.

Хранение и воспроизведение данных

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

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

Интеграция с другими системами

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

определять границы

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

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

Инструменты и инфраструктура

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

в заключение

CQRS предоставляет уникальный способ масштабирования и организации микросервисов. В сочетании с экосистемой Spring он предоставляет мощный набор инструментов для создания надежных, масштабируемых и удобных в обслуживании систем. Однако, как и в случае со всеми архитектурными решениями, вам необходимо взвесить все «за» и «против» и убедиться, что оно подходит для вашего конкретного случая использования.

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.