Избавьтесь от сложного кода: 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
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose