Cloud Architecture - Command Query Responsibility Segregation (Part 1)
content derives from an internal talk at Microsoft that Ricardo and I
gave in February of 2012. The purpose of the talk was to reveal our
discoveries in the field with respect to what real customers are doing
when building cloud architectures. |
Ricardo’s blog can be found here: http://blog.ricardovillalobos.com/
We discovered something interesting. Several ISVs were using slight variations of the same pattern.
When we considered the benefits and why these ISVs were using these architectures, the reasoning became apparent. Ricardo and I were immediately drawn to this pattern.
We will explain the architecture in the context of Windows Azure. But this isn’t a requirement. The techniques and approaches we discuss are applicable to any cloud vendor. The architectures presented even work for private cloud or on-premise scenarios as well.
|Objectives for the next several posts|
We believe the patterns we are seeing today represent a natural evolution. The techniques illustrated have been in practice for decades. What makes these approaches really practical today is that there is direct support for the low-level frameworks in Windows Azure directly. Worker roles, web roles, Windows Azure Queues, Service Bus Queues, scalable and fast storage are available out of the box to jump start the major pillars of the needed architecture.
|What you can expect to walk away with|
As with anything we learn, there is a vocabulary, a set of terms that you need to “talk the talk.”
A large part of this post is discussing CQRS. We will defer that until later. Let’s talk a little bit about event sourcing and domain driven methodologies.
What we find kind of interesting is that the technology of CQRS is often discussed alongside the concept of Event Sourcing and Domain Driven Design approaches.
For example, the concept of Event Sourcing is not formally a part of CQRS. But time and time again, almost universally, all ISVs seemed to implement Event Sourcing. And we’ve seen some ISVs depend on an event sourcing as the only valid store of important business data.
Domain Driven Design
Regarding Domain-Driven design approaches, Ricardo and I still debate whether they are an essential ingredient to CQRS. Most developers agree that the domain and domain logic is the primary focus of architecture. In Domain Drive Design approaches there are one or more team members that are experts in a specific sphere of knowledge, influence, or activity. They are the domain experts that develop and define a system of abstractions that help solve problems in the domain.
The outcome of theses posts is pretty simple.
Ricardo and I want to show architectures that include CQRS. The goal of the architectures is to be able to scale and to focus on providing the fastest possible support for client applications.
|The Pre-Cloud and Post Cloud World|
|Unless you’ve been living in a cave for the last few years, you have seen this general tendency for asynchronous patterns and loosely coupled architectures.
Of course these goals have always been at the forefront of developer
minds. But we believe that the growth of cloud computing has brought
asynchronous, loosely coupled application architectures to an even
higher level of importance. |
Asynchronous techniques are needed because input/output operations are normally slower that other processing operations. Typically, the client application will need to wait for a particular I/O routine to completed. Finding a way to
Asynchronous Techniques - Optimizing Compute and IO Bound Programming
If you look at the way Windows 8 applications will be developed, an asynchronous approach to writing code will be a requirement. End users expect a lot from their software today. They want to be able to use web based applications which run in a disconnected fashion, but also want highly responsive experiences.
Write and Read operations are parallelized in CQRS
As we dive deeper into CQRS, you’ll see that read and write operations are fully de-coupled, supporting asynchronous reads and writes.
|I give Ricardo credit for coining the term horizontal de-coupling. |
Later, we will talk about vertical de-coupling. Vertical de-coupling typically involves a separating read operations from write operations. More on that later.
DTOs, or data transfer objects has been a common approach to de-coupling the service layer from the presentation layer.
A DTO is simple container for a set of aggregated data that needs to be transferred across a process or network boundary. Some developers use the Assembler pattern [Fowler], which creates DTOs from business objects and vice versa. This pattern is a specialized instance of the Mapper pattern and lets you convert between your domain objects and the data being serialized across the network.
Closer to storage, ORMs have been a popular approach to de-coupling the business data layer from the actual physical database or storage type. ORMs often introduce a little bit of performance overhead. They often implement their own caching mechanism to somewhat make up for extra latency they introduce.
|Your typical cloud architecture|
This is typically are plain vanilla and cloud based architecture. It works pretty well for most cases and does lend itself to some degree of scaling.
Keeping the presentation layer from being too chatty with the service layer, we typically employ some sort of the session state as a caching service to the presentation layer, so that it does not have to go back to the service layer every time a user takes an action.
What is interesting about the middle green boxes is that we are combining three layers into one web role or worker role. The three layers we are talking about are the service, business, and data layers.
The key point here is that all write and read operations happen on the same worker or web instance/role up in the cloud, limiting scale.
Data synchronization issues often come about as read and write operations conflict about blocking strategies. This normally results in slower reads for client applications.
In short, the architecture below does not attempt to optimize read operations as a separate scalable activity.
|Why we need new patterns – The next post|
Stay tuned for the next post…
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)