Developing event-driven microservices with event sourcing and CQRS (london Java community)
Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)
-
Upload
chris-richardson -
Category
Software
-
view
37.366 -
download
9
Transcript of Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)
![Page 1: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/1.jpg)
@crichardson
Developing event-driven microservices with event
sourcing and CQRSChris Richardson
Author of POJOs in Action Founder of the original CloudFoundry.com
@crichardson [email protected] http://plainoldobjects.com http://microservices.io
![Page 2: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/2.jpg)
@crichardson
Presentation goal
Show how Event Sourcing and Command Query Responsibility Segregation
(CQRS) are a great way to implement microservices
![Page 3: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/3.jpg)
@crichardson
About Chris
![Page 4: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/4.jpg)
@crichardson
About Chris
Consultant and trainer focusing on microservices (http://www.chrisrichardson.net/)
![Page 5: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/5.jpg)
@crichardson
About Chris
Founder of a startup that is creating a platform that makes it easy for
application developers write microservices
(http://bit.ly/trialeventuate)
![Page 6: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/6.jpg)
@crichardson
For more information
https://github.com/cer/event-sourcing-examples
http://microservices.io
http://plainoldobjects.com/
https://twitter.com/crichardson
http://eventuate.io/
![Page 7: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/7.jpg)
@crichardson
Agenda
Why event sourcing?
Overview of event sourcing
ACID-free design
Designing a domain model based on event sourcing
Implementing queries in an event sourced application
Event sourcing and microservices
![Page 8: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/8.jpg)
@crichardson
Tomcat
Traditional monolithic architecture
Browser/Client
WAR/EAR
RDBMS
…
Customers
Orders
StoreFront UI
develop test
deploy
Simple to
Load balancer
scale
Spring MVC
Spring Hibernate
HTML
REST/JSON
ACID
Shopping cart
![Page 9: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/9.jpg)
@crichardson
But that leads* to monolithic hell
For large and/or complex applications…
![Page 10: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/10.jpg)
@crichardson
Today: use a microservice, polyglot architecture
Shopping UI
Orders Service Customer Service
Order Database Customer Database
Standalone services
Sharded SQLNoSQL DB
![Page 11: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/11.jpg)
@crichardson
But now we have distributed data management
problems
![Page 12: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/12.jpg)
@crichardson
Example: placing an order
Order Service Customer Service
Order Database
Customer Database
Order #1 Customer #1
No 2PC
No ACID
NoSQL SQL
![Page 13: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/13.jpg)
@crichardson
Customer management
How to maintain invariants?
Order management
Order Service
placeOrder()
Customer Service
updateCreditLimit()
Customer
creditLimit ...
has ordersbelongs toOrder
total
Invariant: sum(open order.total) <= customer.creditLimit
?
![Page 14: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/14.jpg)
@crichardson
Use an event-driven architecture….
http://www.merriam-webster.com/dictionary/event
![Page 15: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/15.jpg)
@crichardson
….Use an event-driven architecture
Services publish events when something important happens, e.g. state changes
Services subscribe to events and update their state
Maintain eventual consistency across multiple aggregates (in multiple datastores)
Synchronize replicated data
![Page 16: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/16.jpg)
@crichardson
Order ManagementOrder
id : 4567 total: 343 state = CREATED
Customer Management
Customer creditLimit : 12000 creditReservations: {}
Customer creditLimit : 12000 creditReservations: { 4567 -> 343}
Order id : 4567 total: 343 state = OPEN
Eventually consistent credit checking
Message Bus
createOrder()
Publishes:Subscribes to:
Subscribes to:
publishes:
OrderCreatedEvent
CreditReservedEvent
OrderCreatedEvent CreditReservedEvent
![Page 17: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/17.jpg)
@crichardson
Now there are two problems to solve….
![Page 18: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/18.jpg)
@crichardson
Problem #1: How to design eventually consistent business logic?
More on that later….
![Page 19: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/19.jpg)
@crichardson
Problem #2: How atomicity update database and publish an event
Order Service
Order Database
Message Broker
insert Order
publish OrderCreatedEvent
dual write problem
?
![Page 20: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/20.jpg)
@crichardson
Update and publish using 2PC
Guaranteed atomicity BUT
Need a distributed transaction manager
Database and message broker must support 2PC
Impacts reliability
Not fashionable
2PC is best avoided
![Page 21: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/21.jpg)
@crichardson
Transaction log tailingHow:
Read the database “transaction log” = single source of truth
Publish events to message broker
LinkedIn databus https://github.com/linkedin/databus
Supports Oracle and MySQL
Publish as events
AWS DynamoDB streams
Ordered sequence of creates, updates, deletes made to a DynamoDB table
Last 24 hours
Subscribe to get changes
MongoDB
Read the oplog
![Page 22: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/22.jpg)
Transaction log tailing: benefits and drawbacks
Benefits
No 2PC
No application changes required
Guaranteed to be accurate
Drawbacks
Immature
Database specific solutions
Low-level DB changes rather business level events = need to reverse engineer domain events
![Page 23: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/23.jpg)
@crichardson
Use database triggers
Track changes to tables
Insert events into an event table
Use datastore as a message queue
Pull events from event table and write to message broker
![Page 24: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/24.jpg)
Database triggers: benefits and drawbacks
Benefits
No 2PC
No application changes required
Drawbacks
Requires the database to support them
Database specific solutions
Low-level DB changes rather business level events = need to reverse engineer domain events
Error-prone, e.g. missing trigger
![Page 25: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/25.jpg)
@crichardson
Application created events
Use datastore as a message queue
Txn #1: Update database: new entity state & event
Txn #2: Consume event
Txn #3: Mark event as consumed
Eventually consistent mechanism (used by eBay)
See BASE: An Acid Alternative, http://bit.ly/ebaybase
![Page 26: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/26.jpg)
Application created eventsBenefits
High-level domain events
No 2PC
Drawbacks
Requires changes to the application
Only works for SQL and some NoSQL databases
Error-prone
![Page 27: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/27.jpg)
@crichardson
Agenda
Why event sourcing?
Overview of event sourcing
ACID-free design
Designing a domain model based on event sourcing
Implementing queries in an event sourced application
Event sourcing and microservices
![Page 28: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/28.jpg)
@crichardson
Just publish events
Application
Database
Message Broker
update
publish
X
![Page 29: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/29.jpg)
@crichardson
Event sourcingFor each aggregate (business entity):
Identify (state-changing) domain events
Define Event classes
For example,
ShoppingCart: ItemAddedEvent, ItemRemovedEvent, OrderPlacedEvent
Order: OrderCreated, OrderCancelled, OrderApproved, OrderRejected, OrderShipped
![Page 30: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/30.jpg)
@crichardson
Persists events NOT current state
Order
status ….
Event table
101 ACCEPTED
Order tableXOrderCreated101 901 …
OrderApproved101 902 …
OrderShipped101 903 …
![Page 31: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/31.jpg)
@crichardson
Replay events to recreate state
Order
state
OrderCreated(…) OrderAccepted(…) OrderShipped(…)
Events
Periodically snapshot to avoid loading all events
![Page 32: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/32.jpg)
@crichardson
The present is a fold over history
currentState = foldl(applyEvent, initialState, events)
![Page 33: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/33.jpg)
@crichardson
Event
Aggregates: Command ⇒ Events
AggregateCommand Event
![Page 34: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/34.jpg)
@crichardson
Aggregates: Event ⇒ Updated aggregate
AggregateEvent Aggregate’
![Page 35: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/35.jpg)
@crichardson
Request handling in an event-sourced application
HTTP Handler
Event Store
pastEvents = findEvents(entityId)
Order
new()
applyEvents(pastEvents)
newEvents = processCmd(SomeCmd)
saveEvents(newEvents)
Microservice A
(optimistic locking)
![Page 36: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/36.jpg)
@crichardson
Event Store publishes events - consumed by other services
Event Store
Event Subscriber
subscribe(EventTypes)
publish(event)
publish(event)
Aggregate
CQRS View
update()
update()
Microservice B
send notifications
…
![Page 37: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/37.jpg)
Event store = database + message broker
Hybrid database and message broker
Implementations:
Home-grown/DIY
geteventstore.com by Greg Young
http://eventuate.io (mine)
Event Store
Save aggregate
events
Get aggregate
events
Subscribe to events
![Page 38: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/38.jpg)
@crichardson
Benefits of event sourcingSolves data consistency issues in a Microservice/NoSQL-based architecture
Reliable event publishing: publishes events needed by predictive analytics etc, user notifications,…
Eliminates O/R mapping problem (mostly)
Reifies state changes:
Built-in, reliable audit log,
temporal queries
Preserved history ⇒ More easily implement future requirements
![Page 39: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/39.jpg)
@crichardson
Drawbacks of event sourcing
Weird and unfamiliar
Events = a historical record of your bad design decisions
Handling duplicate events can be tricky
Application must handle eventually consistent data
Event store only directly supports PK-based lookup => use Command Query Responsibility Segregation (CQRS) to handle queries
![Page 40: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/40.jpg)
@crichardson
Agenda
Why event sourcing?
Overview of event sourcing
ACID-free design
Designing a domain model based on event sourcing
Implementing queries in an event sourced application
Event sourcing and microservices
![Page 41: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/41.jpg)
@crichardson
Implementing createOrder()
POST /orders
class OrderServiceImpl {
public Order createOrder() { … Creates Order … }
}
![Page 42: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/42.jpg)
@crichardson
Implement requirements and preserve invariants
As a customer I want to place an order So that I get the needed products
Given that my available credit is $1500 When I place a $250 order Then the order is created Then my available credit is $1250
Story
Scenario
Post conditions
Pre conditions
Given that my available credit is $1500 When I place a $2500 order Then the order is rejected Then my available credit is $1500
Scenario
Invariant: sum(open order.total) <= customer.creditLimit
![Page 43: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/43.jpg)
@crichardson
createOrder() updates multiple aggregates
Updates Customer aggregate’s available credit
Creates Order aggregate
Associates Order with Customer
![Page 44: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/44.jpg)
@crichardson
Old-style ACID…BEGIN TRANSACTION
… VERIFY CREDIT …
… CREATE ORDER…
COMMIT TRANSACTION
![Page 45: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/45.jpg)
@crichardson
… becomes eventually consistent (BASE)
Updating multiple aggregates
multi-step, event-driven flow
each step updates one Aggregate
Service creates saga to coordinate workflow
A state machine
Part of the domain, e.g. Order aggregate OR Synthetic aggregate
Post-conditions and invariants eventually become true
![Page 46: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/46.jpg)
@crichardson
Creating an order
Order
Customer
CreatedCredit reserved
public Order createOrder() { … Creates Order … }
Approved
![Page 47: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/47.jpg)
@crichardson
Need compensating transactions
Pre-conditions might be false when attempting to update an aggregate
Credit check fails ⇒ cancel order
Credit check succeeded but customer cancels order ⇒ undo credit reservation
…
![Page 48: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/48.jpg)
@crichardson
Agenda
Why event sourcing?
Overview of event sourcing
ACID-free design
Designing a domain model based on event sourcing
Implementing queries in an event sourced application
Event sourcing and microservices
![Page 49: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/49.jpg)
@crichardson
Use the familiar building blocks of DDD
Entity
Value object
Services
Repositories
Aggregates ⟸ essential
![Page 50: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/50.jpg)
Aggregate designGraph consisting of a root entity and one or more other entities and value objects
Each core business entity = Aggregate: e.g. customer, Account, Order, Product, ….
Reference other aggregate roots via primary key
Often contains partial copy of other aggregates’ data
Order
OrderLine Item
quantity productId productName productPrice
customerId
Address
street city …
![Page 51: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/51.jpg)
@crichardson
Partition the domain model into Aggregates
Order
OrderLine Item
quantity
…
Addressstreet city …
Customer
Productname price
![Page 52: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/52.jpg)
@crichardson
Transaction = processing one command by one aggregate
No opportunity to update multiple aggregates within a transaction
Aggregate granularity is important
If an update must be atomic (i.e. no compensating transaction) then it must be handled by a single aggregate
e.g. scanning boarding pass at security checkpoint or when entering jetway
![Page 53: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/53.jpg)
@crichardson
Aggregate granularity
Consistency Scalability/ User experience
Customer
Order
Product
Customer
Order
Product
Customer
Order
Product
![Page 54: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/54.jpg)
Designing domain eventsRecord state changes for an aggregate
Part of the public API of the domain model ProductAddedToCart
id : TimeUUID productId productName productPrice shoppingCartId
Required by aggregate
Enrichment: Required by by
consumers
![Page 55: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/55.jpg)
@crichardson
Example event
![Page 56: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/56.jpg)
@crichardson
Designing commandsCreated by a service from incoming request
Processed by an aggregate
Immutable
Contains value objects for
Validating request
Creating event
Auditing user activity
![Page 57: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/57.jpg)
@crichardson
Example command
![Page 58: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/58.jpg)
@crichardson
Hybrid OO/FP domain objects
![Page 59: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/59.jpg)
@crichardson
OO = State + Behavior
creditLimit creditReservations : Map[OrderId, Money]
Customer
List<Event> processCommand ( Command aCommand) { … }
void applyEvent (Event anEvent) { … }
State
Behavior
![Page 60: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/60.jpg)
@crichardson
Aggregate traits
Map Command to Events
Apply event returning updated Aggregate
Used by Event Store
to reconstitute aggregate
![Page 61: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/61.jpg)
@crichardson
ReflectiveMutableCommandProcessingAggregate
![Page 62: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/62.jpg)
@crichardson
Customer - command processing
![Page 63: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/63.jpg)
@crichardson
Customer - applying events
![Page 64: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/64.jpg)
@crichardson
Event Store APIT is a subclass of Aggregate[T]
Rx Observable = Future++
![Page 65: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/65.jpg)
@crichardson
Creating an order
save() concisely specifies: 1.Creates Customer aggregate 2.Processes command 3.Applies events 4.Persists events
![Page 66: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/66.jpg)
@crichardson
Event handling in Customers
1.Load Customer aggregate 2.Processes command 3.Applies events 4.Persists events
Triggers BeanPostProcessor Durable subscription name
![Page 67: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/67.jpg)
@crichardson
Agenda
Why event sourcing?
Overview of event sourcing
ACID-free design
Designing a domain model based on event sourcing
Implementing queries in an event sourced application
Event sourcing and microservices
![Page 68: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/68.jpg)
@crichardson
Let’s imagine you want to display a customer and their recent orders
![Page 69: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/69.jpg)
@crichardson
Need to ‘join’ customers and orders BUT
Event store only supports primary key lookup
![Page 70: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/70.jpg)
@crichardson
Use Command Query Responsibility Segregation
(CQRS)
![Page 71: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/71.jpg)
@crichardson
Command Query Responsibility Segregation (CQRS)
Command-side
Commands
Aggregate
Event Store
Events
Query-side
Queries
(Denormalized) View
Events
![Page 72: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/72.jpg)
@crichardson
Query-side design
Event Store
Updater
View Updater Service
Events
Reader
HTTP GET Request
View Query Service
View Store
e.g. MongoDB
Neo4J CloudSearch
update query
![Page 73: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/73.jpg)
@crichardson
Persisting a customer and order history in MongoDB
{ "_id" : "0000014f9a45004b-0a00270000000000", "_class" : "net.chrisrichardson…..views.orderhistory.CustomerView", "version" : NumberLong(5), "orders" : { "0000014f9a450063-0a00270000000000" : { "state" : "APPROVED", "orderId" : "0000014f9a450063-0a00270000000000", "orderTotal" : { "amount" : "1234" } }, "0000014f9a450063-0a00270000000001" : { "state" : "REJECTED", "orderId" : "0000014f9a450063-0a00270000000001", "orderTotal" : { "amount" : "3000" } } }, "name" : "Fred", "creditLimit" : { "amount" : "2000" } }
Denormalized = efficient lookup
![Page 74: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/74.jpg)
@crichardson
Persisting customers and order info using Spring Data for MongoDB...
![Page 75: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/75.jpg)
@crichardson
Persisting customers and order using Spring Data for MongoDB...
![Page 76: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/76.jpg)
Other kinds of viewsAWS Cloud Search
Text search as-a-Service
View updater batches aggregates to index
View query service does text search
AWS DynamoDB
NoSQL as-a-Service
On-demand scalable - specify desired read/write capacity
Document and key-value data models
Useful for denormalized, UI oriented views
![Page 77: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/77.jpg)
Benefits and drawbacks of CQRS
Benefits
Necessary in an event-sourced architecture
Separation of concerns = simpler command and query models
Supports multiple denormalized views
Improved scalability and performance
Drawbacks
Complexity
Potential code duplication
Replication lag/eventually consistent views
![Page 78: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/78.jpg)
@crichardson
Agenda
Why event sourcing?
Overview of event sourcing
ACID-free design
Designing a domain model based on event sourcing
Implementing queries in an event sourced application
Event sourcing and microservices
![Page 79: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/79.jpg)
@crichardson
Partitioning into microservices: Use Strategic DDD
![Page 80: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/80.jpg)
@crichardson
Strategic design: identify sub-domains and bounded contexts
Online store domain
![Page 81: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/81.jpg)
@crichardson
Strategic design: identify sub-domains and bounded contexts
Customer Management Order
ManagementCatalog
management …
![Page 82: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/82.jpg)
@crichardson
Bounded context = microservices
…
Customer management
domain model
Order management
domain model
Catalog management
domain model
…
domain model
Customer view
Command side Query side
![Page 83: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/83.jpg)
@crichardsonEvent Store
HTTP Request
HTTP Adapter
Event Handler
Cmd
Cmd
Events
Events
Xyz Adapter
Xyz Requestmicroservice
Aggregate
Service
Event Adapter
![Page 84: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/84.jpg)
@crichardson
Order Controller
![Page 85: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/85.jpg)
@crichardson
When to use microservices?In the beginning: •You don’t need it •It will slow you down
Later on: •You need it •Refactoring dependencies is painful
![Page 86: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/86.jpg)
@crichardson
Aggregates + Event Sourcing =
Modular domain model
![Page 87: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/87.jpg)
@crichardson
Modular domain model
Tightly coupled ACID
Loosely coupled aggregates Eventually consistent
Customer
Order
Product
Customer
Order
Product
![Page 88: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/88.jpg)
@crichardson
MonolithicFirst approach
Tomcat
WAR/EAR
Not entirely free though - Event Sourcing premium
Customer
Order
Product
![Page 89: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/89.jpg)
@crichardson
But no Big Ball of Mud to untangle
![Page 90: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/90.jpg)
@crichardson
Microservices deployment
Tomcat
WAR/EAR
Much higher - microservices premium
Customer
Tomcat
WAR/EAR
Order
Tomcat
WAR/EAR
Product
![Page 91: Developing event-driven microservices with event sourcing and CQRS (svcc, svcc2015)](https://reader034.fdocuments.us/reader034/viewer/2022042517/587085871a28ab57368b7849/html5/thumbnails/91.jpg)
@crichardson
Summary
Event sourcing solves key data consistency issues with:
Microservices
Partitioned SQL/NoSQL databases
Apply strategic DDD to identify microservices
Apply tactical DDD to design individual services
Use CQRS to implement materialized views for queries