SlideShare a Scribd company logo
1 of 53
Download to read offline
Full Stack Reactive in Practice
Presenting a real-world CQRS
(command query responsibility
segregation) and ES (event
sourcing) architecture.
Kevin Webber
Director of Engineering @
Reading Plus
w: kevinwebber.ca
m: medium.com/@kvnwbbr
t: @kvnwbbr
— Reading Plus is an adaptive platform that helps K-12
students become successful readers and lifelong
learners
— We will be applying reactive techniques and
technologies to a mission with purpose
— Find us at https://readingplus.com and stay tuned for
upcoming engineering opportunities
Why Reactive?
— React, Vue, and other front-end frameworks are
enabling innovative user experiences
Why Reactive?
— React, Vue, and other front-end frameworks are
enabling innovative user experiences
— Meanwhile, relational databases continue to dominate
the server side
Why Reactive?
— React, Vue, and other front-end frameworks are
enabling innovative user experiences
— Meanwhile, relational databases continue to dominate
the server side
— Reactive principles and frameworks help create an
end-to-end event-driven channel, all the way up and
all the way down
Traditional architecture
— Unbounded in complexity and
side effects
— Putting React or Vue on top
won't help much
— Batch-mode, high-latency,
high-failure rates
— Has an impact
— Customer happiness?
— Developer joy?
— Visit TheDailyWTF :)
What we will cover
All references and examples will be in Java.
1. Designing reactive systems → Event Storming, DDD
2. Implementing reactive systems → Lagom, Play, Akka
3. Deploying reactive systems → sbt, Kubernetes
Part 1. Designing Reactive Systems
— Raw ingredients
— Commands & events
— Inception
— Event storming & DDD
— Fidelity
— Event modeling
— Handoff
— User stories
Systems have been event driven for centuries!
Events are
— Interesting things, that have
— happened in the past.
Event sourcing
— Commands are applied
against an entity, the entity
can accept or reject a
command
— If accepted, an entity will
generate an event and then
apply that event in order to
change state
Defining aggregate boundaries
— Structures implementation
around related items
— The yellow sticky in the
middle represents state
Defining bounded contexts
— Group together related
business concepts
— Contain domain complexity
— A single person can master an
aggregate
— A single team can master a
bounded context
How do we model a bounded context?
— Arrange events in linear order by time
— Events cluster into closely related groups (aggregates)
— Aggregates cluster into closely related groups
(bounded contexts)
— Event Storming helps discover the problem space
— Event Modeling creates a blueprint for a solution
From https://eventmodeling.org/posts/what-is-event-
modeling/
Essential learning resources
— Book: Event Storming by Alberto Brandolini
— Book: Domain-Driven Design Distilled by Vaughn
Vernon
— Website: Event Modeling by Adam Dymitruk
Part 2. Implementation
— Tools
— Lagom, Play, and Akka
— Cassandra and Kafka
— Pa!erns
— Event sourcing, CQRS
— Architecture
— Interface, BFF, services
— Integration
— Point to point, streaming,
pub/sub
Reactive Stock Trader
— Reference application for Reactive in Practice
— Vue, Lagom, Play, Akka, Cassandra, Kafka,
Kubernetes
— Bounded contexts
— Portfolio
— Broker
— Wire transfers
— https://github.com/RedElastic/reactive-stock-trader
Placing a wire transfer
We'll cover the command channel first.
1. Create command
2. Send over REST
3. Direct command to entity
4. Create event
5. Change state
6. Publish event
Submit transfer request (Vue.js)
onSubmit() {
this.submitted = true;
submitTransfer(this.form)
.then(() => {
this.submitted = false;
this.onReset();
});
},
API gateway
— Backend for Frontend (BFF) is
a pattern that involves
creating a 1:1 relationship
between backends and UIs
— The BFF then handles all calls
to various underlying
microservices (Portfolio,
Broker, Wires, etc)
— Also performs authentication,
authorization, etc
Play (command side API)
@Override
public ServiceCall<Transfer, TransferId> transferFunds() {
TransferId transferId = TransferId.newId();
return transfer ->
transferRepository
.get(transferId) // 1 (get reference to entity)
.ask(TransferCommand.TransferFunds.builder()
.source(transfer.getSourceAccount())
.destination(transfer.getDestinationAccount())
.amount(transfer.getFunds())
.build()
) // 2 (ask pattern)
.thenApply(done -> transferId);
}
BFF and Service Integration
— Play routes all commands and
queries to Lagom
microservices
— Lagom is a framework built on
top of Akka for developing
reactive microservices
— Based on the principles of
CQRS (Command Query
Responsibility Segregation)
Lagom (aggregates / entities)
— Based around persistent entities (aka, aggregates)
— Stored in memory for fast access
— Can be recovered via Cassandra as the event log
public class TransferEntity extends
PersistentEntity<TransferCommand,
TransferEvent,
Optional<TransferState>> {
// ...
}
Lagom (event sourcing)
— No mutable data, only
immutable state
— State is only changed on
successful event application
— Events are journaled
— Entity can always recover in-
memory by replaying events
from the journal
— Entities are not queried
directly, read-side queries are
backed by views
State machines
Let's say we're modeling an ATM
machine...
— This ATM machine has three
different states
— Each state has a different
behaviour for the same input
https://www.uml-diagrams.org/
state-machine-diagrams.html
Lagom (event sourcing)
private Behavior empty() {
BehaviorBuilder builder = newBehaviorBuilder(Optional.empty());
builder.setCommandHandler(TransferCommand.TransferFunds.class,
(cmd, ctx) -> { // 1 (handler is invoked from ask pattern)
TransferDetails transferDetails = TransferDetails.builder()
.source(cmd.getSource())
.destination(cmd.getDestination())
.amount(cmd.getAmount())
.build(); // 2 (build up details of xfer)
ObjectMapper mapper = new ObjectMapper();
TransferUpdated tc = buildTransferUpdated(
transferDetails, "Transfer Initiated");
publishedTopic.publish(
mapper.valueToTree(tc).toString()); // 3 (publish to stream)
return ctx.thenPersist(
new TransferEvent
.TransferInitiated(
getTransferId(), transferDetails),
evt -> ctx.reply(Done.getInstance())
); // 4 (persist event & return ID)
});
builder.setEventHandlerChangingBehavior(
TransferEvent.TransferInitiated.class,
this::fundsRequested); // 5 (change state)
return builder.build();
}
Views
— Read side processors build a
precomputed table
— Queries are only against
precomputed tables
— Use this to populate data on
initial page load
Creating a portfolio
1. When each portfolio is
created, we create a portfolio
entity and then persist the
create event to the journal
2. A read side processor
subscribes to journal updates
3. With each update, the read
side processor updates a
projected view
Let's cover #3...
Lagom ReadSide processor
Update a precomputed query table (Cassandra) on every
new event we subscribe to.
@Override
public ReadSideHandler<PortfolioEvent> buildHandler() {
return readSide.<PortfolioEvent>builder("portfolio_offset") // 1
.setGlobalPrepare(this::prepareCreateTables) // 2
.setPrepare(tag -> prepareWritePortfolios()) // 3
.setEventHandler(Opened.class, this::processPortfolioChanged) // 4
.build();
}
private CompletionStage<Done> prepareWritePortfolios() {
return session
.prepare("INSERT INTO portfolio_summary (portfolioId, name) VALUES (?, ?)")
.thenApply(ps -> {
this.writePortfolios = ps;
return Done.getInstance();
});
}
Queries are then executed against the projected view for
a vastly lower latency user experience.
@Override
public ServiceCall<NotUsed, PSequence<PortfolioSummary>> getAllPortfolios() {
return request -> {
CompletionStage<PSequence<PortfolioSummary>> result =
db.selectAll("SELECT portfolioId, name FROM portfolio_summary;")
.thenApply(rows -> {
List<PortfolioSummary> summary = rows.stream().map(row ->
PortfolioSummary.builder()
.portfolioId(new PortfolioId(
row.getString("portfolioId")))
.name(row.getString("name"))
.build())
.collect(Collectors.toList());
return TreePVector.from(summary);
});
return result;
};
}
Streaming
1. Render initial page with precomputed view over HTTP/
REST
2. Switch to unidirectional streaming for updates (events
over WS)
3. Commands over REST will still cause full page
refreshes (can change unidirectional stream to BiDi
stream in future)
Instead, let's use the Lagom PubSub API to push updates
to the UI in real-time...
Streaming (Lagom)
This code exposes a Reactive Streams Source via Lagom,
which Play can then "attach" to.
@Override
public ServiceCall<NotUsed, Source<String, ?>> transferStream() {
return request -> {
// subscribe to events on a specific topic ("transfer")
final PubSubRef<String> topic =
pubSub.refFor(
TopicId.of(String.class,
"transfer"));
// return the Source as a future (standard async Java 8)
return CompletableFuture.completedFuture(topic.subscriber());
};
}
Streaming (architecture)
PubSub works by broadcasting
events to subscribers:
— Publisher is TransferEntity
— Subscriber is
WireTransferServiceImpl
— This will create a streaming
Source
Create a streaming connection all the way down.
WireTransferController
public WebSocket ws() {
return WebSocket.Text.acceptOrResult(req -> {
return wireTransferService
.transferStream()
.invoke()
.thenApply(source -> {
return F.Either.Right(
Flow.fromSinkAndSource(
Sink.ignore(),
source
)
);
});
});
}
WebSockets (Vue.js)
connect() {
this.socket = new WebSocket(
"ws://localhost:9000/api/transfer/stream");
this.socket.onopen = () => {
this.socket.onmessage = (e) => {
let event = JSON.parse(e.data);
var index = -1;
// 1. determine if we're updating a row (initiated)
// or adding a new row (completed)
for (var i = 0; i < this.transfers.length; i++) {
if (this.transfers[i].id === event.id) {
index = i;
break;
}
}
if (index === -1) {
// unshift is similar to push, but prepends
this.transfers.unshift({
// ... 3. create object with id, status, etc
});
} else {
let t = {
// ... 4. create object with id, status, etc
};
this.transfers.splice(index, 1, t);
this.updateCashOnHand();
}
};
};
}
Part 3. Deployment
— Packaging
— sbt, service boundaries
— Testing
— Deploying to Minikube
— Handling dependencies in
k8s such as Cassandra,
Kafka
— Deployment
— Production deployments
Final architecture
Reactive Stock Trader needs...
— Formation of a cluster so Lagom entities can stay
available in memory
— Connection to Cassandra and Kafka (in a "high-
availability" clustered configuration)
— Cassandra for the backing journal
— Kafka for the Lagom Message Broker API for
communication between services
Aggregates are stored in-memory while the journal is
persisted to Cassandra.
In this example, we have a three node Kubernetes
cluster, with two bounded contexts spread across those
nodes. This offers resilience and scale.
Deploying to Minikube
Instructions are available here to help deploy Reactive
Stock Trader (along with Cassandra and Kafka) to
Minikube:
https://github.com/RedElastic/reactive-stock-trader/tree/
master/deploy/instructions
Conclusion
— CQRS separates writes and reads for reliability and
performance
— Event sourcing eliminates mutability concerns of
relational databases while preserving their query
capabilities
— Operationally Lagom is cloud-native and ready to
deploy to AWS, Azure, GCP, etc, via Kubernetes
What about serverless?
— For the foreseeable future we
need to understand how our
software interacts with the
runtime environment
— A serverless component may
be part of a reactive system,
but is not a replacement for a
reactive system
— Reactive systems enable
portability across cloud
vendors, whereas many
serverless offerings lock us in
Reactive in Practice
For a complete look at this
material, visit IBM Developer and
check out Reactive in Practice, a
12 part series (parts 8-12 to be
published mid-September).
https://developer.ibm.com/series/
reactive-in-practice/
Thanks to Dana Harrington,
Lightbend, and IBM.

More Related Content

What's hot

A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...
A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...
A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...
confluent
 
Stateful, Stateless and Serverless - Running Apache Kafka® on Kubernetes
Stateful, Stateless and Serverless - Running Apache Kafka® on KubernetesStateful, Stateless and Serverless - Running Apache Kafka® on Kubernetes
Stateful, Stateless and Serverless - Running Apache Kafka® on Kubernetes
confluent
 
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
 

What's hot (20)

Digital Transformation with Kubernetes, Containers, and Microservices
Digital Transformation with Kubernetes, Containers, and MicroservicesDigital Transformation with Kubernetes, Containers, and Microservices
Digital Transformation with Kubernetes, Containers, and Microservices
 
Building a Web Application with Kafka as your Database
Building a Web Application with Kafka as your DatabaseBuilding a Web Application with Kafka as your Database
Building a Web Application with Kafka as your Database
 
Pivoting Spring XD to Spring Cloud Data Flow with Sabby Anandan
Pivoting Spring XD to Spring Cloud Data Flow with Sabby AnandanPivoting Spring XD to Spring Cloud Data Flow with Sabby Anandan
Pivoting Spring XD to Spring Cloud Data Flow with Sabby Anandan
 
A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...
A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...
A Marriage of Lambda and Kappa: Supporting Iterative Development of an Event ...
 
3 Ways to Deliver an Elastic, Cost-Effective Cloud Architecture (ANZ)
3 Ways to Deliver an Elastic, Cost-Effective Cloud Architecture (ANZ)3 Ways to Deliver an Elastic, Cost-Effective Cloud Architecture (ANZ)
3 Ways to Deliver an Elastic, Cost-Effective Cloud Architecture (ANZ)
 
Bank of China (HK) Tech Talk 1: Dive Into Apache Kafka
Bank of China (HK) Tech Talk 1: Dive Into Apache KafkaBank of China (HK) Tech Talk 1: Dive Into Apache Kafka
Bank of China (HK) Tech Talk 1: Dive Into Apache Kafka
 
All Streams Ahead! ksqlDB Workshop ANZ
All Streams Ahead! ksqlDB Workshop ANZAll Streams Ahead! ksqlDB Workshop ANZ
All Streams Ahead! ksqlDB Workshop ANZ
 
What's New in Confluent Platform 5.5
What's New in Confluent Platform 5.5What's New in Confluent Platform 5.5
What's New in Confluent Platform 5.5
 
Live Event Debugging With ksqlDB at Reddit | Hannah Hagen and Paul Kiernan, R...
Live Event Debugging With ksqlDB at Reddit | Hannah Hagen and Paul Kiernan, R...Live Event Debugging With ksqlDB at Reddit | Hannah Hagen and Paul Kiernan, R...
Live Event Debugging With ksqlDB at Reddit | Hannah Hagen and Paul Kiernan, R...
 
Stateful, Stateless and Serverless - Running Apache Kafka® on Kubernetes
Stateful, Stateless and Serverless - Running Apache Kafka® on KubernetesStateful, Stateless and Serverless - Running Apache Kafka® on Kubernetes
Stateful, Stateless and Serverless - Running Apache Kafka® on Kubernetes
 
Monitoring Large-Scale Apache Spark Clusters at Databricks
Monitoring Large-Scale Apache Spark Clusters at DatabricksMonitoring Large-Scale Apache Spark Clusters at Databricks
Monitoring Large-Scale Apache Spark Clusters at Databricks
 
Diving into the Deep End - Kafka Connect
Diving into the Deep End - Kafka ConnectDiving into the Deep End - Kafka Connect
Diving into the Deep End - Kafka Connect
 
Time series-analysis-using-an-event-streaming-platform -_v3_final
Time series-analysis-using-an-event-streaming-platform -_v3_finalTime series-analysis-using-an-event-streaming-platform -_v3_final
Time series-analysis-using-an-event-streaming-platform -_v3_final
 
Migrating from One Cloud Provider to Another (Without Losing Your Data or You...
Migrating from One Cloud Provider to Another (Without Losing Your Data or You...Migrating from One Cloud Provider to Another (Without Losing Your Data or You...
Migrating from One Cloud Provider to Another (Without Losing Your Data or You...
 
Bravo Six, Going Realtime. Transitioning Activision Data Pipeline to Streamin...
Bravo Six, Going Realtime. Transitioning Activision Data Pipeline to Streamin...Bravo Six, Going Realtime. Transitioning Activision Data Pipeline to Streamin...
Bravo Six, Going Realtime. Transitioning Activision Data Pipeline to Streamin...
 
Reactive Fast Data & the Data Lake with Akka, Kafka, Spark
Reactive Fast Data & the Data Lake with Akka, Kafka, SparkReactive Fast Data & the Data Lake with Akka, Kafka, Spark
Reactive Fast Data & the Data Lake with Akka, Kafka, Spark
 
Flattening the Curve with Kafka (Rishi Tarar, Northrop Grumman Corp.) Kafka S...
Flattening the Curve with Kafka (Rishi Tarar, Northrop Grumman Corp.) Kafka S...Flattening the Curve with Kafka (Rishi Tarar, Northrop Grumman Corp.) Kafka S...
Flattening the Curve with Kafka (Rishi Tarar, Northrop Grumman Corp.) Kafka S...
 
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...
 
How Credit Karma Makes Real-Time Decisions For 60 Million Users With Akka Str...
How Credit Karma Makes Real-Time Decisions For 60 Million Users With Akka Str...How Credit Karma Makes Real-Time Decisions For 60 Million Users With Akka Str...
How Credit Karma Makes Real-Time Decisions For 60 Million Users With Akka Str...
 
Keynote: Jay Kreps, Confluent | Kafka ♥ Cloud | Kafka Summit 2020
Keynote: Jay Kreps, Confluent | Kafka ♥ Cloud | Kafka Summit 2020Keynote: Jay Kreps, Confluent | Kafka ♥ Cloud | Kafka Summit 2020
Keynote: Jay Kreps, Confluent | Kafka ♥ Cloud | Kafka Summit 2020
 

Similar to Full Stack Reactive In Practice

Coldbox developer training – session 5
Coldbox developer training – session 5Coldbox developer training – session 5
Coldbox developer training – session 5
Billie Berzinskas
 
WS-VLAM workflow
WS-VLAM workflowWS-VLAM workflow
WS-VLAM workflow
guest6295d0
 

Similar to Full Stack Reactive In Practice (20)

Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Scala in increasingly demanding environments - DATABIZ
Scala in increasingly demanding environments - DATABIZScala in increasingly demanding environments - DATABIZ
Scala in increasingly demanding environments - DATABIZ
 
Our way to microservices
Our way to microservicesOur way to microservices
Our way to microservices
 
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
 
Andrii Dembitskyi "Events in our applications Event bus and distributed systems"
Andrii Dembitskyi "Events in our applications Event bus and distributed systems"Andrii Dembitskyi "Events in our applications Event bus and distributed systems"
Andrii Dembitskyi "Events in our applications Event bus and distributed systems"
 
Tuning and optimizing webcenter spaces application white paper
Tuning and optimizing webcenter spaces application white paperTuning and optimizing webcenter spaces application white paper
Tuning and optimizing webcenter spaces application white paper
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
 
Coldbox developer training – session 5
Coldbox developer training – session 5Coldbox developer training – session 5
Coldbox developer training – session 5
 
Apache Samza 1.0 - What's New, What's Next
Apache Samza 1.0 - What's New, What's NextApache Samza 1.0 - What's New, What's Next
Apache Samza 1.0 - What's New, What's Next
 
Os Haase
Os HaaseOs Haase
Os Haase
 
An approach to responsive, realtime with Backbone.js and WebSockets
An approach to responsive, realtime with Backbone.js and WebSocketsAn approach to responsive, realtime with Backbone.js and WebSockets
An approach to responsive, realtime with Backbone.js and WebSockets
 
Fabric - Realtime stream processing framework
Fabric - Realtime stream processing frameworkFabric - Realtime stream processing framework
Fabric - Realtime stream processing framework
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Walking Through Cloud Serving at Yahoo!
Walking Through Cloud Serving at Yahoo!Walking Through Cloud Serving at Yahoo!
Walking Through Cloud Serving at Yahoo!
 
WS-VLAM workflow
WS-VLAM workflowWS-VLAM workflow
WS-VLAM workflow
 
Struts
StrutsStruts
Struts
 
Apache Beam: A unified model for batch and stream processing data
Apache Beam: A unified model for batch and stream processing dataApache Beam: A unified model for batch and stream processing data
Apache Beam: A unified model for batch and stream processing data
 
Let's react - Meetup
Let's react - MeetupLet's react - Meetup
Let's react - Meetup
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMS
 
Cloud Serving Engine
Cloud Serving EngineCloud Serving Engine
Cloud Serving Engine
 

More from Lightbend

More from Lightbend (20)

IoT 'Megaservices' - High Throughput Microservices with Akka
IoT 'Megaservices' - High Throughput Microservices with AkkaIoT 'Megaservices' - High Throughput Microservices with Akka
IoT 'Megaservices' - High Throughput Microservices with Akka
 
How Akka Cluster Works: Actors Living in a Cluster
How Akka Cluster Works: Actors Living in a ClusterHow Akka Cluster Works: Actors Living in a Cluster
How Akka Cluster Works: Actors Living in a Cluster
 
The Reactive Principles: Eight Tenets For Building Cloud Native Applications
The Reactive Principles: Eight Tenets For Building Cloud Native ApplicationsThe Reactive Principles: Eight Tenets For Building Cloud Native Applications
The Reactive Principles: Eight Tenets For Building Cloud Native Applications
 
Putting the 'I' in IoT - Building Digital Twins with Akka Microservices
Putting the 'I' in IoT - Building Digital Twins with Akka MicroservicesPutting the 'I' in IoT - Building Digital Twins with Akka Microservices
Putting the 'I' in IoT - Building Digital Twins with Akka Microservices
 
Cloudstate - Towards Stateful Serverless
Cloudstate - Towards Stateful ServerlessCloudstate - Towards Stateful Serverless
Cloudstate - Towards Stateful Serverless
 
Digital Transformation from Monoliths to Microservices to Serverless and Beyond
Digital Transformation from Monoliths to Microservices to Serverless and BeyondDigital Transformation from Monoliths to Microservices to Serverless and Beyond
Digital Transformation from Monoliths to Microservices to Serverless and Beyond
 
Akka Anti-Patterns, Goodbye: Six Features of Akka 2.6
Akka Anti-Patterns, Goodbye: Six Features of Akka 2.6Akka Anti-Patterns, Goodbye: Six Features of Akka 2.6
Akka Anti-Patterns, Goodbye: Six Features of Akka 2.6
 
Microservices, Kubernetes, and Application Modernization Done Right
Microservices, Kubernetes, and Application Modernization Done RightMicroservices, Kubernetes, and Application Modernization Done Right
Microservices, Kubernetes, and Application Modernization Done Right
 
Akka and Kubernetes: A Symbiotic Love Story
Akka and Kubernetes: A Symbiotic Love StoryAkka and Kubernetes: A Symbiotic Love Story
Akka and Kubernetes: A Symbiotic Love Story
 
Scala 3 Is Coming: Martin Odersky Shares What To Know
Scala 3 Is Coming: Martin Odersky Shares What To KnowScala 3 Is Coming: Martin Odersky Shares What To Know
Scala 3 Is Coming: Martin Odersky Shares What To Know
 
Migrating From Java EE To Cloud-Native Reactive Systems
Migrating From Java EE To Cloud-Native Reactive SystemsMigrating From Java EE To Cloud-Native Reactive Systems
Migrating From Java EE To Cloud-Native Reactive Systems
 
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming ApplicationsRunning Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
Running Kafka On Kubernetes With Strimzi For Real-Time Streaming Applications
 
Designing Events-First Microservices For A Cloud Native World
Designing Events-First Microservices For A Cloud Native WorldDesigning Events-First Microservices For A Cloud Native World
Designing Events-First Microservices For A Cloud Native World
 
Scala Security: Eliminate 200+ Code-Level Threats With Fortify SCA For Scala
Scala Security: Eliminate 200+ Code-Level Threats With Fortify SCA For ScalaScala Security: Eliminate 200+ Code-Level Threats With Fortify SCA For Scala
Scala Security: Eliminate 200+ Code-Level Threats With Fortify SCA For Scala
 
A Glimpse At The Future Of Apache Spark 3.0 With Deep Learning And Kubernetes
A Glimpse At The Future Of Apache Spark 3.0 With Deep Learning And KubernetesA Glimpse At The Future Of Apache Spark 3.0 With Deep Learning And Kubernetes
A Glimpse At The Future Of Apache Spark 3.0 With Deep Learning And Kubernetes
 
Akka and Kubernetes: Reactive From Code To Cloud
Akka and Kubernetes: Reactive From Code To CloudAkka and Kubernetes: Reactive From Code To Cloud
Akka and Kubernetes: Reactive From Code To Cloud
 
Hands On With Spark: Creating A Fast Data Pipeline With Structured Streaming ...
Hands On With Spark: Creating A Fast Data Pipeline With Structured Streaming ...Hands On With Spark: Creating A Fast Data Pipeline With Structured Streaming ...
Hands On With Spark: Creating A Fast Data Pipeline With Structured Streaming ...
 
How Akka Works: Visualize And Demo Akka With A Raspberry-Pi Cluster
How Akka Works: Visualize And Demo Akka With A Raspberry-Pi ClusterHow Akka Works: Visualize And Demo Akka With A Raspberry-Pi Cluster
How Akka Works: Visualize And Demo Akka With A Raspberry-Pi Cluster
 
Ready for Fast Data: How Lightbend Enables Teams To Build Real-Time, Streamin...
Ready for Fast Data: How Lightbend Enables Teams To Build Real-Time, Streamin...Ready for Fast Data: How Lightbend Enables Teams To Build Real-Time, Streamin...
Ready for Fast Data: How Lightbend Enables Teams To Build Real-Time, Streamin...
 
Akka Streams And Kafka Streams: Where Microservices Meet Fast Data
Akka Streams And Kafka Streams: Where Microservices Meet Fast DataAkka Streams And Kafka Streams: Where Microservices Meet Fast Data
Akka Streams And Kafka Streams: Where Microservices Meet Fast Data
 

Recently uploaded

CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
anilsa9823
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
anilsa9823
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Recently uploaded (20)

call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 

Full Stack Reactive In Practice

  • 1.
  • 2. Full Stack Reactive in Practice Presenting a real-world CQRS (command query responsibility segregation) and ES (event sourcing) architecture. Kevin Webber Director of Engineering @ Reading Plus w: kevinwebber.ca m: medium.com/@kvnwbbr t: @kvnwbbr
  • 3. — Reading Plus is an adaptive platform that helps K-12 students become successful readers and lifelong learners — We will be applying reactive techniques and technologies to a mission with purpose — Find us at https://readingplus.com and stay tuned for upcoming engineering opportunities
  • 4. Why Reactive? — React, Vue, and other front-end frameworks are enabling innovative user experiences
  • 5. Why Reactive? — React, Vue, and other front-end frameworks are enabling innovative user experiences — Meanwhile, relational databases continue to dominate the server side
  • 6. Why Reactive? — React, Vue, and other front-end frameworks are enabling innovative user experiences — Meanwhile, relational databases continue to dominate the server side — Reactive principles and frameworks help create an end-to-end event-driven channel, all the way up and all the way down
  • 7. Traditional architecture — Unbounded in complexity and side effects — Putting React or Vue on top won't help much — Batch-mode, high-latency, high-failure rates — Has an impact — Customer happiness? — Developer joy? — Visit TheDailyWTF :)
  • 8. What we will cover All references and examples will be in Java. 1. Designing reactive systems → Event Storming, DDD 2. Implementing reactive systems → Lagom, Play, Akka 3. Deploying reactive systems → sbt, Kubernetes
  • 9. Part 1. Designing Reactive Systems — Raw ingredients — Commands & events — Inception — Event storming & DDD — Fidelity — Event modeling — Handoff — User stories
  • 10. Systems have been event driven for centuries!
  • 11. Events are — Interesting things, that have — happened in the past.
  • 12. Event sourcing — Commands are applied against an entity, the entity can accept or reject a command — If accepted, an entity will generate an event and then apply that event in order to change state
  • 13. Defining aggregate boundaries — Structures implementation around related items — The yellow sticky in the middle represents state
  • 14. Defining bounded contexts — Group together related business concepts — Contain domain complexity — A single person can master an aggregate — A single team can master a bounded context
  • 15. How do we model a bounded context? — Arrange events in linear order by time — Events cluster into closely related groups (aggregates) — Aggregates cluster into closely related groups (bounded contexts) — Event Storming helps discover the problem space — Event Modeling creates a blueprint for a solution
  • 17. Essential learning resources — Book: Event Storming by Alberto Brandolini — Book: Domain-Driven Design Distilled by Vaughn Vernon — Website: Event Modeling by Adam Dymitruk
  • 18. Part 2. Implementation — Tools — Lagom, Play, and Akka — Cassandra and Kafka — Pa!erns — Event sourcing, CQRS — Architecture — Interface, BFF, services — Integration — Point to point, streaming, pub/sub
  • 19. Reactive Stock Trader — Reference application for Reactive in Practice — Vue, Lagom, Play, Akka, Cassandra, Kafka, Kubernetes — Bounded contexts — Portfolio — Broker — Wire transfers — https://github.com/RedElastic/reactive-stock-trader
  • 20.
  • 21. Placing a wire transfer We'll cover the command channel first. 1. Create command 2. Send over REST 3. Direct command to entity 4. Create event 5. Change state 6. Publish event
  • 22.
  • 23. Submit transfer request (Vue.js) onSubmit() { this.submitted = true; submitTransfer(this.form) .then(() => { this.submitted = false; this.onReset(); }); },
  • 24. API gateway — Backend for Frontend (BFF) is a pattern that involves creating a 1:1 relationship between backends and UIs — The BFF then handles all calls to various underlying microservices (Portfolio, Broker, Wires, etc) — Also performs authentication, authorization, etc
  • 25. Play (command side API) @Override public ServiceCall<Transfer, TransferId> transferFunds() { TransferId transferId = TransferId.newId(); return transfer -> transferRepository .get(transferId) // 1 (get reference to entity) .ask(TransferCommand.TransferFunds.builder() .source(transfer.getSourceAccount()) .destination(transfer.getDestinationAccount()) .amount(transfer.getFunds()) .build() ) // 2 (ask pattern) .thenApply(done -> transferId); }
  • 26. BFF and Service Integration — Play routes all commands and queries to Lagom microservices — Lagom is a framework built on top of Akka for developing reactive microservices — Based on the principles of CQRS (Command Query Responsibility Segregation)
  • 27. Lagom (aggregates / entities) — Based around persistent entities (aka, aggregates) — Stored in memory for fast access — Can be recovered via Cassandra as the event log public class TransferEntity extends PersistentEntity<TransferCommand, TransferEvent, Optional<TransferState>> { // ... }
  • 28. Lagom (event sourcing) — No mutable data, only immutable state — State is only changed on successful event application — Events are journaled — Entity can always recover in- memory by replaying events from the journal — Entities are not queried directly, read-side queries are backed by views
  • 29. State machines Let's say we're modeling an ATM machine... — This ATM machine has three different states — Each state has a different behaviour for the same input https://www.uml-diagrams.org/ state-machine-diagrams.html
  • 30. Lagom (event sourcing) private Behavior empty() { BehaviorBuilder builder = newBehaviorBuilder(Optional.empty()); builder.setCommandHandler(TransferCommand.TransferFunds.class, (cmd, ctx) -> { // 1 (handler is invoked from ask pattern) TransferDetails transferDetails = TransferDetails.builder() .source(cmd.getSource()) .destination(cmd.getDestination()) .amount(cmd.getAmount()) .build(); // 2 (build up details of xfer) ObjectMapper mapper = new ObjectMapper(); TransferUpdated tc = buildTransferUpdated( transferDetails, "Transfer Initiated"); publishedTopic.publish( mapper.valueToTree(tc).toString()); // 3 (publish to stream) return ctx.thenPersist( new TransferEvent .TransferInitiated( getTransferId(), transferDetails), evt -> ctx.reply(Done.getInstance()) ); // 4 (persist event & return ID) }); builder.setEventHandlerChangingBehavior( TransferEvent.TransferInitiated.class, this::fundsRequested); // 5 (change state) return builder.build(); }
  • 31.
  • 32.
  • 33.
  • 34.
  • 35. Views — Read side processors build a precomputed table — Queries are only against precomputed tables — Use this to populate data on initial page load
  • 36. Creating a portfolio 1. When each portfolio is created, we create a portfolio entity and then persist the create event to the journal 2. A read side processor subscribes to journal updates 3. With each update, the read side processor updates a projected view Let's cover #3...
  • 37. Lagom ReadSide processor Update a precomputed query table (Cassandra) on every new event we subscribe to. @Override public ReadSideHandler<PortfolioEvent> buildHandler() { return readSide.<PortfolioEvent>builder("portfolio_offset") // 1 .setGlobalPrepare(this::prepareCreateTables) // 2 .setPrepare(tag -> prepareWritePortfolios()) // 3 .setEventHandler(Opened.class, this::processPortfolioChanged) // 4 .build(); } private CompletionStage<Done> prepareWritePortfolios() { return session .prepare("INSERT INTO portfolio_summary (portfolioId, name) VALUES (?, ?)") .thenApply(ps -> { this.writePortfolios = ps; return Done.getInstance(); }); }
  • 38. Queries are then executed against the projected view for a vastly lower latency user experience. @Override public ServiceCall<NotUsed, PSequence<PortfolioSummary>> getAllPortfolios() { return request -> { CompletionStage<PSequence<PortfolioSummary>> result = db.selectAll("SELECT portfolioId, name FROM portfolio_summary;") .thenApply(rows -> { List<PortfolioSummary> summary = rows.stream().map(row -> PortfolioSummary.builder() .portfolioId(new PortfolioId( row.getString("portfolioId"))) .name(row.getString("name")) .build()) .collect(Collectors.toList()); return TreePVector.from(summary); }); return result; }; }
  • 39. Streaming 1. Render initial page with precomputed view over HTTP/ REST 2. Switch to unidirectional streaming for updates (events over WS) 3. Commands over REST will still cause full page refreshes (can change unidirectional stream to BiDi stream in future) Instead, let's use the Lagom PubSub API to push updates to the UI in real-time...
  • 40. Streaming (Lagom) This code exposes a Reactive Streams Source via Lagom, which Play can then "attach" to. @Override public ServiceCall<NotUsed, Source<String, ?>> transferStream() { return request -> { // subscribe to events on a specific topic ("transfer") final PubSubRef<String> topic = pubSub.refFor( TopicId.of(String.class, "transfer")); // return the Source as a future (standard async Java 8) return CompletableFuture.completedFuture(topic.subscriber()); }; }
  • 41. Streaming (architecture) PubSub works by broadcasting events to subscribers: — Publisher is TransferEntity — Subscriber is WireTransferServiceImpl — This will create a streaming Source
  • 42. Create a streaming connection all the way down.
  • 43. WireTransferController public WebSocket ws() { return WebSocket.Text.acceptOrResult(req -> { return wireTransferService .transferStream() .invoke() .thenApply(source -> { return F.Either.Right( Flow.fromSinkAndSource( Sink.ignore(), source ) ); }); }); }
  • 44. WebSockets (Vue.js) connect() { this.socket = new WebSocket( "ws://localhost:9000/api/transfer/stream"); this.socket.onopen = () => { this.socket.onmessage = (e) => { let event = JSON.parse(e.data); var index = -1; // 1. determine if we're updating a row (initiated) // or adding a new row (completed) for (var i = 0; i < this.transfers.length; i++) { if (this.transfers[i].id === event.id) { index = i; break; } } if (index === -1) { // unshift is similar to push, but prepends this.transfers.unshift({ // ... 3. create object with id, status, etc }); } else { let t = { // ... 4. create object with id, status, etc }; this.transfers.splice(index, 1, t); this.updateCashOnHand(); } }; }; }
  • 45. Part 3. Deployment — Packaging — sbt, service boundaries — Testing — Deploying to Minikube — Handling dependencies in k8s such as Cassandra, Kafka — Deployment — Production deployments
  • 47. Reactive Stock Trader needs... — Formation of a cluster so Lagom entities can stay available in memory — Connection to Cassandra and Kafka (in a "high- availability" clustered configuration) — Cassandra for the backing journal — Kafka for the Lagom Message Broker API for communication between services
  • 48. Aggregates are stored in-memory while the journal is persisted to Cassandra.
  • 49. In this example, we have a three node Kubernetes cluster, with two bounded contexts spread across those nodes. This offers resilience and scale.
  • 50. Deploying to Minikube Instructions are available here to help deploy Reactive Stock Trader (along with Cassandra and Kafka) to Minikube: https://github.com/RedElastic/reactive-stock-trader/tree/ master/deploy/instructions
  • 51. Conclusion — CQRS separates writes and reads for reliability and performance — Event sourcing eliminates mutability concerns of relational databases while preserving their query capabilities — Operationally Lagom is cloud-native and ready to deploy to AWS, Azure, GCP, etc, via Kubernetes
  • 52. What about serverless? — For the foreseeable future we need to understand how our software interacts with the runtime environment — A serverless component may be part of a reactive system, but is not a replacement for a reactive system — Reactive systems enable portability across cloud vendors, whereas many serverless offerings lock us in
  • 53. Reactive in Practice For a complete look at this material, visit IBM Developer and check out Reactive in Practice, a 12 part series (parts 8-12 to be published mid-September). https://developer.ibm.com/series/ reactive-in-practice/ Thanks to Dana Harrington, Lightbend, and IBM.