SlideShare a Scribd company logo
1 of 65
Download to read offline
@crichardson 
Building microservices with 
Scala, functional domain 
models and Spring Boot 
Chris Richardson 
Author of POJOs in Action 
Founder of the original CloudFoundry.com 
@crichardson 
chris@chrisrichardson.net 
http://plainoldobjects.com
@crichardson 
Presentation goal 
Share my experiences with building an 
application using Scala, functional domain 
models, microservices, event sourcing, 
CQRS, and Spring Boot
@crichardson 
About Chris
@crichardson 
About Chris 
Founder of a buzzword compliant (stealthy, social, mobile, 
big data, machine learning, ...) startup 
Consultant helping organizations improve how they 
architect and deploy applications using cloud, micro 
services, polyglot applications, NoSQL, ...
@crichardson 
Agenda 
Why build event-driven microservices? 
Overview of event sourcing 
Designing microservices with event sourcing 
Implementing queries in an event sourced application 
Building and deploying microservices
@crichardson 
Let’s imagine that you are 
building a banking app...
@crichardson 
Domain model 
Account 
balance 
open(initialBalance) 
debit(amount) 
credit(amount) 
MoneyTransfer 
fromAccountId 
toAccountId 
amount
@crichardson 
Traditional application 
architecture 
BanBaknikningg UI 
Accounts 
Transfers 
Tomcat 
Browser/ 
Client 
WAR/EAR 
RDBMS 
Customers 
Simple to 
develop 
test 
deploy 
Load 
balancer 
scale 
Spring MVC 
Spring 
Hibernate 
... 
HTML 
REST/JSON
@crichardson 
Problem #1: monolithic 
architecture 
Intimidates developers 
Obstacle to frequent deployments 
Overloads your IDE and container 
Obstacle to scaling development 
Requires long-term commitment to a technology stack
Standalone 
services 
@crichardson 
Solution #1: use a microservice 
architecture 
Banking UI 
Account 
Management Service 
Transaction 
Management Service 
Account 
Database 
Transaction 
Database
@crichardson 
Problem #2: relational 
databases 
Scalability 
Distribution 
Schema updates 
O/R impedance mismatch 
Handling semi-structured data
@crichardson 
Solution #2: use NoSQL 
databases 
Avoids the limitations of RDBMS 
For example, 
text search ⇒ Solr/Cloud Search 
social (graph) data ⇒ Neo4J 
highly distributed/available database ⇒ Cassandra 
...
@crichardson 
Different modules use 
different databases 
IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg
But now we have problems 
with data consistency! 
@crichardson
Problem #3: Microservices = 
distributed data management 
@crichardson 
Each microservice has it’s own database 
Some data is replicated and must be kept in sync 
Business transactions must update data owned by 
multiple services 
Tricky to implement reliably without 2PC
Problem #4: NoSQL = 
ACID-free, denormalized databases 
Limited transactions, i.e. no ACID transactions 
Tricky to implement business transactions that update 
multiple rows, e.g. http://bit.ly/mongo2pc 
Limited querying capabilities 
Requires denormalized/materialized views that must be 
synchronized 
Multiple datastores (e.g. DynamoDB + Cloud Search ) 
that need to be kept in sync 
@crichardson
Solution to #3/#4: Event-based 
architecture to the rescue 
@crichardson 
Microservices publish events when state changes 
Microservices subscribe to events 
Synchronize replicated data 
Maintains eventual consistency across multiple 
aggregates (in multiple datastores)
Eventually consistent money transfer 
MoneyTransferService AccountService 
@crichardson 
Message Bus 
transferMoney() 
Subscribes to: Publishes: 
Subscribes to: 
publishes: 
AccountDebitedEvent 
AccountCreditedEvent 
MoneyTransferCreatedEvent 
DebitRecordedEvent 
MoneyTransferCreatedEvent 
DebitRecordedEvent 
AccountDebitedEvent 
AccountCreditedEvent
To maintain consistency a service 
@crichardson 
must 
atomically publish an event 
whenever 
a domain object changes
@crichardson 
How to generate events 
reliably? 
Database triggers, Hibernate event listener, ... 
Reliable BUT 
Not with NoSQL 
Disconnected from the business level event 
Limited applicability 
Ad hoc event publishing code mixed into business logic 
Messy code, poor separation of concerns 
Unreliable, e.g. too easy to forget to publish an event
How to atomically update 
datastore and publish event(s) 
Use 2PC 
@crichardson 
Database and message broker must support 2PC 
2PC is best avoided 
Use datastore as a message queue 
1. Update database: new entity state & event to publish 
2. Publish event & mark event as published 
Eventually consistent mechanism 
See BASE: An Acid Alternative, http://bit.ly/ebaybase 
• Difficult to implement when using a NoSQL database :-(
@crichardson 
Agenda 
Why build event-driven microservices? 
Overview of event sourcing 
Designing microservices with event sourcing 
Implementing queries in an event sourced application 
Building and deploying microservices
@crichardson 
Event sourcing 
For each aggregate: 
Identify (state-changing) domain events 
Define Event classes 
For example, 
Account: AccountOpenedEvent, AccountDebitedEvent, 
AccountCreditedEvent 
ShoppingCart: ItemAddedEvent, ItemRemovedEvent, 
OrderPlacedEvent
@crichardson 
Persists events 
NOT current state 
Account 
balance 
open(initial) 
debit(amount) 
credit(amount) 
Account X 
table 101 450 
Event table 
AccountOpened 
AccountCredited 
AccountDebited 
101 
101 
101 
901 
902 
903 
500 
250 
300
@crichardson 
Replay events to recreate 
state 
Account 
balance 
Events 
AccountOpenedEvent(balance) 
AccountDebitedEvent(amount) 
AccountCreditedEvent(amount)
@crichardson 
Aggregate traits 
Apply event returning 
updated Aggregate 
Map Command to Events
Account - command processing 
Prevent 
overdraft 
@crichardson
@crichardson 
Account - applying events 
Immutable
Request handling in an event-sourced application 
@crichardson 
HTTP 
Handler 
Event 
Store 
pastEvents = findEvents(entityId) 
Account 
new() 
applyEvents(pastEvents) 
newEvents = processCmd(SomeCmd) 
saveEvents(newEvents) 
Microservice A
@crichardson 
Event Store publishes events - 
consumed by other services 
Event 
Store 
Microservice B 
Event 
Subscriber 
subscribe(EventTypes) 
publish(event) 
publish(event) 
Aggregate 
NoSQL 
materialized 
view 
update() 
update()
@crichardson 
Persisting events 
Ideally use a cross platform format 
Use weak serialization: 
enables event evolution, eg. add memo field to transfer 
missing field ⇒ provide default value 
unknown field ⇒ ignore 
JSON is a good choice
Optimizing using snapshots 
Most aggregates have relatively few events 
BUT consider a 10-year old Account ⇒ many transactions 
Therefore, use snapshots: 
Periodically save snapshot of aggregate state 
Typically serialize memento of the aggregate 
Load latest snapshot + subsequent events 
@crichardson
@crichardson 
Event Store API 
trait EventStore { 
def save[T <: Aggregate[T]](entity: T, events: Seq[Event], 
assignedId : Option[EntityId] = None): Future[EntityWithIdAndVersion[T]] 
def update[T <: Aggregate[T]](entityIdAndVersion : EntityIdAndVersion, 
entity: T, events: Seq[Event]): Future[EntityWithIdAndVersion[T]] 
def find[T <: Aggregate[T] : ClassTag](entityId: EntityId) : 
Future[EntityWithIdAndVersion[T]] 
def findOptional[T <: Aggregate[T] : ClassTag](entityId: EntityId) 
Future[Option[EntityWithIdAndVersion[T]]] 
def subscribe(subscriptionId: SubscriptionId): 
Future[AcknowledgableEventStream] 
}
@crichardson 
Business benefits of event 
sourcing 
Built-in, reliable audit log 
Enables temporal queries 
Publishes events needed by big data/predictive analytics 
etc. 
Preserved history ⇒ More easily implement future 
requirements
Technical benefits of event 
sourcing 
Solves data consistency issues in a Microservice/NoSQL-based 
@crichardson 
architecture: 
Atomically save and publish events 
Event subscribers update other aggregates ensuring 
eventual consistency 
Event subscribers update materialized views in SQL and 
NoSQL databases (more on that later) 
Eliminates O/R mapping problem
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 (more 
on that later) 
@crichardson
Example of an eventual 
consistency problem 
Scenario: 
1.Create the user 
2.Create shopping cart 
3.Update the user with the shopping cart’s id 
The user temporarily does not have a shopping cart id! 
Client might need to retry their request at a later point 
Server should return status code 418?? 
@crichardson
Handling duplicate messages 
Idempotent operations 
e.g. add item to shopping cart 
Duplicate detection: 
e.g. track most recently seen event and discard earlier 
ones 
@crichardson
@crichardson 
Agenda 
Why build event-driven microservices? 
Overview of event sourcing 
Designing microservices with event sourcing 
Implementing queries in an event sourced application 
Building and deploying microservices
The anatomy of a microservice 
@crichardson 
HTTP Request 
HTTP Adapter 
Cmd 
Xyz Request 
Aggregate 
Xyz Adapter 
Event Adapter 
Event Store 
Cmd 
Events 
Events 
microservice
@crichardson 
Asynchronous Spring MVC 
controller
@crichardson 
MoneyTransferService 
DSL concisely specifies: 
1.Creates MoneyTransfer aggregate 
2.Processes command 
3.Applies events 
4.Persists events
@crichardson 
MoneyTransfer Aggregate
@crichardson 
Handling events published 
by Accounts 
1.Load MoneyTransfer aggregate 
2.Processes command 
3.Applies events 
4.Persists events
@crichardson 
Agenda 
Why build event-driven microservices? 
Overview of event sourcing 
Designing microservices with event sourcing 
Implementing queries in an event sourced application 
Building and deploying microservices
Let’s imagine that you want 
to display an account and it’s 
recent transactions... 
@crichardson
Displaying balance + recent 
credits and debits 
We need to do a “join: between the Account and the corresponding 
MoneyTransfers 
(Assuming Debit/Credit events don’t include other account, ...) 
@crichardson 
BUT 
Event Store = primary key lookup of individual aggregates, ... 
⇒ 
Use Command Query Responsibility Separation 
Define separate “materialized” query-side views that implement 
those queries
HTTP GET 
Request 
View Query 
Service 
@crichardson 
Query-side microservices 
Updater - microservice 
View Updater 
Service 
Events 
Event Store 
Reader - microservice 
View 
Store 
e.g. 
MongoDB 
Neo4J 
CloudSearch 
update query
Persisting account balance and 
recent transactions in MongoDB 
Transfers that update 
The sequence of 
debits and credits 
@crichardson 
{ 
id: "298993498", 
balance: 100000, 
transfers : [ 
{"transferId" : "4552840948484", 
"fromAccountId" : 298993498, 
"toAccountId" : 3483948934, 
"amount" : 5000}, ... 
], 
changes: [ 
the account 
{"changeId" : "93843948934", 
"transferId" : "4552840948484", 
"transactionType" : "AccountDebited", 
"amount" : 5000}, ... 
] 
} 
Denormalized = efficient lookup
duplicate event detection 
@crichardson 
Updating MongoDB using 
Spring Data 
class AccountInfoUpdateService 
(mongoTemplate : MongoTemplate, ...) 
extends CompoundEventHandler { 
@EventHandler 
def recordDebit(de: DispatchedEvent[AccountDebitedEvent]) = { 
... 
val ci = AccountChangeInfo(...) 
mongoTemplate.updateMulti( 
new Query(where("id").is(de.entityId.id).and("version").lt(changeId)), 
new Update(). 
dec("balance", amount). 
push("changes", ci). 
set("version", changeId), 
classOf[AccountInfo]) 
} 
@EventHandler 
def recordTransfer(de: DispatchedEvent[MoneyTransferCreatedEvent]) = ... 
} 
insert/In-place update 
updates to and from accounts
Retrieving account info from 
MongoDB using Spring Data 
class AccountInfoQueryService(accountInfoRepository : AccountInfoRepository) 
{ 
@crichardson 
def findByAccountId(accountId : EntityId) : AccountInfo = 
accountInfoRepository.findOne(accountId.id) 
} 
case class AccountInfo(id : String, balance : Long, 
transactions : List[AccountTransactionInfo], 
changes : List[ChangeInfo], 
version : String) 
case class AccountTransactionInfo(changeId : String, 
transactionId : String, 
transactionType : String, 
amount : Long, balanceDelta : Long) 
trait AccountInfoRepository extends MongoRepository[AccountInfo, String] 
Implementation generated by Spring Data
@crichardson 
Other kinds of views 
AWS Cloud Search 
Text search as-a-Service 
View updater batches aggregates to index 
View query 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
@crichardson 
Dealing with eventually 
consistent views 
Scenario: 
Client creates/updates aggregate 
Client requests view of aggregate 
But the view might not yet have been updated 
Solution: 
Create/Update response contains aggregate version 
Query request contains desired version 
Alternatively: 
“Fake it” in the UI until the view is updated
@crichardson 
Agenda 
Why build event-driven microservices? 
Overview of event sourcing 
Designing microservices with event sourcing 
Implementing queries in an event sourced application 
Building and deploying microservices
Building microservices with 
Spring Boot 
Makes it easy to create stand-alone, production ready 
Spring Applications 
Automatically configures Spring using Convention over 
Configuration 
Externalizes configuration 
Generates standalone executable JARs with embedded 
web server 
@crichardson
Spring Boot simplifies configuration 
Spring 
You write less Boot 
@crichardson 
Application 
components 
Spring 
Container 
Fully 
configured 
application 
Configuration 
Metadata 
•Typesafe JavaConfig 
•Annotations 
•Legacy XML 
Default 
Configuration 
Metadata 
of this 
Inferred from 
CLASSPATH
Tiny Spring configuration for 
Account microservice 
Scan for controllers 
@crichardson 
@Configuration 
@EnableAutoConfiguration 
@Import(classOf[JdbcEventStoreConfiguration])) 
@ComponentScan 
class AccountConfiguration { 
@Bean 
def accountService(eventStore : EventStore) = 
new AccountService(eventStore) 
@Bean 
def accountEventHandlers(eventStore : EventStore) = 
EventHandlerRegistrar.makeFromCompoundEventHandler( 
eventStore, "accountEventHandlers", 
new TransferWorkflowAccountHandlers(eventStore)) 
@Bean 
@Primary 
def scalaObjectMapper() = ScalaObjectMapper 
} 
Service 
Event handlers 
Customize JSON serialization
@crichardson 
The Main program 
object BankingMain extends App { 
SpringApplication.run(classOf[AccountConfiguration], args :_ *) 
}
@crichardson 
Building with Gradle 
buildscript { 
repositories { 
mavenCentral() 
} 
dependencies { 
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.0.RELEASE") 
} 
} 
apply plugin: 'scala' 
apply plugin: 'spring-boot' 
...
Command line arg processing 
@crichardson 
Running the microservice 
$ java -jar build/libs/banking-main-1.0-SNAPSHOT.jar --server.port=8081 
... 
11:38:04.633 INFO n.c.e.e.bank.web.main.BankingMain$ - Started 
BankingMain. in 8.811 seconds (JVM running for 9.884) 
$ curl localhost:8081/health 
{"status":"UP", 
"mongo":{"status":"UP","version":"2.4.10"}, 
"db":{"status":"UP","database":"H2","hello":1} 
} 
Built in health checks
NodeJS-based API gateway 
Motivations 
Small footprint 
Efficient, event-driven I/O 
Availability of modules: express, request, googleapis, ... 
Routes requests to the appropriate backend service based 
on URL prefix 
Handles Google/OAuth-based authentication 
@crichardson
@crichardson 
Jenkins-based deployment 
pipeline 
Build & Test 
micro-service 
Build & Test 
Docker 
image 
Deploy 
Docker 
image 
to registry 
One pipeline per micro-service
@crichardson 
Production environment 
EC2 instance running Docker 
Deployment tool: 
1.Compares running containers with what’s been built by 
Jenkins 
2.Pulls latest images from Docker registry 
3.Stops old versions 
4.Launches new versions
@crichardson 
Summary 
Event Sourcing solves key data consistency issues with: 
Microservices 
Partitioned/NoSQL databases 
Spring and Scala play nicely together 
Spring Boot makes it very easily to build production ready 
microservices 
NodeJS is useful for building network-centric services
@crichardson chris@chrisrichardson.net 
@crichardson 
Questions? 
http://plainoldobjects.com http://microservices.io

More Related Content

What's hot

What's hot (20)

Events, Picos, and Microservices
Events, Picos, and MicroservicesEvents, Picos, and Microservices
Events, Picos, and Microservices
 
Building microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring BootBuilding microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring Boot
 
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)
 
How to write your database: the story about Event Store
How to write your database: the story about Event StoreHow to write your database: the story about Event Store
How to write your database: the story about Event Store
 
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
 
DDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFrameworkDDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFramework
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)
 
A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)
 
Microservice Architecture with CQRS and Event Sourcing
Microservice Architecture with CQRS and Event SourcingMicroservice Architecture with CQRS and Event Sourcing
Microservice Architecture with CQRS and Event Sourcing
 
Effective Microservices Design using Events and Event Sourcing
Effective Microservices Design using Events and Event SourcingEffective Microservices Design using Events and Event Sourcing
Effective Microservices Design using Events and Event Sourcing
 
Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)
 
Going Serverless with CQRS on AWS
Going Serverless with CQRS on AWSGoing Serverless with CQRS on AWS
Going Serverless with CQRS on AWS
 
Developing event-driven microservices with event sourcing and CQRS (london Ja...
Developing event-driven microservices with event sourcing and CQRS (london Ja...Developing event-driven microservices with event sourcing and CQRS (london Ja...
Developing event-driven microservices with event sourcing and CQRS (london Ja...
 
Building and deploying microservices with event sourcing, CQRS and Docker (Me...
Building and deploying microservices with event sourcing, CQRS and Docker (Me...Building and deploying microservices with event sourcing, CQRS and Docker (Me...
Building and deploying microservices with event sourcing, CQRS and Docker (Me...
 
Developing microservices with aggregates (melbourne)
Developing microservices with aggregates (melbourne)Developing microservices with aggregates (melbourne)
Developing microservices with aggregates (melbourne)
 
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
 
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
 
#JaxLondon keynote: Developing applications with a microservice architecture
#JaxLondon keynote: Developing applications with a microservice architecture#JaxLondon keynote: Developing applications with a microservice architecture
#JaxLondon keynote: Developing applications with a microservice architecture
 
CQRS + Event Sourcing
CQRS + Event SourcingCQRS + Event Sourcing
CQRS + Event Sourcing
 
Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)
 

Viewers also liked

Viewers also liked (9)

Stephane Lapointe & Alexandre Brisebois: Développer des microservices avec Se...
Stephane Lapointe & Alexandre Brisebois: Développer des microservices avec Se...Stephane Lapointe & Alexandre Brisebois: Développer des microservices avec Se...
Stephane Lapointe & Alexandre Brisebois: Développer des microservices avec Se...
 
An Introduction to Domain Driven Design in PHP
An Introduction to Domain Driven Design in PHPAn Introduction to Domain Driven Design in PHP
An Introduction to Domain Driven Design in PHP
 
How ddd, cqrs and event sourcing constitute the architecture of the future
How ddd, cqrs and event sourcing constitute the architecture of the futureHow ddd, cqrs and event sourcing constitute the architecture of the future
How ddd, cqrs and event sourcing constitute the architecture of the future
 
Domain Driven Design Development Spring Portfolio
Domain Driven Design Development Spring PortfolioDomain Driven Design Development Spring Portfolio
Domain Driven Design Development Spring Portfolio
 
Entity Framework and Domain Driven Design
Entity Framework and Domain Driven DesignEntity Framework and Domain Driven Design
Entity Framework and Domain Driven Design
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Laravel.IO A Use-Case Architecture
Laravel.IO A Use-Case ArchitectureLaravel.IO A Use-Case Architecture
Laravel.IO A Use-Case Architecture
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
 
Domain Driven Design 101
Domain Driven Design 101Domain Driven Design 101
Domain Driven Design 101
 

Similar to Building Microservices with Scala, functional domain models and Spring Boot - Chris Richardson

Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...
Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...
Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...
confluent
 

Similar to Building Microservices with Scala, functional domain models and Spring Boot - Chris Richardson (20)

Developing event-driven microservices with event sourcing and CQRS (phillyete)
Developing event-driven microservices with event sourcing and CQRS (phillyete)Developing event-driven microservices with event sourcing and CQRS (phillyete)
Developing event-driven microservices with event sourcing and CQRS (phillyete)
 
Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...
 
Events on the outside, on the inside and at the core (jaxlondon)
Events on the outside, on the inside and at the core (jaxlondon)Events on the outside, on the inside and at the core (jaxlondon)
Events on the outside, on the inside and at the core (jaxlondon)
 
Events on the outside, on the inside and at the core - Chris Richardson
Events on the outside, on the inside and at the core - Chris RichardsonEvents on the outside, on the inside and at the core - Chris Richardson
Events on the outside, on the inside and at the core - Chris Richardson
 
Developing event-driven microservices with event sourcing and CQRS (Shanghai)
Developing event-driven microservices with event sourcing and CQRS (Shanghai)Developing event-driven microservices with event sourcing and CQRS (Shanghai)
Developing event-driven microservices with event sourcing and CQRS (Shanghai)
 
Microservices + Events + Docker = A Perfect Trio by Docker Captain Chris Rich...
Microservices + Events + Docker = A Perfect Trio by Docker Captain Chris Rich...Microservices + Events + Docker = A Perfect Trio by Docker Captain Chris Rich...
Microservices + Events + Docker = A Perfect Trio by Docker Captain Chris Rich...
 
Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)
 
SVCC Developing Asynchronous, Message-Driven Microservices
SVCC Developing Asynchronous, Message-Driven Microservices  SVCC Developing Asynchronous, Message-Driven Microservices
SVCC Developing Asynchronous, Message-Driven Microservices
 
Solving distributed data management problems in a microservice architecture (...
Solving distributed data management problems in a microservice architecture (...Solving distributed data management problems in a microservice architecture (...
Solving distributed data management problems in a microservice architecture (...
 
YOW2018 - Events and Commands: Developing Asynchronous Microservices
YOW2018 - Events and Commands: Developing Asynchronous MicroservicesYOW2018 - Events and Commands: Developing Asynchronous Microservices
YOW2018 - Events and Commands: Developing Asynchronous Microservices
 
OReilly SACON2018 - Events on the outside, on the inside, and at the core
OReilly SACON2018 - Events on the outside, on the inside, and at the coreOReilly SACON2018 - Events on the outside, on the inside, and at the core
OReilly SACON2018 - Events on the outside, on the inside, and at the core
 
Mucon: Not Just Events: Developing Asynchronous Microservices
Mucon: Not Just Events: Developing Asynchronous MicroservicesMucon: Not Just Events: Developing Asynchronous Microservices
Mucon: Not Just Events: Developing Asynchronous Microservices
 
Event driven architecure
Event driven architecureEvent driven architecure
Event driven architecure
 
Real-Time Event Processing
Real-Time Event ProcessingReal-Time Event Processing
Real-Time Event Processing
 
Siddhi - cloud-native stream processor
Siddhi - cloud-native stream processorSiddhi - cloud-native stream processor
Siddhi - cloud-native stream processor
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...
Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...
Event Driven Architecture with a RESTful Microservices Architecture (Kyle Ben...
 
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
 
(MBL305) You Have Data from the Devices, Now What?: Getting the Value of the IoT
(MBL305) You Have Data from the Devices, Now What?: Getting the Value of the IoT(MBL305) You Have Data from the Devices, Now What?: Getting the Value of the IoT
(MBL305) You Have Data from the Devices, Now What?: Getting the Value of the IoT
 
Keep Your Code Low, Low, Low, Low, Low: Getting to Digitally Driven With Orac...
Keep Your Code Low, Low, Low, Low, Low: Getting to Digitally Driven With Orac...Keep Your Code Low, Low, Low, Low, Low: Getting to Digitally Driven With Orac...
Keep Your Code Low, Low, Low, Low, Low: Getting to Digitally Driven With Orac...
 

More from JAXLondon2014

How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...
How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...
How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...
JAXLondon2014
 
Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...
Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...
Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...
JAXLondon2014
 
Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...
Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...
Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...
JAXLondon2014
 

More from JAXLondon2014 (20)

GridGain 6.0: Open Source In-Memory Computing Platform - Nikita Ivanov
GridGain 6.0: Open Source In-Memory Computing Platform - Nikita IvanovGridGain 6.0: Open Source In-Memory Computing Platform - Nikita Ivanov
GridGain 6.0: Open Source In-Memory Computing Platform - Nikita Ivanov
 
Performance Metrics for your Delivery Pipeline - Wolfgang Gottesheim
Performance Metrics for your Delivery Pipeline - Wolfgang GottesheimPerformance Metrics for your Delivery Pipeline - Wolfgang Gottesheim
Performance Metrics for your Delivery Pipeline - Wolfgang Gottesheim
 
How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...
How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...
How to randomly access data in close-to-RAM speeds but a lower cost with SSD’...
 
Conditional Logging Considered Harmful - Sean Reilly
Conditional Logging Considered Harmful - Sean ReillyConditional Logging Considered Harmful - Sean Reilly
Conditional Logging Considered Harmful - Sean Reilly
 
Finding your Way in the Midst of the NoSQL Haze - Abdelmonaim Remani
Finding your Way in the Midst of the NoSQL Haze - Abdelmonaim RemaniFinding your Way in the Midst of the NoSQL Haze - Abdelmonaim Remani
Finding your Way in the Midst of the NoSQL Haze - Abdelmonaim Remani
 
API Management - a hands on workshop - Paul Fremantle
API Management - a hands on workshop - Paul FremantleAPI Management - a hands on workshop - Paul Fremantle
API Management - a hands on workshop - Paul Fremantle
 
'Bootiful' Code with Spring Boot - Josh Long
'Bootiful' Code with Spring Boot - Josh Long'Bootiful' Code with Spring Boot - Josh Long
'Bootiful' Code with Spring Boot - Josh Long
 
The Full Stack Java Developer - Josh Long
The Full Stack Java Developer - Josh LongThe Full Stack Java Developer - Josh Long
The Full Stack Java Developer - Josh Long
 
The Economies of Scaling Software - Josh Long and Abdelmonaim Remani
The Economies of Scaling Software - Josh Long and Abdelmonaim RemaniThe Economies of Scaling Software - Josh Long and Abdelmonaim Remani
The Economies of Scaling Software - Josh Long and Abdelmonaim Remani
 
Dataflow, the Forgotten Way - Russel Winder
Dataflow, the Forgotten Way - Russel WinderDataflow, the Forgotten Way - Russel Winder
Dataflow, the Forgotten Way - Russel Winder
 
Habits of Highly Effective Technical Teams - Martijn Verburg
Habits of Highly Effective Technical Teams - Martijn VerburgHabits of Highly Effective Technical Teams - Martijn Verburg
Habits of Highly Effective Technical Teams - Martijn Verburg
 
The Lazy Developer's Guide to Cloud Foundry - Holly Cummins
The Lazy Developer's Guide to Cloud Foundry - Holly CumminsThe Lazy Developer's Guide to Cloud Foundry - Holly Cummins
The Lazy Developer's Guide to Cloud Foundry - Holly Cummins
 
Testing within an Agile Environment - Beyza Sakir and Chris Gollop
Testing within an Agile Environment - Beyza Sakir and Chris GollopTesting within an Agile Environment - Beyza Sakir and Chris Gollop
Testing within an Agile Environment - Beyza Sakir and Chris Gollop
 
Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...
Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...
Testing the Enterprise Layers - the A, B, C's of Integration Testing - Aslak ...
 
Squeezing Performance of out of In-Memory Data Grids - Fuad Malikov
Squeezing Performance of out of In-Memory Data Grids - Fuad MalikovSqueezing Performance of out of In-Memory Data Grids - Fuad Malikov
Squeezing Performance of out of In-Memory Data Grids - Fuad Malikov
 
Spocktacular Testing - Russel Winder
Spocktacular Testing - Russel WinderSpocktacular Testing - Russel Winder
Spocktacular Testing - Russel Winder
 
Server Side JavaScript on the Java Platform - David Delabassee
Server Side JavaScript on the Java Platform - David DelabasseeServer Side JavaScript on the Java Platform - David Delabassee
Server Side JavaScript on the Java Platform - David Delabassee
 
Reflection Madness - Dr. Heinz Kabutz
Reflection Madness - Dr. Heinz KabutzReflection Madness - Dr. Heinz Kabutz
Reflection Madness - Dr. Heinz Kabutz
 
Rapid Web Application Development with MongoDB and the JVM - Trisha Gee
Rapid Web Application Development with MongoDB and the JVM - Trisha GeeRapid Web Application Development with MongoDB and the JVM - Trisha Gee
Rapid Web Application Development with MongoDB and the JVM - Trisha Gee
 
Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...
Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...
Pushing Java EE outside of the Enterprise: Home Automation and IoT - David De...
 

Recently uploaded

If this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New NigeriaIf this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New Nigeria
Kayode Fayemi
 
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptxChiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
raffaeleoman
 
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
Sheetaleventcompany
 

Recently uploaded (20)

Introduction to Prompt Engineering (Focusing on ChatGPT)
Introduction to Prompt Engineering (Focusing on ChatGPT)Introduction to Prompt Engineering (Focusing on ChatGPT)
Introduction to Prompt Engineering (Focusing on ChatGPT)
 
Causes of poverty in France presentation.pptx
Causes of poverty in France presentation.pptxCauses of poverty in France presentation.pptx
Causes of poverty in France presentation.pptx
 
Air breathing and respiratory adaptations in diver animals
Air breathing and respiratory adaptations in diver animalsAir breathing and respiratory adaptations in diver animals
Air breathing and respiratory adaptations in diver animals
 
If this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New NigeriaIf this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New Nigeria
 
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptxChiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
 
lONG QUESTION ANSWER PAKISTAN STUDIES10.
lONG QUESTION ANSWER PAKISTAN STUDIES10.lONG QUESTION ANSWER PAKISTAN STUDIES10.
lONG QUESTION ANSWER PAKISTAN STUDIES10.
 
Sector 62, Noida Call girls :8448380779 Noida Escorts | 100% verified
Sector 62, Noida Call girls :8448380779 Noida Escorts | 100% verifiedSector 62, Noida Call girls :8448380779 Noida Escorts | 100% verified
Sector 62, Noida Call girls :8448380779 Noida Escorts | 100% verified
 
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
 
BDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort Service
 
SaaStr Workshop Wednesday w/ Lucas Price, Yardstick
SaaStr Workshop Wednesday w/ Lucas Price, YardstickSaaStr Workshop Wednesday w/ Lucas Price, Yardstick
SaaStr Workshop Wednesday w/ Lucas Price, Yardstick
 
Presentation on Engagement in Book Clubs
Presentation on Engagement in Book ClubsPresentation on Engagement in Book Clubs
Presentation on Engagement in Book Clubs
 
Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...
Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...
Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...
 
Report Writing Webinar Training
Report Writing Webinar TrainingReport Writing Webinar Training
Report Writing Webinar Training
 
Dreaming Marissa Sánchez Music Video Treatment
Dreaming Marissa Sánchez Music Video TreatmentDreaming Marissa Sánchez Music Video Treatment
Dreaming Marissa Sánchez Music Video Treatment
 
ICT role in 21st century education and it's challenges.pdf
ICT role in 21st century education and it's challenges.pdfICT role in 21st century education and it's challenges.pdf
ICT role in 21st century education and it's challenges.pdf
 
The workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdf
The workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdfThe workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdf
The workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdf
 
Thirunelveli call girls Tamil escorts 7877702510
Thirunelveli call girls Tamil escorts 7877702510Thirunelveli call girls Tamil escorts 7877702510
Thirunelveli call girls Tamil escorts 7877702510
 
My Presentation "In Your Hands" by Halle Bailey
My Presentation "In Your Hands" by Halle BaileyMy Presentation "In Your Hands" by Halle Bailey
My Presentation "In Your Hands" by Halle Bailey
 
Dreaming Music Video Treatment _ Project & Portfolio III
Dreaming Music Video Treatment _ Project & Portfolio IIIDreaming Music Video Treatment _ Project & Portfolio III
Dreaming Music Video Treatment _ Project & Portfolio III
 
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdfAWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
 

Building Microservices with Scala, functional domain models and Spring Boot - Chris Richardson

  • 1. @crichardson Building microservices with Scala, functional domain models and Spring Boot Chris Richardson Author of POJOs in Action Founder of the original CloudFoundry.com @crichardson chris@chrisrichardson.net http://plainoldobjects.com
  • 2. @crichardson Presentation goal Share my experiences with building an application using Scala, functional domain models, microservices, event sourcing, CQRS, and Spring Boot
  • 4. @crichardson About Chris Founder of a buzzword compliant (stealthy, social, mobile, big data, machine learning, ...) startup Consultant helping organizations improve how they architect and deploy applications using cloud, micro services, polyglot applications, NoSQL, ...
  • 5. @crichardson Agenda Why build event-driven microservices? Overview of event sourcing Designing microservices with event sourcing Implementing queries in an event sourced application Building and deploying microservices
  • 6. @crichardson Let’s imagine that you are building a banking app...
  • 7. @crichardson Domain model Account balance open(initialBalance) debit(amount) credit(amount) MoneyTransfer fromAccountId toAccountId amount
  • 8. @crichardson Traditional application architecture BanBaknikningg UI Accounts Transfers Tomcat Browser/ Client WAR/EAR RDBMS Customers Simple to develop test deploy Load balancer scale Spring MVC Spring Hibernate ... HTML REST/JSON
  • 9. @crichardson Problem #1: monolithic architecture Intimidates developers Obstacle to frequent deployments Overloads your IDE and container Obstacle to scaling development Requires long-term commitment to a technology stack
  • 10. Standalone services @crichardson Solution #1: use a microservice architecture Banking UI Account Management Service Transaction Management Service Account Database Transaction Database
  • 11. @crichardson Problem #2: relational databases Scalability Distribution Schema updates O/R impedance mismatch Handling semi-structured data
  • 12. @crichardson Solution #2: use NoSQL databases Avoids the limitations of RDBMS For example, text search ⇒ Solr/Cloud Search social (graph) data ⇒ Neo4J highly distributed/available database ⇒ Cassandra ...
  • 13. @crichardson Different modules use different databases IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg
  • 14. But now we have problems with data consistency! @crichardson
  • 15. Problem #3: Microservices = distributed data management @crichardson Each microservice has it’s own database Some data is replicated and must be kept in sync Business transactions must update data owned by multiple services Tricky to implement reliably without 2PC
  • 16. Problem #4: NoSQL = ACID-free, denormalized databases Limited transactions, i.e. no ACID transactions Tricky to implement business transactions that update multiple rows, e.g. http://bit.ly/mongo2pc Limited querying capabilities Requires denormalized/materialized views that must be synchronized Multiple datastores (e.g. DynamoDB + Cloud Search ) that need to be kept in sync @crichardson
  • 17. Solution to #3/#4: Event-based architecture to the rescue @crichardson Microservices publish events when state changes Microservices subscribe to events Synchronize replicated data Maintains eventual consistency across multiple aggregates (in multiple datastores)
  • 18. Eventually consistent money transfer MoneyTransferService AccountService @crichardson Message Bus transferMoney() Subscribes to: Publishes: Subscribes to: publishes: AccountDebitedEvent AccountCreditedEvent MoneyTransferCreatedEvent DebitRecordedEvent MoneyTransferCreatedEvent DebitRecordedEvent AccountDebitedEvent AccountCreditedEvent
  • 19. To maintain consistency a service @crichardson must atomically publish an event whenever a domain object changes
  • 20. @crichardson How to generate events reliably? Database triggers, Hibernate event listener, ... Reliable BUT Not with NoSQL Disconnected from the business level event Limited applicability Ad hoc event publishing code mixed into business logic Messy code, poor separation of concerns Unreliable, e.g. too easy to forget to publish an event
  • 21. How to atomically update datastore and publish event(s) Use 2PC @crichardson Database and message broker must support 2PC 2PC is best avoided Use datastore as a message queue 1. Update database: new entity state & event to publish 2. Publish event & mark event as published Eventually consistent mechanism See BASE: An Acid Alternative, http://bit.ly/ebaybase • Difficult to implement when using a NoSQL database :-(
  • 22. @crichardson Agenda Why build event-driven microservices? Overview of event sourcing Designing microservices with event sourcing Implementing queries in an event sourced application Building and deploying microservices
  • 23. @crichardson Event sourcing For each aggregate: Identify (state-changing) domain events Define Event classes For example, Account: AccountOpenedEvent, AccountDebitedEvent, AccountCreditedEvent ShoppingCart: ItemAddedEvent, ItemRemovedEvent, OrderPlacedEvent
  • 24. @crichardson Persists events NOT current state Account balance open(initial) debit(amount) credit(amount) Account X table 101 450 Event table AccountOpened AccountCredited AccountDebited 101 101 101 901 902 903 500 250 300
  • 25. @crichardson Replay events to recreate state Account balance Events AccountOpenedEvent(balance) AccountDebitedEvent(amount) AccountCreditedEvent(amount)
  • 26. @crichardson Aggregate traits Apply event returning updated Aggregate Map Command to Events
  • 27. Account - command processing Prevent overdraft @crichardson
  • 28. @crichardson Account - applying events Immutable
  • 29. Request handling in an event-sourced application @crichardson HTTP Handler Event Store pastEvents = findEvents(entityId) Account new() applyEvents(pastEvents) newEvents = processCmd(SomeCmd) saveEvents(newEvents) Microservice A
  • 30. @crichardson Event Store publishes events - consumed by other services Event Store Microservice B Event Subscriber subscribe(EventTypes) publish(event) publish(event) Aggregate NoSQL materialized view update() update()
  • 31. @crichardson Persisting events Ideally use a cross platform format Use weak serialization: enables event evolution, eg. add memo field to transfer missing field ⇒ provide default value unknown field ⇒ ignore JSON is a good choice
  • 32. Optimizing using snapshots Most aggregates have relatively few events BUT consider a 10-year old Account ⇒ many transactions Therefore, use snapshots: Periodically save snapshot of aggregate state Typically serialize memento of the aggregate Load latest snapshot + subsequent events @crichardson
  • 33. @crichardson Event Store API trait EventStore { def save[T <: Aggregate[T]](entity: T, events: Seq[Event], assignedId : Option[EntityId] = None): Future[EntityWithIdAndVersion[T]] def update[T <: Aggregate[T]](entityIdAndVersion : EntityIdAndVersion, entity: T, events: Seq[Event]): Future[EntityWithIdAndVersion[T]] def find[T <: Aggregate[T] : ClassTag](entityId: EntityId) : Future[EntityWithIdAndVersion[T]] def findOptional[T <: Aggregate[T] : ClassTag](entityId: EntityId) Future[Option[EntityWithIdAndVersion[T]]] def subscribe(subscriptionId: SubscriptionId): Future[AcknowledgableEventStream] }
  • 34. @crichardson Business benefits of event sourcing Built-in, reliable audit log Enables temporal queries Publishes events needed by big data/predictive analytics etc. Preserved history ⇒ More easily implement future requirements
  • 35. Technical benefits of event sourcing Solves data consistency issues in a Microservice/NoSQL-based @crichardson architecture: Atomically save and publish events Event subscribers update other aggregates ensuring eventual consistency Event subscribers update materialized views in SQL and NoSQL databases (more on that later) Eliminates O/R mapping problem
  • 36. 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 (more on that later) @crichardson
  • 37. Example of an eventual consistency problem Scenario: 1.Create the user 2.Create shopping cart 3.Update the user with the shopping cart’s id The user temporarily does not have a shopping cart id! Client might need to retry their request at a later point Server should return status code 418?? @crichardson
  • 38. Handling duplicate messages Idempotent operations e.g. add item to shopping cart Duplicate detection: e.g. track most recently seen event and discard earlier ones @crichardson
  • 39. @crichardson Agenda Why build event-driven microservices? Overview of event sourcing Designing microservices with event sourcing Implementing queries in an event sourced application Building and deploying microservices
  • 40. The anatomy of a microservice @crichardson HTTP Request HTTP Adapter Cmd Xyz Request Aggregate Xyz Adapter Event Adapter Event Store Cmd Events Events microservice
  • 42. @crichardson MoneyTransferService DSL concisely specifies: 1.Creates MoneyTransfer aggregate 2.Processes command 3.Applies events 4.Persists events
  • 44. @crichardson Handling events published by Accounts 1.Load MoneyTransfer aggregate 2.Processes command 3.Applies events 4.Persists events
  • 45. @crichardson Agenda Why build event-driven microservices? Overview of event sourcing Designing microservices with event sourcing Implementing queries in an event sourced application Building and deploying microservices
  • 46. Let’s imagine that you want to display an account and it’s recent transactions... @crichardson
  • 47. Displaying balance + recent credits and debits We need to do a “join: between the Account and the corresponding MoneyTransfers (Assuming Debit/Credit events don’t include other account, ...) @crichardson BUT Event Store = primary key lookup of individual aggregates, ... ⇒ Use Command Query Responsibility Separation Define separate “materialized” query-side views that implement those queries
  • 48. HTTP GET Request View Query Service @crichardson Query-side microservices Updater - microservice View Updater Service Events Event Store Reader - microservice View Store e.g. MongoDB Neo4J CloudSearch update query
  • 49. Persisting account balance and recent transactions in MongoDB Transfers that update The sequence of debits and credits @crichardson { id: "298993498", balance: 100000, transfers : [ {"transferId" : "4552840948484", "fromAccountId" : 298993498, "toAccountId" : 3483948934, "amount" : 5000}, ... ], changes: [ the account {"changeId" : "93843948934", "transferId" : "4552840948484", "transactionType" : "AccountDebited", "amount" : 5000}, ... ] } Denormalized = efficient lookup
  • 50. duplicate event detection @crichardson Updating MongoDB using Spring Data class AccountInfoUpdateService (mongoTemplate : MongoTemplate, ...) extends CompoundEventHandler { @EventHandler def recordDebit(de: DispatchedEvent[AccountDebitedEvent]) = { ... val ci = AccountChangeInfo(...) mongoTemplate.updateMulti( new Query(where("id").is(de.entityId.id).and("version").lt(changeId)), new Update(). dec("balance", amount). push("changes", ci). set("version", changeId), classOf[AccountInfo]) } @EventHandler def recordTransfer(de: DispatchedEvent[MoneyTransferCreatedEvent]) = ... } insert/In-place update updates to and from accounts
  • 51. Retrieving account info from MongoDB using Spring Data class AccountInfoQueryService(accountInfoRepository : AccountInfoRepository) { @crichardson def findByAccountId(accountId : EntityId) : AccountInfo = accountInfoRepository.findOne(accountId.id) } case class AccountInfo(id : String, balance : Long, transactions : List[AccountTransactionInfo], changes : List[ChangeInfo], version : String) case class AccountTransactionInfo(changeId : String, transactionId : String, transactionType : String, amount : Long, balanceDelta : Long) trait AccountInfoRepository extends MongoRepository[AccountInfo, String] Implementation generated by Spring Data
  • 52. @crichardson Other kinds of views AWS Cloud Search Text search as-a-Service View updater batches aggregates to index View query 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
  • 53. @crichardson Dealing with eventually consistent views Scenario: Client creates/updates aggregate Client requests view of aggregate But the view might not yet have been updated Solution: Create/Update response contains aggregate version Query request contains desired version Alternatively: “Fake it” in the UI until the view is updated
  • 54. @crichardson Agenda Why build event-driven microservices? Overview of event sourcing Designing microservices with event sourcing Implementing queries in an event sourced application Building and deploying microservices
  • 55. Building microservices with Spring Boot Makes it easy to create stand-alone, production ready Spring Applications Automatically configures Spring using Convention over Configuration Externalizes configuration Generates standalone executable JARs with embedded web server @crichardson
  • 56. Spring Boot simplifies configuration Spring You write less Boot @crichardson Application components Spring Container Fully configured application Configuration Metadata •Typesafe JavaConfig •Annotations •Legacy XML Default Configuration Metadata of this Inferred from CLASSPATH
  • 57. Tiny Spring configuration for Account microservice Scan for controllers @crichardson @Configuration @EnableAutoConfiguration @Import(classOf[JdbcEventStoreConfiguration])) @ComponentScan class AccountConfiguration { @Bean def accountService(eventStore : EventStore) = new AccountService(eventStore) @Bean def accountEventHandlers(eventStore : EventStore) = EventHandlerRegistrar.makeFromCompoundEventHandler( eventStore, "accountEventHandlers", new TransferWorkflowAccountHandlers(eventStore)) @Bean @Primary def scalaObjectMapper() = ScalaObjectMapper } Service Event handlers Customize JSON serialization
  • 58. @crichardson The Main program object BankingMain extends App { SpringApplication.run(classOf[AccountConfiguration], args :_ *) }
  • 59. @crichardson Building with Gradle buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.0.RELEASE") } } apply plugin: 'scala' apply plugin: 'spring-boot' ...
  • 60. Command line arg processing @crichardson Running the microservice $ java -jar build/libs/banking-main-1.0-SNAPSHOT.jar --server.port=8081 ... 11:38:04.633 INFO n.c.e.e.bank.web.main.BankingMain$ - Started BankingMain. in 8.811 seconds (JVM running for 9.884) $ curl localhost:8081/health {"status":"UP", "mongo":{"status":"UP","version":"2.4.10"}, "db":{"status":"UP","database":"H2","hello":1} } Built in health checks
  • 61. NodeJS-based API gateway Motivations Small footprint Efficient, event-driven I/O Availability of modules: express, request, googleapis, ... Routes requests to the appropriate backend service based on URL prefix Handles Google/OAuth-based authentication @crichardson
  • 62. @crichardson Jenkins-based deployment pipeline Build & Test micro-service Build & Test Docker image Deploy Docker image to registry One pipeline per micro-service
  • 63. @crichardson Production environment EC2 instance running Docker Deployment tool: 1.Compares running containers with what’s been built by Jenkins 2.Pulls latest images from Docker registry 3.Stops old versions 4.Launches new versions
  • 64. @crichardson Summary Event Sourcing solves key data consistency issues with: Microservices Partitioned/NoSQL databases Spring and Scala play nicely together Spring Boot makes it very easily to build production ready microservices NodeJS is useful for building network-centric services
  • 65. @crichardson chris@chrisrichardson.net @crichardson Questions? http://plainoldobjects.com http://microservices.io