developing event-driven microservices with event sourcing and cqrs (london java community)

61
@crichardson E vent-driven microservices with event sourcing and CQRS Chris Richardson Founder of Eventuate.io Founder of the original CloudFoundry.com Author of POJOs in Action @crichardson [email protected] http://eventuate.io

Upload: chris-richardson

Post on 12-Apr-2017

704 views

Category:

Software


5 download

TRANSCRIPT

Page 1: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Event-driven microservices with event sourcing and CQRS

Chris Richardson

Founder of Eventuate.io Founder of the original CloudFoundry.com Author of POJOs in Action

@crichardson [email protected] http://eventuate.io

Page 2: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@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 (london Java community)

@crichardson

About Chris

Page 4: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

About Chris

Consultant and trainer focusing on modern

application architectures including microservices

(http://www.chrisrichardson.net/)

Page 5: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

About Chris

Founder of a startup that is creating a platform that makes it easier for developers to write transactional

microservices (http://eventuate.io)

Page 6: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

For more information

http://learnmicroservices.io

Page 7: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Agenda

Monolith vs. microservices

Event-driven microservices

Overview of event sourcing

Implementing queries in an event sourced application

Page 8: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Let’s imagine you are building a large, complex application,

e.g. an online store

Page 9: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Successful software development

Architecture

Process OrganizationAgile Continuous delivery …

Small, autonomous, teams

Page 10: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

?Architecture

Page 11: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Page 12: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

The monolithic architecture

Tomcat

Browser

WAR

SQL database

HTML

REST/JSON

Client App

Simple to ….

Develop Test

Deploy Scale

Catalog Module

Reviews Module

Orders Module

StoreFront UI Module

Page 13: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

But successful

applications keep

growing ….

Page 14: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Monolithic architecture

Process OrganizationAgile Continuous delivery …

Small, autonomous, teams

Page 15: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Apply functional decomposition

X axis - horizontal duplication

Z axis

- data

partit

ioning

Y axis - functional

decomposition

Scale b

y split

ting s

imilar

thing

s

Scale by splitting

different things

Page 16: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Microservice architecture

Browser

Mobile Device

Store Front UI

API Gateway

Catalog Service

Review Service

Order Service

… Service

Catalog Database

Review Database

Order Database

… Database

HTML

REST

REST

REST

Page 17: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Microservice architecture

Process OrganizationAgile Continuous delivery …

Small, autonomous, teams✔ ✔

Page 18: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Drawbacks

Complexity

Page 19: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

DrawbacksComplexity of developing a distributed system

Implementing inter-process communication

Handling partial failures

Complexity of implementing business transactions that span multiple databases (without 2PC)

Complexity of testing a distributed system

Complexity of deploying and operating a distributed system

Managing the development and deployment of features that span multiple services

Fortunately solutions exists

Page 20: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

The benefits typically outweigh the drawbacks

for large, complex applications

Page 21: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Issues to address

How to deploy the services?

How do the services communicate?

How do clients of the application communicate with the services?

How to partition the system into services?

How to deal with distributed data management problems?

….

Page 22: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Agenda

Monolith vs. microservices

Event-driven microservices

Overview of event sourcing

Implementing queries in an event sourced application

Page 23: Developing event-driven microservices with event sourcing and CQRS (london Java community)

Data management patterns

Page 24: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

The Database

Shared database

Order Service Customer Service … Service

Order table Customer table …

orderTotal creditLimit

Tight coupling Simple and

ACID

Page 25: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Database per service

Order Service Customer Service

Order Database Customer Database

Order table Customer table

orderTotal creditLimit

Loose coupling 😀 but more complex 😓 and….

Page 26: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

2PC (aka. distributed transactions)

is not viable choice for most modern applications

Page 27: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Customer management

How to maintain data consistency without 2PC?

Order management

Order Service

placeOrder()

Customer Service

updateCreditLimit()

Customer

creditLimit ...

has ordersbelongs toOrder

total

Invariant: sum(open order.total) <= customer.creditLimit

?

Page 28: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Event-driven architecture

Page 29: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Use event-driven, eventually consistent order processing

Order Service

Customer Service

Order created

Credit Reserved

Credit Check Failed

Place Order

OR

Page 30: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

How atomically update database and publish an event

Order Service

Order Database

Message Broker

insert Order

publish OrderCreatedEvent

dual write problem

?

Page 31: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Failure = inconsistent system

Order Service

Order Database

Message Broker

insert Order

publish OrderCreatedEvent

X

Page 32: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

2PC is not an option

Page 33: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Reliably publish events when state changes

Page 34: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Agenda

Monolith vs. microservices

Event-driven microservices

Overview of event sourcing

Implementing queries in an event sourced application

Page 35: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Just publish events

Application

Database

Message Broker

update

publish

X

Page 36: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Event sourcingFor each domain object (i.e. DDD aggregate):

Identify (state changing) domain events, e.g. use Event Storming

Define Event classes

For example,

ShoppingCart: ItemAddedEvent, ItemRemovedEvent, OrderPlacedEvent

Order: OrderCreated, OrderCancelled, OrderApproved, OrderRejected, OrderShipped

Page 37: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Persists events NOT current state

Order

status ….

101 ACCEPTED

Order tableX

Page 38: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Persists events NOT current state

Event table

Entity type Event id

Entity id

Event data

Order 902101 …OrderApproved

Order 903101 …OrderShipped

Event type

Order 901101 …OrderCreated

Page 39: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Replay events to recreate state

Order

state

OrderCreated(…) OrderAccepted(…) OrderShipped(…)

Events

Periodically snapshot to avoid loading all events

Page 40: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

The present is a fold over history

currentState = foldl(applyEvent, initialState, events)

Page 41: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Familiar concepts restructured

class Customer {

public void reserveCredit( orderId : String, amount : Money) {

// verify

// update state this.xyz = … }

public List<Event> process( ReserveCreditCommand cmd) { // verify … return singletonList( new CreditReservedEvent(…); ) }

public void apply( CreditReservedEvent event) { // update state this.xyz = event.xyz }

Page 42: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Event

Aggregates: Command ⇒ Events

AggregateCommand Event

Page 43: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Aggregates: Event ⇒ Updated aggregate

AggregateEvent Updated Aggregate

Page 44: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Request handling in an event sourced application

HTTP Handler

Event Store

pastEvents = findEvents(entityId)

Order

new()

applyEvents(pastEvents)

newEvents = processCmd(someCmd)

saveEvents(newEvents) (optimistic locking)

Order Service

applyEvents(newEvents)

Page 45: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Event Store publishes events consumed by other services

Event Store

Event Subscriber

subscribe(EventTypes)

publish(event)

publish(event)

Customer

update()

Customer Service

Page 46: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Event Store publishes events consumed by other services

Event Store

Event Subscriber

subscribe(EventTypes)

publish(event)

publish(event)

CQRS View

update()

Service Xyz

send notifications

Page 47: Developing event-driven microservices with event sourcing and CQRS (london Java community)

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 48: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@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 49: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Drawbacks of event sourcingRequires application rewrite

Weird and unfamiliar style of programming

Events = a historical record of your bad design decisions

Must detect and ignore duplicate events

Idempotent event handlers

Track most recent event and ignore older ones

Querying the event store can be challenging

Some queries might be complex/inefficient, e.g. accounts with a balance > X

Event store might only support lookup of events by entity id

Must use Command Query Responsibility Segregation (CQRS) to handle queries ⇒ application must handle eventually consistent data

Page 50: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Agenda

Monolith vs. microservices

Event-driven microservices

Overview of event sourcing

Implementing queries in an event sourced application

Page 51: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Find recent, valuable customers

SELECT * FROM CUSTOMER c, ORDER o WHERE c.id = o.ID AND o.ORDER_TOTAL > 100000 AND o.STATE = 'SHIPPED' AND c.CREATION_DATE > ?

Customer Service

Order Service

What if event sourcing is

used?…. is no longer easy

Page 52: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Use Command Query Responsibility Segregation

(CQRS)

Page 53: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Command Query Responsibility Segregation (CQRS)

Application logic

Commands Queries

X

Page 54: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Command Query Responsibility Segregation (CQRS)

Command side

Commands

Aggregate

Event Store

Events

Query side

Queries

(Materialized) View

Events

Page 55: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Query side design

Event Store

Updater

View Updater Service

Events

Reader

HTTP GET Request

View Query Service

View Store

e.g. MongoDB

ElasticSearch Neo4J

update query

Page 56: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@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 57: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Persisting customers and order info using Spring Data for MongoDB...

Page 58: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Persisting customers and order using Spring Data for MongoDB...

Page 59: Developing event-driven microservices with event sourcing and CQRS (london Java community)

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 60: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

Summary

Use microservices to accelerate development

Use an event-driven architecture to maintain data consistency

Implement an event-driven architecture using event sourcing

Use CQRS to implement materialized views for queries

Page 61: Developing event-driven microservices with event sourcing and CQRS (london Java community)

@crichardson

@crichardson [email protected]

http://learnmicroservices.io

Questions?