Spring Insight vRealize Operations

Scaling in Complex Domains Using CQRS, Axon, and Spring Insight

If you build modern applications, you are constantly keeping abreast of helpful architecture patterns and ways to deal with scale, agility, performance, security, integration, and more.

In this post, we’d like to introduce you to the Command Query Responsibility Segregation (CQRS) pattern and explain how it allows your architecture to scale and perform in the face of complex domains. Then, we will talk about a specific CQRS framework called Axon and explain how you can use it with Spring Insight via the Spring Insight plugin architecture.

What is CQRS?

CQRS is a design pattern that essentially does away with the notion of a single shared domain model that’s used everywhere in an application. It introduces separate models for state-changing operations versus operations that only inspect the state of the system. These operations are respectively referred to as commands and queries and make up the acronym. The term was first coined by Greg Young, who’s a strong advocate of the pattern, and is based on Bertrand Meyer’s notion of Command Query Separation.

Greg found that the responsibilities involved with updating the state of a system (like validation), generating notifications, and persisting the changed state, tend to drive the design of a domain model in different ways than the responsibility to query that same system.

With systems that have a relatively low complexity and perform mostly CRUD operations, a single domain model is not usually a problem. However, as the complexity increases and more requirements arise for both update logic and the inquiries to be supported, differences tend to get in the way of efficiently supporting all the—sometimes competing—requirements.

For example, updates use a normalized, fine-grained model that can perform all necessary checks and triggers appropriate resulting actions to be taken. For querying, you might want to work with denormalized, pre-processed data that directly supports the relevant queries and doesn’t require all sorts of logic like joins and aggregations to extract what’s needed.

CQRS specifies one domain model that’s used to process commands (i.e. for updates) and one or more models that are used for queries. Each query model is specifically tailored to the informational needs for each piece of system functionality. This has several advantages, but also some important implications that we’ll explore here.

>> Get the Spring Insight plugin for Axon here

Applying the CQRS

How a system that uses CQRS works is roughly as follows:

  • state changes are initiated in the form of commands
  • these commands trigger changes to the domain model that’s used for updates, the so-called Command Model
  • this model is responsible for updating its state while guarding its consistency and triggering logic that’s involved with processing the changes contained in the command
  • changes to the Command Model are propagated to the Query Model(s)
  • clients of the Query Models will now see the effect of the updates as they query the system

Although propagating the Command Model changes to the Query Models can be done in different ways, it’s common to use an eventing mechanism here where the Query Models subscribe to events published by the Command Model. For small systems, this could be done synchronously. For larger systems, events are typically sent and handled asynchronously. An asynchronous approach allows the system to scale relatively easy, since the Command Model doesn’t need to wait for all Query Models to apply the changes. The approach also results in a delay between updates and the visibility of those changes and makes the system eventually consistent—a typical characteristic of a distributed system that needs to be available in the face of delays or errors in one of its parts.

CQRS doesn’t prescribe any details on how to sync the models, but, when asynchronous eventing is used, it is important to think about things like the durability of your events. When events get lost, or when a Query Model fails to update itself because of some external cause, you’ll end up with an eventually inconsistent system!

Fortunately there are decades of experience with building reliable systems through messaging, so make sure to keep the best practices in mind while architecting your system this way.

The Command Model could be persisted in a straightforward manner to something like a database of course, but CQRS lends itself quite well to the use of another pattern: Event Sourcing. With event sourcing, you store each and every event that is the result of applying a command and not just the current state of the model. The model is loaded by applying the stored events to an initial state (there exist lots of possible optimisations here).

One benefit of the approach is that, when new requirements arise (e.g. because there’s a need for an additional query model), you can simply replay all (or a relevant subset) of the stored events to populate that model. The event store also serves as an excellent audit log, where you can always retrace what resulted in the current state of the system.

CQRS Benefits

By applying the CQRS pattern to (parts of) your application, querying becomes straightforward. By design, the model that’s queried will directly support the needed view of the system’s information. Not only does this simplify the code, it also makes querying more efficient and allows read-only operations to be scaled independently of the rest of the application. The latter is especially the case with systems that asynchronously apply their state changes to the query models.

When event sourcing is used, you don’t even have to worry about having all your models complete when taking the system into production: by replaying events, you can always populate new models later on, opening up all sorts of possibilities including custom trend analysis.

Also, because of the strict separation between updates and queries, individual parts of the system can support different, non-functional requirements like availability, scalability, etc. As well, software development can also take a fundamentally different approach when updates are separate from queries—you can manage projects and development tasks differently. Here is a beautiful example of where CQRS can really benefit a development team over the lifecycle of an application—you build a CRUD-centric system in V01, then you add a complex notification model on top of it in V02, then you want a task-based GUI in V03, you add trend analysis in V04, you need to audit key events in V05, and you need real-time integration with another system in V06.

Introducing Axon Framework

Since CQRS is an architectural pattern, there is no such thing as a “CQRS Implementation.” However, using CQRS in practice does result in the use of specific components: 1) an Event Bus to transport events between components, 2) a Command Bus to dispatch commands to a Command Handler, and 3) an Event Store to store the events generated by the Command Model. By providing a decoupled architecture at the service/component level, it improves performance and scale, agility, security, integration, and more.

Axon Framework is a Java framework which provides implementations of these common building blocks, allowing developers to focus on the business logic. For example, Axon provides a number of Command Bus implementations, ranging from the in-process SimpleCommandBus to the DistributedCommandBus, which allows a cluster of machines to distribute commands among each other.

Very often, developers confuse the concept of “scalability” with the actual use of multiple machines to handle requests. In the Axon Framework, the difference between handling all logic in a single machine, and handling it on different machines, is a matter of configuration. The business logic code is not affected. This makes it easier to start small, keeping the ability to scale when required. This is made possible by keeping track of what data from the Command Model resides on what machine. Commands that target specific entities in the Command Model can therefore be routed directly to the corresponding machine.

Axon Insight Plugin

As a framework that operates at an infrastructure level, the operations that Axon performs as it handles the commands and events can provide a lot of insight into the application’s behavior.

In order to expose this information, a Spring Insight plugin was developed that does exactly this. Spring Insight can be used with any Java application. Spring Insight Developer and Spring Insight Operations are also part of the vFabric tc Server product. If you aren’t familiar, here is an explanation of what Spring Insight Developer can do to help you analyze code and a reference for how the plug-in based architecture works..

The Axon Spring Insight plugin adds a number of supported operations to Spring Insight to make it aware of the dispatching and handling of commands and events. With the plugin, developers can trace the flow of commands or events and monitor the performance of their handlers.

Initially developed as part of Axon Framework, this plugin has now been adopted by VMware as a community plugin, with the intent to bundle it with future Spring Insight releases. Here is another great reference on CQRS with Axon.

About the Author: Joris Kuipers is an Enterprise Java Consultant & Software engineer with 13 years of experience. His areas of expertise include but are not limited to everything Spring, Hibernate, messaging, transactions, IBM WebSphere and EJB. In april 2007, Joris started as Senior Consultant at Interface21 (now SpringSource, a VMware division), training Java developers in Spring and other Java EE technologies as well as providing technical consultancy.
About the Author: Allard Buijze is a Software Architect at Trifork (Founded as JTeam, formerly known as Orange11). In that role, he investigates different technologies and methodologies to find out how they can help us develop better code in less time. Allard’s specialties include Programming, Web application development, Portals, J2EE, Spring Framework, Web Services, Agile software development and Scrum.