SlideShare uma empresa Scribd logo
1 de 59
Baixar para ler offline
Matt Walters
@mateodelnorte
hi@iammattwalters.com
How to CQRS in Node
Eventually consistent architectures that scale
and grow.
It’s real. It works!
Former TechStars Co. CTO. Now consultant.
Built two businesses’ platforms from scratch using
CQRS in Node. Both large, distributed systems.
CQRS made both more maintainable and extendable.
Marketing platform crunched the Twitter firehose in
realtime. 3 Engineers managed around 20 services.
- GoChime.com
Bond Exchange with over $1.75B in trades. 6 engineers
managed around 40 services.
- Electronifie.com
Open Source my tooling and frameworks.
Other companies using them too!
(and I’ll tell you how)
That’s me ^^ !!
When to CQRS
• Realtime, reactive systems
• When preferring small, modular services
• When aiming for learning and growth
• When aiming to grow or eventually split teams
• Want ability to scale different parts of your
system separately
When not to CQRS
• Standalone, static sites
• Standalone, simple CRUD applications
What is CQRS?
First, a primer from history.
Bertrand Meyer, regarding object interfaces:
“Every method should either be a command that
performs an action, or a query that returns data to the
caller, but not both. In other words, Asking a question
should not change the answer.”
Long before CQRS was CQS:
Command Query Separation.
this guy
Some Type
doSomething() : void
getSomeStuff() : Stuff
Either change stuff<——
Or get stuff<——
CQS
Command-Query
Separation
doAndGetStuff() : Stuff Never both!
——————
Command-Query
Responsibility Segregation
A system-wide architecture that states - externally
facing subsystems (apps and apis) send commands to
perform actions which update the system’s state and
request queries to determine system’s state.
*Basically CQS on a system-wide scale. Calls between
services should change stuff, or get stuff. Never both.
CQRS
Command-Query
Responsibility Segregation
CQRS also denotes that queries and command
processing are provided by different subsystems.
Queries are made against a data store. Commands are
sent to and processed by services.
CQRS One more thing!
What is CQRS?
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web
client
denormalizer
web-uiweb-uisvc
unidirectional flow
eventually consistent
Queries
Commands
the dance!
Events
How about a larger system?
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
Queries
Commands
unidirectional flow
eventually consistent
the dance!
Events
What’s that dance you’re doing?
denormalizer
dbdenormalizer
dbdenormalizer
db
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
the dance!
chain reaction of events which play out as a result of an
incoming command.
each service subscribes to the events they care about
choreography!
(not orchestration)
Events
commands tell services
when an actor wants an action
clients send commands to instruct a service to do work
commands are sent asynchronously; fire and forget
commands are present-tense, directives: order.create
web app order-svc
order.create
commands are sent directly to a single receiving service
events tell the world
when you’re done
services publish to inform other services of work / actions performed,
and state updated
services publish (broadcast) events to any services
that wish to subscribe
events past-tense, describe what happened: order.created
order-svc fulfillment-svc
order.createdorder.created
order.created
order.created
Two types of services
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
front end
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Two types of services
web-uiweb-uiweb-app
web
client
denormalizer
web-uiweb-uisvc
front end
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Let’s focus on:
web-uiweb-uiweb-app
web
client
web-uiweb-uisvc
front end (an app’s perspective)
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Apps (and apis) still query a db to get the state of the system
Never directly modify the db they read from
Let’s focus on:
web-uiweb-uiweb-app
web
client
web-uiweb-uisvc
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Instead, apps (and apis) send commands instructing services to
perform an action
Apps expect their read only representation of system state will
eventually be updated in the denormalizer db
Let’s focus on:
front end (an app’s perspective)
Commands are sent over a reliable transport (rabbitmq, kafka,
zeromq, etc) to ensure delivery and eventual consistency
Let’s pick a transport!
rabbitmq
messaging that just works
• direct send to queue
• fanout / topic routing
• highly available
• highly performant
• used in financial exchanges,
industrial applications and more
• open source
• free
rabbitmq
messaging that just works
brew install rabbitmq
framework!minimalist
Let’s pick a
servicebus
super simple messaging in node
• direct send
• pub / sub / fanout / topic -routing
• simple to set up
• highly performant
• used in financial exchanges,
online advertising and more
• open source
• free
• perfect for creating microservices!
servicebus
super simple messaging in node
npm install servicebus —save
web-uiweb-uiweb-app
web
client
denormalizer
web-uiweb-uisvc
front end
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Let’s focus on:
web-uiweb-uiweb-app
web-ui
web-uisvc
front end commands
denormalizer
dbdenormalizer
dbdenormalizer
db
How’s this work?
Let’s focus on:
Sending commands
from the front end
// web-app, onButtonClick. instead of updating db.
const bus = require('servicebus').bus();
bus.send(‘order.create', { 

order: {
userId: userId,
orderItems: items
}
});
web-uiweb-uiweb-app
web-ui
web-uisvc
// fire and forget.
command name
command itself
order.create command
Then what from the front end?
web-uiweb-uiweb-app
denormalizer
dbdenormalizer
dbdenormalizer
db
We wait.
• reactive / realtime:
• mongo oplog tailing (meteor)
• rethinkdb
• redis notifications
• couchdb
• graphQL
• polling
• non-realtime:
• product design: thanks! we’re processing your
order! check back later for updates!
queries!
We wait.
For the backend.
Choreography.
It’s eventually consistent!
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
front end
Let’s focus on:
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Let’s focus on:
back end
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
Let’s focus on:
back end (a service’s perspective)
web-uiweb-uiweb-app
svc
Commands
Events• Listen for commands and subscribe to events
• Performs business logic to process commands and events
• Update local state (optionally)
• Publish events to tell external services of updated state
Let’s focus on:
Sample service.
web-uiweb-uiweb-app
web-ui
web-uisvc
command name
command object
// order-svc index.js
const bus = require(‘./bus’);
const create = require(‘./lib/create’);
bus.listen(‘order.create', (event) => {
create(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.created’, order, () => {
event.handle.ack();
});
});
});
service publishes to the world when it’s done!
order.create command
order.created
event
Sample service.
web-uiweb-uiweb-app
web-ui
web-uisvc
listening for commands
performing business logic &
updating state// order-svc index.js
const bus = require(‘./bus’);
const create = require(‘./lib/create’);
bus.listen(‘order.create', (event) => {
create(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.created’, order, () => {
event.handle.ack();
});
});
});
order.create command
order.created
event
completing atomic transaction and allowing error handling
back end (a downstream service’s perspective)
web-uiweb-uiweb-app
svc
Commands
Events• Listen for commands and subscribe to events
• Performs business logic to process commands and events
• Update local state (optionally)
• Publish events to tell external services of updated state
svc-2
Events
Events
Let’s focus on:
Same thing!
Sample downstream service.
web-uiweb-uiweb-app
web-ui
web-uisvc
// fulfillment-svc index.js
const bus = require(‘./bus’);
const fulfill = require(‘./lib/fulfill’);
bus.subscribe(‘order.created', (event) => {
fulfill(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.fulfilled’, order, () => {
event.handle.ack();
});
});
});
order.created
order.fulfilled
subscribe for events instead of
listening for commands
no different, from any other service!
Multiple handlers?
svc
Commands
svc-2
Events
svc-2
Events
servicebus-register-handlers
convention based event handler definition for
distributed services using servicebus.
automatically registers
event & command
handlers saved as
modules in folder
initialize at startup
servicebus-register-handlers
const bus = require(‘./lib/bus'); // instantiate servicebus instance
const config = require('cconfig')();
const log = require('llog');
const registerHandlers = require('servicebus-register-handlers');
registerHandlers({
bus: bus,
handleError: function handleError (msg, err) {
log.error('error handling %s: %s. rejecting message w/ cid %s and correlationId %s.', msg.type,
err, msg.cid, this.correlationId);
log.error(err);
msg.handle.reject(function () {
throw err;
});
},
path: './lib/handlers',
queuePrefix: 'my-svc-name'
});
initialize at startup:
provide initialized bus
define your error handling
path to your handlers
prefix to differentiate similar queues
servicebus-register-handlers
const log = require("llog");
module.exports.ack = true;
module.exports.queueName = 'my-service-name-order';
module.exports.routingKey = "order.create";
module.exports.listen = function (event, cb) {
log.info(`handling listened event of type ${event.type} with routingKey $
{this.routingKey}`);
/*
do something with your event
*/
cb();
};
each handler is a file
no params marks success.
pass back error to retry or fail.
callback based transactions!
differentiate queues
for different services
specify which commands or
events to listen or subscribe to
servicebus-register-handlers
super simple messaging in node
npm install servicebus-register-handlers —save
What about the ‘work’ part?
const log = require("llog");
module.exports.ack = true;
module.exports.queueName = 'my-service-name-order';
module.exports.routingKey = "order.create";
module.exports.listen = function (event, cb) {
log.info(`handling listened event of type ${event.type}
with routingKey ${this.routingKey}`);
/*
do something with your event
*/
cb();
};
// order-svc index.js
const bus = require(‘./bus’);
const create = require(‘./lib/create’);
bus.listen(‘order.create', (event) => {
create(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.created’, order, () => {
event.handle.ack();
});
});
});
these parts
What about the ‘work’ part?
That’s up to you!
Need an audit trail? Targeting finance? Consider event sourcing.
*and my framework, ‘sourced’
Depending on your problem, the right choice could be
mongoose and mongodb, a graph database, an in-memory data
structure, or even flat files.
CQRS makes no assertions about what technology you should
use, and in fact frees you to make a different decision for each
particular problem.
and depends on the problem you’re solving
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
bus.use() middleware
into bus message
pipeline. middleware can
act on incoming and/or
outgoing messages
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
packages outgoing
message data and
adds useful type,
timestamp, and
other properties
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
adds a correlationId
for tracing related
commands and events
through your system
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
now, every failed
message will retry
3 times if errors occur.
after that, the message
will automatically be
put on an error queue
for human inspection!
And more!
distributed tracing middleware!
var trace = require('servicebus-trace');
bus.use(trace({
serviceName: 'my-service-name',
store: new trace.RedisStore({
host: config.REDIS_HOST || 'localhost',
port: config.REDIS_PORT || 6379
})
}));
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Recapping Back End Services
back end services
web-uiweb-uiweb-app
svc
Commands
Events• Listen for commands and subscribe to events
• Performs business logic to process commands and events
• Update local state (optionally)
• Publish events to tell external services of updated state
Recapping:
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Recapping Back End Services
wat wat watwat
Wat!
is
a
denormalizer?
back end
What’s a denormalizer?
front end
• Just another back end service
• Has one job to do
• Subscribe to all events that the UI cares about
• Persist events in a format most efficient for the UI to view
• Completes the eventually consistent, unidirectional flow
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web
client
denormalizer
Events
svc
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web
client
denormalizer
back end
What’s a denormalizer?
Events
front end
svc
Recapping the big picture.
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
Queries
Commands
unidirectional flow
eventually consistent
the dance!
Events
CQRS? That’s a myth!
Thanks!
We’ll sneak preview even more tooling for
easily building these systems in a future talk!
Matt Walters
github & twitter: @mateodelnorte
email: hi@iammattwalters.com
website: iammattwalters.com
rabbitmq.com
npmjs.com/package/servicebus
How to CQRS in Node
npmjs.com/package/servicebus-register-handlers
npmjs.com/package/servicebus-retry
npmjs.com/package/servicebus-trace

Mais conteúdo relacionado

Mais procurados

Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkPatrick LaRoche
 
Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009John Allspaw
 
Rackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & PackerRackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & PackerMarc Cluet
 
vSphere APIs for performance monitoring
vSphere APIs for performance monitoringvSphere APIs for performance monitoring
vSphere APIs for performance monitoringAlan Renouf
 
Backy - VM backup beyond bacula
Backy - VM backup beyond baculaBacky - VM backup beyond bacula
Backy - VM backup beyond baculaChristian Theune
 
232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현NAVER D2
 
Behind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling StorytimeBehind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling StorytimeSergeyChernyshev
 
Capacity Planning For LAMP
Capacity Planning For LAMPCapacity Planning For LAMP
Capacity Planning For LAMPJohn Allspaw
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011bobmcwhirter
 
Web versus Native: round 1!
Web versus Native: round 1!Web versus Native: round 1!
Web versus Native: round 1!Chris Mills
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxbobmcwhirter
 
Packer, where DevOps begins
Packer, where DevOps beginsPacker, where DevOps begins
Packer, where DevOps beginsJeff Hung
 
Empowering the "mobile web"
Empowering the "mobile web"Empowering the "mobile web"
Empowering the "mobile web"Chris Mills
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...POSSCON
 
Web optimization with service woker
Web optimization with service wokerWeb optimization with service woker
Web optimization with service wokerChen-Tien Tsai
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build SystemIntroduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build SystemHubSpot Product Team
 
How to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - WebinarHow to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - WebinarCommon Sense
 
Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존동수 장
 

Mais procurados (20)

Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM Talk
 
Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009
 
Rackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & PackerRackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & Packer
 
vSphere APIs for performance monitoring
vSphere APIs for performance monitoringvSphere APIs for performance monitoring
vSphere APIs for performance monitoring
 
Backy - VM backup beyond bacula
Backy - VM backup beyond baculaBacky - VM backup beyond bacula
Backy - VM backup beyond bacula
 
232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현
 
Behind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling StorytimeBehind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling Storytime
 
Capacity Planning For LAMP
Capacity Planning For LAMPCapacity Planning For LAMP
Capacity Planning For LAMP
 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
 
Web versus Native: round 1!
Web versus Native: round 1!Web versus Native: round 1!
Web versus Native: round 1!
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Packer, where DevOps begins
Packer, where DevOps beginsPacker, where DevOps begins
Packer, where DevOps begins
 
Empowering the "mobile web"
Empowering the "mobile web"Empowering the "mobile web"
Empowering the "mobile web"
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
 
Web optimization with service woker
Web optimization with service wokerWeb optimization with service woker
Web optimization with service woker
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build SystemIntroduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
 
How to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - WebinarHow to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - Webinar
 
Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존
 

Semelhante a How to CQRS in node: Eventually Consistent, Distributed Microservice Systems..

Architecting Microservices in .Net
Architecting Microservices in .NetArchitecting Microservices in .Net
Architecting Microservices in .NetRichard Banks
 
HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...Oleg Lobanov
 
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...Amazon Web Services
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
Get your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: BackendGet your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: BackendAckee
 
Vert.x for Microservices Architecture
Vert.x for Microservices ArchitectureVert.x for Microservices Architecture
Vert.x for Microservices ArchitectureIdan Fridman
 
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)Agile Lietuva
 
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...CodeMill digital skills
 
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...confluent
 
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...Lightbend
 
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...Ludovic Piot
 
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...Amazon Web Services
 
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, ParisSusanne Kaiser
 
Integration in the age of DevOps
Integration in the age of DevOpsIntegration in the age of DevOps
Integration in the age of DevOpsAlbert Wong
 
Reference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to KubernetesReference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to KubernetesRakesh Gujjarlapudi
 
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You DrawNagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You DrawNagios
 
Microservices and Friends
Microservices and FriendsMicroservices and Friends
Microservices and FriendsYun Zhi Lin
 
WinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release PipelinesWinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release PipelinesWinOps Conf
 
Evolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.jsEvolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.jsSteve Jamieson
 

Semelhante a How to CQRS in node: Eventually Consistent, Distributed Microservice Systems.. (20)

Architecting Microservices in .Net
Architecting Microservices in .NetArchitecting Microservices in .Net
Architecting Microservices in .Net
 
HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...
 
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
Get your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: BackendGet your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: Backend
 
Vert.x for Microservices Architecture
Vert.x for Microservices ArchitectureVert.x for Microservices Architecture
Vert.x for Microservices Architecture
 
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
 
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
 
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
 
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
 
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
 
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
 
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
 
Integration in the age of DevOps
Integration in the age of DevOpsIntegration in the age of DevOps
Integration in the age of DevOps
 
Reference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to KubernetesReference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to Kubernetes
 
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You DrawNagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
 
Micro service architecture
Micro service architectureMicro service architecture
Micro service architecture
 
Microservices and Friends
Microservices and FriendsMicroservices and Friends
Microservices and Friends
 
WinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release PipelinesWinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release Pipelines
 
Evolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.jsEvolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.js
 

Último

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 

Último (20)

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 

How to CQRS in node: Eventually Consistent, Distributed Microservice Systems..

  • 1. Matt Walters @mateodelnorte hi@iammattwalters.com How to CQRS in Node Eventually consistent architectures that scale and grow.
  • 2. It’s real. It works! Former TechStars Co. CTO. Now consultant. Built two businesses’ platforms from scratch using CQRS in Node. Both large, distributed systems. CQRS made both more maintainable and extendable. Marketing platform crunched the Twitter firehose in realtime. 3 Engineers managed around 20 services. - GoChime.com Bond Exchange with over $1.75B in trades. 6 engineers managed around 40 services. - Electronifie.com Open Source my tooling and frameworks. Other companies using them too! (and I’ll tell you how) That’s me ^^ !!
  • 3. When to CQRS • Realtime, reactive systems • When preferring small, modular services • When aiming for learning and growth • When aiming to grow or eventually split teams • Want ability to scale different parts of your system separately When not to CQRS • Standalone, static sites • Standalone, simple CRUD applications
  • 5. First, a primer from history. Bertrand Meyer, regarding object interfaces: “Every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer.” Long before CQRS was CQS: Command Query Separation. this guy
  • 6. Some Type doSomething() : void getSomeStuff() : Stuff Either change stuff<—— Or get stuff<—— CQS Command-Query Separation doAndGetStuff() : Stuff Never both! ——————
  • 7. Command-Query Responsibility Segregation A system-wide architecture that states - externally facing subsystems (apps and apis) send commands to perform actions which update the system’s state and request queries to determine system’s state. *Basically CQS on a system-wide scale. Calls between services should change stuff, or get stuff. Never both. CQRS
  • 8. Command-Query Responsibility Segregation CQRS also denotes that queries and command processing are provided by different subsystems. Queries are made against a data store. Commands are sent to and processed by services. CQRS One more thing!
  • 10. How about a larger system? denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web-uiweb-uiweb-api web client mobile client denormalizer svc-3 svc-2 web-uiweb-uisvc-1 Queries Commands unidirectional flow eventually consistent the dance! Events
  • 11. What’s that dance you’re doing? denormalizer dbdenormalizer dbdenormalizer db denormalizer svc-3 svc-2 web-uiweb-uisvc-1 the dance! chain reaction of events which play out as a result of an incoming command. each service subscribes to the events they care about choreography! (not orchestration) Events
  • 12. commands tell services when an actor wants an action clients send commands to instruct a service to do work commands are sent asynchronously; fire and forget commands are present-tense, directives: order.create web app order-svc order.create commands are sent directly to a single receiving service
  • 13. events tell the world when you’re done services publish to inform other services of work / actions performed, and state updated services publish (broadcast) events to any services that wish to subscribe events past-tense, describe what happened: order.created order-svc fulfillment-svc order.createdorder.created order.created order.created
  • 14. Two types of services denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web-uiweb-uiweb-api web client mobile client denormalizer svc-3 svc-2 web-uiweb-uisvc-1 front end
  • 17. web-uiweb-uiweb-app web client web-uiweb-uisvc front end (an app’s perspective) denormalizer dbdenormalizer dbdenormalizer db What’s different? Apps (and apis) still query a db to get the state of the system Never directly modify the db they read from Let’s focus on:
  • 18. web-uiweb-uiweb-app web client web-uiweb-uisvc denormalizer dbdenormalizer dbdenormalizer db What’s different? Instead, apps (and apis) send commands instructing services to perform an action Apps expect their read only representation of system state will eventually be updated in the denormalizer db Let’s focus on: front end (an app’s perspective) Commands are sent over a reliable transport (rabbitmq, kafka, zeromq, etc) to ensure delivery and eventual consistency
  • 19. Let’s pick a transport!
  • 20. rabbitmq messaging that just works • direct send to queue • fanout / topic routing • highly available • highly performant • used in financial exchanges, industrial applications and more • open source • free
  • 21. rabbitmq messaging that just works brew install rabbitmq
  • 23. servicebus super simple messaging in node • direct send • pub / sub / fanout / topic -routing • simple to set up • highly performant • used in financial exchanges, online advertising and more • open source • free • perfect for creating microservices!
  • 24. servicebus super simple messaging in node npm install servicebus —save
  • 27. Sending commands from the front end // web-app, onButtonClick. instead of updating db. const bus = require('servicebus').bus(); bus.send(‘order.create', { 
 order: { userId: userId, orderItems: items } }); web-uiweb-uiweb-app web-ui web-uisvc // fire and forget. command name command itself order.create command
  • 28. Then what from the front end? web-uiweb-uiweb-app denormalizer dbdenormalizer dbdenormalizer db We wait. • reactive / realtime: • mongo oplog tailing (meteor) • rethinkdb • redis notifications • couchdb • graphQL • polling • non-realtime: • product design: thanks! we’re processing your order! check back later for updates! queries!
  • 29. We wait. For the backend. Choreography. It’s eventually consistent!
  • 33. back end (a service’s perspective) web-uiweb-uiweb-app svc Commands Events• Listen for commands and subscribe to events • Performs business logic to process commands and events • Update local state (optionally) • Publish events to tell external services of updated state Let’s focus on:
  • 34. Sample service. web-uiweb-uiweb-app web-ui web-uisvc command name command object // order-svc index.js const bus = require(‘./bus’); const create = require(‘./lib/create’); bus.listen(‘order.create', (event) => { create(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.created’, order, () => { event.handle.ack(); }); }); }); service publishes to the world when it’s done! order.create command order.created event
  • 35. Sample service. web-uiweb-uiweb-app web-ui web-uisvc listening for commands performing business logic & updating state// order-svc index.js const bus = require(‘./bus’); const create = require(‘./lib/create’); bus.listen(‘order.create', (event) => { create(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.created’, order, () => { event.handle.ack(); }); }); }); order.create command order.created event completing atomic transaction and allowing error handling
  • 36. back end (a downstream service’s perspective) web-uiweb-uiweb-app svc Commands Events• Listen for commands and subscribe to events • Performs business logic to process commands and events • Update local state (optionally) • Publish events to tell external services of updated state svc-2 Events Events Let’s focus on: Same thing!
  • 37. Sample downstream service. web-uiweb-uiweb-app web-ui web-uisvc // fulfillment-svc index.js const bus = require(‘./bus’); const fulfill = require(‘./lib/fulfill’); bus.subscribe(‘order.created', (event) => { fulfill(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.fulfilled’, order, () => { event.handle.ack(); }); }); }); order.created order.fulfilled subscribe for events instead of listening for commands no different, from any other service!
  • 39. servicebus-register-handlers convention based event handler definition for distributed services using servicebus. automatically registers event & command handlers saved as modules in folder initialize at startup
  • 40. servicebus-register-handlers const bus = require(‘./lib/bus'); // instantiate servicebus instance const config = require('cconfig')(); const log = require('llog'); const registerHandlers = require('servicebus-register-handlers'); registerHandlers({ bus: bus, handleError: function handleError (msg, err) { log.error('error handling %s: %s. rejecting message w/ cid %s and correlationId %s.', msg.type, err, msg.cid, this.correlationId); log.error(err); msg.handle.reject(function () { throw err; }); }, path: './lib/handlers', queuePrefix: 'my-svc-name' }); initialize at startup: provide initialized bus define your error handling path to your handlers prefix to differentiate similar queues
  • 41. servicebus-register-handlers const log = require("llog"); module.exports.ack = true; module.exports.queueName = 'my-service-name-order'; module.exports.routingKey = "order.create"; module.exports.listen = function (event, cb) { log.info(`handling listened event of type ${event.type} with routingKey $ {this.routingKey}`); /* do something with your event */ cb(); }; each handler is a file no params marks success. pass back error to retry or fail. callback based transactions! differentiate queues for different services specify which commands or events to listen or subscribe to
  • 42. servicebus-register-handlers super simple messaging in node npm install servicebus-register-handlers —save
  • 43. What about the ‘work’ part? const log = require("llog"); module.exports.ack = true; module.exports.queueName = 'my-service-name-order'; module.exports.routingKey = "order.create"; module.exports.listen = function (event, cb) { log.info(`handling listened event of type ${event.type} with routingKey ${this.routingKey}`); /* do something with your event */ cb(); }; // order-svc index.js const bus = require(‘./bus’); const create = require(‘./lib/create’); bus.listen(‘order.create', (event) => { create(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.created’, order, () => { event.handle.ack(); }); }); }); these parts
  • 44. What about the ‘work’ part? That’s up to you! Need an audit trail? Targeting finance? Consider event sourcing. *and my framework, ‘sourced’ Depending on your problem, the right choice could be mongoose and mongodb, a graph database, an in-memory data structure, or even flat files. CQRS makes no assertions about what technology you should use, and in fact frees you to make a different decision for each particular problem. and depends on the problem you’re solving
  • 45. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; bus.use() middleware into bus message pipeline. middleware can act on incoming and/or outgoing messages
  • 46. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; packages outgoing message data and adds useful type, timestamp, and other properties
  • 47. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; adds a correlationId for tracing related commands and events through your system
  • 48. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; now, every failed message will retry 3 times if errors occur. after that, the message will automatically be put on an error queue for human inspection!
  • 49. And more! distributed tracing middleware! var trace = require('servicebus-trace'); bus.use(trace({ serviceName: 'my-service-name', store: new trace.RedisStore({ host: config.REDIS_HOST || 'localhost', port: config.REDIS_PORT || 6379 }) }));
  • 51. back end services web-uiweb-uiweb-app svc Commands Events• Listen for commands and subscribe to events • Performs business logic to process commands and events • Update local state (optionally) • Publish events to tell external services of updated state Recapping:
  • 54. back end What’s a denormalizer? front end • Just another back end service • Has one job to do • Subscribe to all events that the UI cares about • Persist events in a format most efficient for the UI to view • Completes the eventually consistent, unidirectional flow denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web client denormalizer Events svc
  • 56. Recapping the big picture. denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web-uiweb-uiweb-api web client mobile client denormalizer svc-3 svc-2 web-uiweb-uisvc-1 Queries Commands unidirectional flow eventually consistent the dance! Events
  • 58. Thanks! We’ll sneak preview even more tooling for easily building these systems in a future talk!
  • 59. Matt Walters github & twitter: @mateodelnorte email: hi@iammattwalters.com website: iammattwalters.com rabbitmq.com npmjs.com/package/servicebus How to CQRS in Node npmjs.com/package/servicebus-register-handlers npmjs.com/package/servicebus-retry npmjs.com/package/servicebus-trace