+ All Categories
Home > Technology > Building a Distributed Application Using CQRS Principles

Building a Distributed Application Using CQRS Principles

Date post: 06-May-2015
Category:
Upload: resources-global-professionals
View: 885 times
Download: 1 times
Share this document with a friend
Description:
Whether you're building a new application from scratch or enhancing an existing one with new functionality, being able to scale is very important to the life of your application. While some may say that you should just throw more hardware at the problem, designing your system up front properly will save you a number of headaches down the road. Command Query Responsibility Segregation (CQRS) is a pattern that helps you design your system to scale over time by taking messaging and applying it to commands your application issues and events that it raises. We'll see a very simple message distribution system and see how applying CQRS along with some event-driven concepts can help your application grow and scale over time. (Presented at the Rockville, MD .NET User Group on 12/11/2013.)
41
Building Distributed Applications Using CQRS Principals David Hoerster
Transcript
Page 1: Building a Distributed Application Using CQRS Principles

Building DistributedApplications Using CQRS

Principals

David Hoerster

Page 2: Building a Distributed Application Using CQRS Principles

About MeC# MVP (Since April 2011)Sr. Director of Web Solutions at RGPConference Director for Pittsburgh TechFestCo-Founder of BrainCredits (braincredits.com)Member of Advisory Board for Microsoft’s p&p CQRS GuidancePast President of Pittsburgh .NET Users Group and organizer of recent Pittsburgh Code Camps and other Tech EventsTwitter - @DavidHoersterBlog – http://geekswithblogs.net/DavidHoersterEmail – [email protected]

Page 3: Building a Distributed Application Using CQRS Principles

Application EvolutionI have an application that reads and writes informationIt has user authentication/authorization servicesIt has search services

Right now, it’s monolithic

I want to make it more distributed. Why?Performance / ScalabilityMaintenenaceExtensibility

Page 4: Building a Distributed Application Using CQRS Principles

What is a Distributed Application?

A system that uses multiple processes to run as a single unit

ServicesPhysical MachinesThe “Cloud”

Search is to be a distributed element of our applicationCreepers

DuplicationComplexity

Page 5: Building a Distributed Application Using CQRS Principles

Application Evolution

Client Black Box System

Data Store

SearchingBusiness

Logic

User Services

Page 6: Building a Distributed Application Using CQRS Principles

Application Evolution

Client Application System Data Store

SearchingBusiness

Logic

User Services

Page 7: Building a Distributed Application Using CQRS Principles

Application Evolution

Client Application System Data Store

Searching

Business Logic

User Services

Reposi

tory

Page 8: Building a Distributed Application Using CQRS Principles

Application Evolution

Client

Application System

Data Store

Searching

Business Logic

User Services

Reposi

tory

Repository

Page 9: Building a Distributed Application Using CQRS Principles

Application Evolution

ClientApplication

SystemData Store

Searching

Business Logic

User Services

Repository

Repository

Repository

Page 10: Building a Distributed Application Using CQRS Principles

Building a Distributed Application

Not separating pieces allows similar functionality to bleed through layers

Business logic duplicatedValidation logic duplicatedWET (anti-DRY) behavior

Clipboard Inheritance or Copy and Paste Development

Page 11: Building a Distributed Application Using CQRS Principles

Building a Distributed Application

Page 12: Building a Distributed Application Using CQRS Principles

DDD to the Rescue?Domain Driven Design (DDD)Provides foundation for building distributed applicationsClearly define roles and boundariesSRP is embracedConcepts involved:

Domains (Aggregate Roots)Entities and Value ObjectsBounded Contexts

Page 13: Building a Distributed Application Using CQRS Principles

Application Evolution (Reminder)

ClientApplication

SystemData Store

Searching

Business Logic

User Services

AppRepo

UserRepo

SearchRepo

Page 14: Building a Distributed Application Using CQRS Principles

Application Evolution

ClientApplication

SystemData Store

Searching

Business Logic

User Services

AppRepo

UserRepo

SearchRepo

Search Store

Bounded Context

Page 15: Building a Distributed Application Using CQRS Principles

Application StatusBreaking out parts into smaller componentsStill some duplicationComplexity

How is search store builtMoving data to search store (triggers? .NET functions?)

DependencyOverall flow of data

Repos probably have all CRUD operationsBusiness logic handles all CRUDTwo way traffic throughout

Page 16: Building a Distributed Application Using CQRS Principles

Application StatusTwo way traffic isn’t badBUT…

Page 17: Building a Distributed Application Using CQRS Principles

Potential Application Evolution

Client

Application System

Data Store

Search Svc

Business Logic

User Services

AppRepo

UserRepo

SearchRepo

Search Store

Search

QueueHandler

WritesReads

Bounded Context

Page 18: Building a Distributed Application Using CQRS Principles

Application BreakoutSearch is now practically standaloneEntry points for querying and writing

Writing to search repository is a messageQuerying is a service call or direct invocation

In theory, search is self-contained and can be distributedHow to best model this interaction?CQRS could be a solution

Page 19: Building a Distributed Application Using CQRS Principles

What is CQRS?CommandQueryResponsibilitySegregation

Is it a pattern or an architecture?

Page 20: Building a Distributed Application Using CQRS Principles

What is CQRS?

Command Query Responsibility SegregationBased upon Bertrand Meyer’s Command Query Separation (CQS) principle:

“every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer” (Meyer)

In essence, commands return acknowledgement; queries return data.

Page 21: Building a Distributed Application Using CQRS Principles

What is CQRS?Taking this further, CQRS describes a system where

Commands are messagesQueries go against a read model

Since commands are returning void, it allows for the message to be transformed into the read modelThis flips the conventional wisdom of fast writes and slow reads

Page 22: Building a Distributed Application Using CQRS Principles

What is CQRS?

CQRS essentially splits your application into two parts

The Read SideThe Command Side

Read Side = requests dataCommand Side = issues commands

Page 23: Building a Distributed Application Using CQRS Principles

What is CQRS?Common Architecture Issues

Business Logic Bleeds Through LayersValidation Logic Ends Up EverywhereCopy and Paste DevelopmentApps That Cater To Modification OperationsLeads To General Complexity Between Tiers

CQRS Simplifies This With Classes Performing Specific Duties (SRP)

Page 24: Building a Distributed Application Using CQRS Principles

The Why And When

Why?Your system is task-basedWant to cleanly separate commands and queriesDifferent teams? Different skill levels?

When?Not just a CRUD appDiscrete service/system that needs isolated, or can

be reused

The potential for eventual consistency is OK

Page 25: Building a Distributed Application Using CQRS Principles

Application Evolution

ClientApplication

SystemData Store

Search Req’s

Business Logic

User Services

AppRepo

UserRepo

SearchRepo

Search Store

Search

Queue

Cmd Handler

Writes

Reads

Bounded Context

Cmd

Search Domain

and Events

Page 26: Building a Distributed Application Using CQRS Principles

What is CQRS?Client

Read Store

Write Store

Repository / Read Model

Command

Command Handler

Domain

Event(s)Event

Handler(s)

Read Model

Page 27: Building a Distributed Application Using CQRS Principles

CQRS Pieces

CommandTells the system you want to do somethingImperative tense

public class CreatePlayer : CommandBase { public Int32 LahmanId { get; set; } public String PlayerId { get; set; } public String FirstName { get; set; } public String LastName { get; set; } public String NickName { get; set; } public String College { get; set; } public String Bats { get; set; } public String Throws { get; set; } public Int32 Height { get; set; } public Int32 Weight { get; set; } public DateTime? Debut { get; set; } public DateTime? FinalGame { get; set; } }

Page 28: Building a Distributed Application Using CQRS Principles

CQRS Pieces

Command HandlersHandles commandsRoutes to the appropriate DomainPrepares the DomainOne command maps to one domain

Page 29: Building a Distributed Application Using CQRS Principles

CQRS Pieces

DomainYour “business logic” componentBusiness rulesCan populate itselfPersists itselfTies in well with Event Sourcing with event replays

Page 30: Building a Distributed Application Using CQRS Principles

CQRS Pieces

EventsGenerally raised by domainSays that something happenedPast tenseMore than one event can be raised by a domain method

public class PlayerCreated : EventBase { public String FullName { get; set; } public String PlayerId { get; set; } }

Page 31: Building a Distributed Application Using CQRS Principles

CQRS Pieces

Event HandlersHandles events raised by the domainCan persist to a read model, send an email, submit other commands, etc.More than one event handler can be mapped to an event

public class PlayerHandler : IHandle<PlayerCreated>, IHandle<PlayerYearAdded> { public void Handle(PlayerCreated theEvent) { //do something }

public void Handle(PlayerYearAdded theEvent) { //do something else } }

Page 32: Building a Distributed Application Using CQRS Principles

BenefitsMove towards SRPComplexity Within Goes DownMaintenance Can Be EasierReduction in Hidden IntentIsolation of Application Parts (Resiliency)

PotentialsIncorporating Event Sourcing

Projecting to Denormalized Views

Page 33: Building a Distributed Application Using CQRS Principles

DrawbacksMore classesPotentially more projectsLearning curve when initially exposedGoes against majority think

MisconceptionsEverything is asyncEventual consistency is badEntire application must use this

Page 34: Building a Distributed Application Using CQRS Principles

Projecting to Denormalized View• Get all of the orders

for user “David” in last 30 days

Customer (SalesLT)CustomerID

NameStyle

Title

FirstName

MiddleName

LastName

Suffix

CompanyName

SalesPerson

EmailAddress

Product (SalesLT)ProductID

Name

ProductNumber

Color

StandardCost

ListPrice

Size

Weight

ProductCategoryID

ProductModelID

SellStartDate

SellEndDate

ProductCategory (SalesLT)ProductCategoryID

ParentProductCategoryID

Name

rowguid

ModifiedDate

ProductModel (SalesLT)ProductModelID

Name

CatalogDescription

rowguid

ModifiedDate

SalesOrderDetail (SalesLT)SalesOrderID

SalesOrderDetailID

OrderQty

ProductID

UnitPrice

UnitPriceDiscount

LineTotal

rowguid

ModifiedDate

SalesOrderHeader (SalesLT)SalesOrderID

RevisionNumber

OrderDate

DueDate

ShipDate

Status

OnlineOrderFlag

SalesOrderNumber

PurchaseOrderNumber

AccountNumber

CustomerID

ShipToAddressID

BillToAddressID

ShipMethod

CreditCardApprovalCode

SubTotal

TaxAmt

Freight

Page 35: Building a Distributed Application Using CQRS Principles

Projecting to Denormalized View

Get all the orders for user ‘David’ in last 30 days

SELECT c.FirstName, c.MiddleName, c.LastName, soh.SalesOrderID, soh.OrderDate, sod.UnitPrice, sod.OrderQty, sod.LineTotal, p.Name as 'ProductName', p.Color, p.ProductNumber, pm.Name as 'ProductModel', pc.Name as 'ProductCategory', pcParent.Name as 'ProductParentCategory'FROM SalesLT.Customer c INNER JOIN SalesLT.SalesOrderHeader soh

ON c.CustomerID = soh.CustomerIDINNER JOIN SalesLT.SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderIDINNER JOIN SalesLT.Product p ON sod.ProductID = p.ProductIDINNER JOIN SalesLT.ProductModel pm ON p.ProductModelID = pm.ProductModelIDINNER JOIN SalesLT.ProductCategory pc ON p.ProductCategoryID = pc.ProductCategoryIDINNER JOIN SalesLT.ProductCategory pcParent ON pc.ParentProductCategoryID = pcParent.ProductCategoryID

WHERE c.FirstName = 'David'AND soh.OrderDate > (GETDATE()-30)

Page 36: Building a Distributed Application Using CQRS Principles

Projecting to Denormalized View

Wouldn’t it be great if it were something like this?

SELECT FirstName, MiddleName, LastName, SalesOrderID, OrderDate, UnitPrice, OrderQty, LineTotal, ProductName, Color, ProductNumber, ProductModel, ProductCategory, ProductParentCategoryFROM CustomerSalesWHERE FirstName = 'David'

AND OrderDate > (GETDATE()-30)

Page 37: Building a Distributed Application Using CQRS Principles

How CQRS Can Help Traditional Architecutre

Many apps cater to modification operationsReads sufferWhat would make querying faster?

Business logic and domain objects bleed through layers as a result, too.

Validation logic may end being in multiple placesThe evil of cut-and-paste development

General complexity within tiers

Page 38: Building a Distributed Application Using CQRS Principles

Demo App Architecture

ClientWeb

Server (Nancy)

Solr Service

MongoDB

MSMQ

Cmd

Command

HandlerDomain

Event Handler

Event

Repository

(SolrNet)

Cmd

Page 39: Building a Distributed Application Using CQRS Principles

DemoLooking at CQRS with Search

Page 40: Building a Distributed Application Using CQRS Principles

ResourcesConference Reservation Example on GitHub https://github.com/DavidHoerster/Conference

CQRS Journey – https://github.com/mspnp/cqrs-journey-docCQRS Info Site – http://cqrs.wordpress.com/DDD/CQRS Google Group - http://groups.google.com/group/dddcqrs

Udi Dahan’s CQRS article “Clarified CQRS” – http://www.udidahan.com/2009/12/09/clarified-cqrs/

Rinat Abdullin’s CQRS information – http://abdullin.com/cqrsDistributed Podcast - http://distributedpodcast.com/

Page 41: Building a Distributed Application Using CQRS Principles

What is CQRS?Client

Read Model Store

Event Store

Repository Command Service

Domain (ARs)

Denormalizer

Event Handler

Command Issued – ack/nackData Requested/Returned

Command SideQuery Side


Recommended