Skip to content

Latest commit

 

History

History
 
 

rest

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Flowing Retail / REST

This folder contains services that connect via REST. Currently, this is reduced to showcasing resilience patterns.

A good background read is this InfoWorld article 3 common pitfalls of microservices integration—and how to avoid them

Sample service demonstrating stateful resilience patterns in a REST environment

This sample REST (micro-)service effects payments in response to a PUT call. It requires an upstream REST service that charges credit cards.

REST callstack

This simple call-chain is perfect for demonstrating important resilience patterns.

The following technology choices are available for the code demos:

There is a stripped-down version available for:

Storyline

See Fail fast is not enough: https://blog.bernd-ruecker.com/fail-fast-is-not-enough-84645d6864d3

Let's assume a scenario where the upstream credit card service still responds, but its very slow. With no resilience pattern in place, this is the worst thing that can happen - as now the payment service will call the credit card service and block until it gets a response. As this take a long time, all threads from the payment service are held hostage, and the payment service will eventually time out for its clients. Tiny failures somewhere in your system might blow up your whole system:

V1

Fail fast

A simple mitigation is to apply a fail fast pattern like circuit breaker. In this example I use Netflix Hystrix (and Polly for C# / Brakes for Node.js, which provide equivalent functionality). If a service responds too slowly, the circuit breaker interrupts and the payment service gets a failure right away. This way you make sure the overall system is still responding, even if functionality degrades (meaning: we cannot charge credit cards).

V2

Fail fast is not enough

Failing fast is good, but it is not enough. Frequently, a retry after the credit card service has been fixed resolves the situation (if the service was in a hard failure mode) - or a retry may discover that the earlier attempt succeeded, but took an abnormal amount of time (if the service is in a degraded performance mode). This retry needs to be stateful to not only retry right away but again in a couple of minutes, hours or even days. Keeping this stateful retry local to the payment service reduces overall architectural complexity.

V3

In the example, I use the Camunda workflow engine (or Zeebe in Camunda Cloud) to do the stateful retry reliably.

Keep synchronous responses

The processing just got asynchronous, which is often not wanted. In this scenario you could very well return a synchronous response whenever the credit card service is available, but switch to asynchronicity when it is not.

V4

HTTP supports this via return codes: 200 OK means "all OK", 202 ACCEPTED means "I'll call you back later".

Sync vs. async

Asynchronous work distribution without messaging

An alternative to synchronously calling an upstream service is to communicate asynchronously. The default would be messaging.

This example shows a successful approach taken by many customers: using the workflow engine as work distribution, behaving like a queue. This leverages the External Tasks pattern.

Microservices

Business transactions using compensation

The last part of the example adds compensation to the game. In distributed systems, ACID transactions are not applicable (or at least do not scale well). Using compensation is the alternative - meaning that you reliably undo already executed work if something later on fails.

Microservices

See payment6.bpmn / Java and PaymentV6.bpmn / C# for the workflow

How-to run

You have to startup both services:

  • Stripe Fake Server
  • Payment Service

This varies:

Now the different versions of the payment service are available:

You now can issue a PUT with an empty body:

curl \
-H "Content-Type: application/json" \
-X PUT \
-d '{}' \
http://localhost:8100/api/payment/v1

Hint on using Camunda Enterprise Edition

For Camunda there is an enterprise edition available with [https://camunda.com/products/cockpit/#/features](additional features in Cockpit) (the monitoring tool). It is quite handy to use this when playing around with the example. You can easily switch to use enterprise edition:

Note that you do not need the enterprise edition to run the examples, the community edition will also do fine. But because of less features you do not see historical workflow instances - and that means you do not see that much in Camunda Cockpit if everything runs smoothly.

Using Camunda Cloud

You can get a free hosted instance of Zeebe in Camunda Cloud at https://camunda.io.