-Service Resiliency With Circuit Breakers Lance Ball - Red Hat - - - PowerPoint PPT Presentation

service resiliency with circuit breakers
SMART_READER_LITE
LIVE PREVIEW

-Service Resiliency With Circuit Breakers Lance Ball - Red Hat - - - PowerPoint PPT Presentation

-Service Resiliency With Circuit Breakers Lance Ball - Red Hat - @lanceball FullStack 2018 Resilience Resiliency is defined as the capability of a system to maintain its functions and structure in the face of internal and external change


slide-1
SLIDE 1

µ-Service Resiliency With Circuit Breakers

Lance Ball - Red Hat - @lanceball FullStack 2018

slide-2
SLIDE 2

Resilience

Resiliency is defined as the capability of a system to maintain its functions and structure in the face of internal and external change and to degrade gracefully when it must.

TOWARD INHERENTLY SECURE AND RESILIENT SOCIETIES Brad Allenby, Jonathan Fink http://science.sciencemag.org/content/309/5737/1034.full

slide-3
SLIDE 3

Microservices

slide-4
SLIDE 4

My App

Monolith

slide-5
SLIDE 5

µ-Service

µ svc A µ svc B µ svc C µ svc D µ svc J µ svc H µ svc F µ svc G µ svc E

slide-6
SLIDE 6

Reality

µ svc A µ svc B µ svc C µ svc D µ svc J µ svc H µ svc F µ svc G µ svc E

slide-7
SLIDE 7

Microservices are not a Panacea

slide-8
SLIDE 8

A Single Failure

µ svc A µ svc B µ svc C µ svc D µ svc J µ svc H µ svc F µ svc G µ svc E

slide-9
SLIDE 9

function wait (timeout) { return new Promise(resolve => { setTimeout(resolve, timeout) }); }

A Simple Sleep in µ-Service D

slide-10
SLIDE 10

const MAX_ATTEMPTS = 10; let retryAttempts = 0; async function fetchData (url) { return request.get(url).then(formatData) .catch(err => { if (retryAttempts > MAX_ATTEMPTS) return Promise.reject(err); retryAttempts++; await wait(500); return fetchData(url); }); }

A Naive Implementation

slide-11
SLIDE 11

What Happens When We Keep On Trying?

slide-12
SLIDE 12

Services D & E Block

µ svc A µ svc B µ svc C µ svc D µ svc J µ svc H µ svc F µ svc G µ svc E

slide-13
SLIDE 13

It Gets Worse

slide-14
SLIDE 14

Failure Cascades

µ svc A µ svc B µ svc C µ svc D µ svc J µ svc H µ svc F µ svc G µ svc E

slide-15
SLIDE 15

Unto Death

µ svc A µ svc B µ svc C µ svc D µ svc J µ svc H µ svc F µ svc G µ svc E

slide-16
SLIDE 16

Naive Implementations are a Band-Aid

slide-17
SLIDE 17

Do not have the same error reoccur constantly. Handle the error quickly and gracefully without waiting for TCP timeout.

Resilience

slide-18
SLIDE 18

Resiliency Patterns

  • Fault and latency tolerant
  • Stops cascading failures
  • Provides fallback behavior
  • Fails fast with graduated

automatic recovery

slide-19
SLIDE 19

Circuit Breakers

slide-20
SLIDE 20
slide-21
SLIDE 21

function fetchData (url) { return _ => { // return a promise return request.get(url) .then(formatData) .catch(err => { // do something more sensible than this console.log(err) }); }; }

A Function: It Might Fail

slide-22
SLIDE 22

const CircuitBreaker = require(‘opossum’); const options = { timeout: 1000, errorThresholdPercentage: 50, resetTimeout: 5000, capacity: 10 }; const circuit = CircuitBreaker( fetchData('/some/url'), options );

Wrap it in a Circuit Breaker

slide-23
SLIDE 23

Fallback Behavior

slide-24
SLIDE 24

circuit.fallback( _ => 'Sorry, out of service right now' ); circuit.on('fallback', result => reportFallbackEvent(result)); Fallback Events

slide-25
SLIDE 25

Events

slide-26
SLIDE 26

★ fire ★ success ★ failure ★

  • pen

★ close ★ halfOpen ★ fallback ★ cacheHit ★ cacheMiss ★ timeout ★ semaphore-locked ★ health-check-failed ★ snapshot Events

slide-27
SLIDE 27

Health Checks

slide-28
SLIDE 28

function memoryUsage () { const memory = process.memoryUsage(); return (memory.heapUsed / memory.heapTotal) < 0.9 ? Promise.resolve() : Promise.reject(); } circuit.healthCheck(memoryUsage); circuit.on('health-check-failed', sendAlertMessage); function sendAlertMessage () { // send an alert message to someone }

Example: Health Checks

slide-29
SLIDE 29

Snapshots

slide-30
SLIDE 30

Example: Snapshots

// Creates a 10 second window consisting of ten time slices, // each time slice being 1 second long. const circuit = circuitBreaker(fs.readFile, { rollingCountBuckets: 10, rollingCountTimeout: 10000}); // get the cumulative status for the last second circuit.status.on(‘snapshot’, data => ( /* store data? */ )); // get the array of 10, 1 second time slices circuit.status.window;

slide-31
SLIDE 31

Statistics

slide-32
SLIDE 32

Statistics Snapshots

slide-33
SLIDE 33

Statistics Stream on the Server

const app = express(); const circuit = CircuitBreaker( callTheRemoteApi ); app.use(‘/stats.stream’, function statStream (request, response) { response.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive'}); circuit.stats.pipe(response); };

slide-34
SLIDE 34

Statistics Stream in the Browser

// in the browser const stats = new EventSource('/stats.stream'); stats.onmessage = updateStats; function updateStats(message) { const stats = JSON.parse(message.data); $('#stats').html(message.data); $('#failures').html(stats.errorCount); $('#fires').html(stats.requestCount); $('#latency-mean').html(stats.latencyTotal_mean.toFixed(2)); }

slide-35
SLIDE 35

Elizabethan Insults

Demo Time!

slide-36
SLIDE 36

Insulting!

slide-37
SLIDE 37

https://launch.openshift.io

slide-38
SLIDE 38

Thanks & Questions

https://launch.openshift.io https://github.com/bucharest-gold/nodejs-circuit-breaker https://github.com/lance/elizabethan-insults https://github.com/bucharest-gold/opossum