Let your microservices flow!
mail@bernd-ruecker.com
With thoughts from http://flowing.io
@berndruecker | @martinschimak
Simplified example:
dash button
Photo by 0xF2, available under Creative Commons BY-ND 2.0
license. https://www.flickr.com/photos/0xf2/29873149904/
Let‘s asume we go for microservices.
Because: Reasons.
Example
Checkout Payment Inventory Shipping
Let‘s zoom into the payment
public void retrievePayment(String customerId, long amount) {
long remainingAmount =
useExistingCustomerCredit(customerId, amount);
if (remainingAmount > 0) {
try {
chargeCreditCard(customerId, remainingAmount);
} catch (CreditCardExpiredException ex) {
restoreCustomerCredit(customerId, amount-remainingAmount);
throw new PaymentFailedException();
}
}
}
Let‘s zoom into the payment
public void retrievePayment(String customerId, long amount) {
long remainingAmount =
useExistingCustomerCredit(customerId, amount);
if (remainingAmount > 0) {
try {
chargeCreditCard(customerId, remainingAmount);
} catch (CreditCardExpiredException ex) {
restoreCustomerCredit(customerId, amount-remainingAmount);
throw new PaymentFailedException();
}
}
}
Remote
Service
Distributed systems
Distributed systems are hard.
You will be screwed.
But you cannot avoid it.
public void retrievePayment(String customerId, long amount) {
long remainingAmount =
useExistingCustomerCredit(customerId, amount);
if (remainingAmount > 0) {
try {
chargeCreditCard(customerId, remainingAmount);
} catch (CreditCardExpiredException ex) {
restoreCustomerCredit(customerId, amount-remainingAmount);
throw new PaymentFailedException();
}
}
}
Unreliable networks require some extra work
Circuit breaker & fail fast
Remember…
public void retrievePayment(String customerId, long amount) {
long remainingAmount =
useExistingCustomerCredit(customerId, amount);
if (remainingAmount > 0) {
try {
chargeCreditCard(customerId, remainingAmount);
} catch (CreditCardExpiredException ex) {
restoreCustomerCredit(customerId, amount-remainingAmount);
throw new PaymentFailedException();
}
}
}
Unreliable networks require some extra work
Circuit breaker & fail fast
Retry capability & async
behavior
Distributed transactions
Payment
requires
state
handling
Persist state with
Entity, Actor, …
State machine
How to
implement?
DIY
State
machine
CADENCE
Baker
Example
* Modeled in BPMN
ISO Standard for modeling and execution
Long running requires persistent state
Distributed transactions
Distributed transactions
Retrying
Timeouts and long running requirements
State machines solve some hard developer problems
Monitoring &
Operations
Handling of time &
timeouts
Retry
Visibility &
Reporting
Versioning
Compensation
Message correlation &
deduplication
Performance &
scalability
State machines
solve some hard developer problems.
Distributed systems pose some hard
problems on developers!
BPM?
A visual test report for example #1 (Balance = 50, Amount = 70)
Look for
lightweight, developer friendly
tools
Synchronous communication?
Asynchronous
Checkout Payment Inventory Shipping
Bus
Event-Driven
Checkout Payment Inventory Shipping
Bus
Order
Placed
Does not
know
recipient
Does not
know
sender
Smart endpoints
and dumb pipes
Event: Fact that
happened in the past,
Immutable fact,
0..n recepients
Order
Placed
Does know
event type…
Event-Driven – the good parts
Checkout Payment Inventory Shipping
Bus
Amount
OnStock
Changed
„The button blinks green
if we can ship the item
within 24 hours!“
End-to-end capabilities using peer-to-peer event flows?
InventoryPayment ShippingCheckout
Order
placed
Payment
received
Goods
fetched
Goods
shipped
Shipping
End-to-end capabilities using peer-to-peer event flows?
InventoryPaymentCheckout
Order
placed
Payment
received
Goods
fetched
Please fetch
the goods
before waiting
for payment
Some
customers can
pay via invoice
…
InventoryPayment ShippingCheckout
Bus
Order
Order
Placed
Retrieve
Payment
Event Command Transformation
Command: Intent,
1 recipient.
Retrieve
Payment
Fetch
Goods
Ship
Goods
Does not
know
sender
Just knows
command
type…
Commanding is important!
InventoryPayment ShippingCheckout
Bus
Ship
Goods
Order
Order
Placed
Retrieve
Payment
„A few smart god services
tell anemic CRUD services
what to do!”
Sam Newman
The problem is not orchestration!
The problem is bad API design.
Orchestration is not about synchronous
request and response.
It is a about commands
and probably long running flows.
And yes –
it can be
reactive.
Example
Example
Payment
Flows are owned by services
Order
Example
InventoryPaymentOrder ShippingCheckout Monitor
https://github.com/flowing/flowing-retail/
Human
Tasks
Messaging under control?
Photo by Andy Simmons, available under Creative Commons BY 2.0 license.
External task worker example
Stripe
Worker
Payment
Rest
Node.js Java
A possibility in your toolbox.
Pro: Easy to do, no AMQP or Kafka required for bus
Con: Coupling to Camunda API
Live hacking
Container
(e.g. Tomcat, WildFly, Websphere, …)
Architecture possibilities
Your application
Engine
DB
BPMN Java …
Your application
Engine
DB
BPMN Java …
Engine
(Docker,
Tomcat, …)
Your application
DB
Embedded engine Container managed engine Remote engine
BPMN
Java, C#,
Go, JS, …
New kid on the block
https://zeebe.io/
Zeebe
Broker
Your
application
Binary (MsgPack)
Support streaming & batching
Client
Horiziontally
scalable
Append only log / event sourcing
Distributed
systems are
hard
State machines
solve hard
developer problems
Can run
decentralized
And provide
visibility
sync and
async
Thank you!
Code:
https://github.com/berndruecker
Slides:
https://bernd-ruecker.com
Blog:
https://blog.bernd-ruecker.com
Feedback:
https://bernd-ruecker.com/feedback
With thoughts from http://flowing.io
@berndruecker | @martinschimak
Images licensed from iStock
no attribution required
Images licensed under Creative Commons license
All icons licensed from Noun Project
no attribution required
Photo by Andy Simmons, available under
Creative Commons BY 2.0 license.
https://www.flickr.com/photos/andysimmons
/4630485117/

JCon 2017: Let your microservices flow