Microservice Resiliency From Front to Back End QCon So Paulo, 2017 - - PowerPoint PPT Presentation

microservice resiliency
SMART_READER_LITE
LIVE PREVIEW

Microservice Resiliency From Front to Back End QCon So Paulo, 2017 - - PowerPoint PPT Presentation

Microservice Resiliency From Front to Back End QCon So Paulo, 2017 Lance Ball, Senior Software Engineer, Red Hat Who am I? Senior Software Engineer, Red Hat Who am I? Senior Software Engineer, Red Hat Who am I? Senior Software Engineer,


slide-1
SLIDE 1

Microservice Resiliency

From Front to Back End

QCon São Paulo, 2017

Lance Ball, Senior Software Engineer, Red Hat

slide-2
SLIDE 2

Who am I?

Senior Software Engineer, Red Hat

slide-3
SLIDE 3

Who am I?

Senior Software Engineer, Red Hat

slide-4
SLIDE 4

Who am I?

Senior Software Engineer, Red Hat

slide-5
SLIDE 5

Who am I?

Senior Software Engineer, Red Hat

slide-6
SLIDE 6

µ Service

software applications as suites of

independently deployable services

https://martinfowler.com/articles/microservices.html

slide-7
SLIDE 7

µ Service

software applications as suites of

independently deployable services

https://martinfowler.com/articles/microservices.html

But what does this mean?!

slide-8
SLIDE 8

What's in an application?

slide-9
SLIDE 9

Stuff

slide-10
SLIDE 10

Monolithic application

slide-11
SLIDE 11

Scaling a monolith

slide-12
SLIDE 12

Microservice application

slide-13
SLIDE 13

Scaled microservices

slide-14
SLIDE 14

Wait... isn't this the UX track?

slide-15
SLIDE 15

Service Lifecycle

slide-16
SLIDE 16

Service Lifecycle

Client makes a request

slide-17
SLIDE 17

Service Lifecycle

Client makes a request Server provides a response

slide-18
SLIDE 18

Service Lifecycle

Client makes a request Server provides a response Often using HTTP transport

slide-19
SLIDE 19

Service Lifecycle

Client makes a request Server provides a response Often using HTTP transport Often with JSON data format

slide-20
SLIDE 20

In the Browser

slide-21
SLIDE 21

In the Browser

XMLHttpRequest

slide-22
SLIDE 22

In the Browser

XMLHttpRequest JQuery

slide-23
SLIDE 23

In the Browser

XMLHttpRequest JQuery AJAX

slide-24
SLIDE 24

Microservice Requests

(simplified)

slide-25
SLIDE 25

Operational Complexity

slide-26
SLIDE 26

Microservices Visualized

https://twitter.com/ThePracticalDev/status/845285541528719360

slide-27
SLIDE 27

Problems

slide-28
SLIDE 28

Problems

Timeouts

slide-29
SLIDE 29

Problems

Timeouts Network saturation

slide-30
SLIDE 30

Problems

Timeouts Network saturation Programmer error

slide-31
SLIDE 31

Problems

Timeouts Network saturation Programmer error Disk failure

slide-32
SLIDE 32

Problems

Timeouts Network saturation Programmer error Disk failure Transitive dependencies

slide-33
SLIDE 33

Cascading failures

slide-34
SLIDE 34
slide-35
SLIDE 35

How to deal with all this

slide-36
SLIDE 36

How to deal with all this

Limit single points of failure

slide-37
SLIDE 37

How to deal with all this

Limit single points of failure Shed load when possible

slide-38
SLIDE 38

How to deal with all this

Limit single points of failure Shed load when possible Provide fallback behavior

slide-39
SLIDE 39

How to deal with all this

Limit single points of failure Shed load when possible Provide fallback behavior Optimize failure discovery

slide-40
SLIDE 40

Circuit Breaker

slide-41
SLIDE 41

Circuit Breaker

Calls that could fail are wrapped

slide-42
SLIDE 42

Circuit Breaker

Calls that could fail are wrapped Circuit opens at a failure threshold

slide-43
SLIDE 43

Circuit Breaker

Calls that could fail are wrapped Circuit opens at a failure threshold Further calls short circuit for a while

slide-44
SLIDE 44

Circuit Breaker

Calls that could fail are wrapped Circuit opens at a failure threshold Further calls short circuit for a while Later, circuit tries again and trips immediately if there is failure

slide-45
SLIDE 45
slide-46
SLIDE 46

Circuit State

slide-47
SLIDE 47

Async operation that could fail

// Use JQuery to get cart info $.get('http://mystore.com/cart') .then((json) => { // update the UI with JSON data }) .catch((e) => { // oops something went wrong console.error(e); })

slide-48
SLIDE 48

Async operation that could fail

// Use JQuery to get cart info $.get('http://mystore.com/cart') .then((json) => { // update the UI with JSON data }) .catch((e) => { // oops something went wrong console.error(e); })

Shed load when possible

slide-49
SLIDE 49

Aside - Promsies

// Use JQuery to get cart info $.get('http://mystore.com/cart') .then((json) => { // update the UI with JSON data }) .catch((e) => { // oops something went wrong console.error(e); })

slide-50
SLIDE 50

Circuit Breaker Example

// Use JQuery's ajax wrapper and circuit breaker // defaults for failure threshold, timing, etc. const circuit = circuitBreaker($.get); circuit.fire('http://nodejs.org/dist/index.json') .then((json) => { // update the UI with JSON data }) // on failure, just log to console .catch(console.error);

slide-51
SLIDE 51

Circuit Breaker Example

// Use JQuery's ajax wrapper and circuit breaker // defaults for failure threshold, timing, etc. const circuit = circuitBreaker($.get); circuit.fire('http://nodejs.org/dist/index.json') .then((json) => { // update the UI with JSON data }) // on failure, just log to console .catch(console.error);

slide-52
SLIDE 52

Circuit Breaker Example

// Use JQuery's ajax wrapper and circuit breaker // defaults for failure threshold, timing, etc. const circuit = circuitBreaker($.get); circuit.fire('http://nodejs.org/dist/index.json') .then((json) => { // update the UI with JSON data }) // on failure, just log to console .catch(console.error);

slide-53
SLIDE 53

Promises vs. Callbacks

// Wrap Node.js' fs.readFile as a promise-returning function const readFile = circuitBreaker.promisify(fs.readFile); const circuit = circuitBreaker(readFile, options); circuit.fire('./package.json', 'utf-8') .then(console.log) .catch(console.error);

slide-54
SLIDE 54

Circuit Breaker Fallback

Provides default behavior in case of error

circuit.fallback((file) => `Sorry, I can't read ${file}`); // Fallback function is still a success case circuit.fire('./package.jsob') .then((data) => console.log(`package.json: \n${data}`)) .catch((err) => console.error(`ERR: ${err}`));

slide-55
SLIDE 55

Circuit Breaker Fallback

Provides default behavior in case of error

circuit.fallback((file) => `Sorry, I can't read ${file}`); // Fallback function is still a success case circuit.fire('./package.jsob') .then((data) => console.log(`package.json: \n${data}`)) .catch((err) => console.error(`ERR: ${err}`));

slide-56
SLIDE 56

Caching

Always returns the same value

const now = circuitBreaker(Date, { cache: true });

slide-57
SLIDE 57

Caching

Always returns the same value

const now = circuitBreaker(Date, { cache: true }); circuit.fire().then(console.log); // Mon Apr 10 2017 12:10:26 GMT-0400 (EDT) circuit.fire().then(console.log); // Mon Apr 10 2017 12:10:26 GMT-0400 (EDT) circuit.fire().then(console.log); // Mon Apr 10 2017 12:10:26 GMT-0400 (EDT)

slide-58
SLIDE 58

When is this useful?

Frequent hits, infrequent change E.g. username

const username = circuitBreaker(fetchUsername, { cache: true }); // periodically clear the cache setInterval(_ => username.clearCache(), 5000);

slide-59
SLIDE 59

Events

Circuit breakers are event emitters

// Update the UI specifically for timeout errors circuit.on('timeout', () => $(element).prepend( mkNode(`${route} is taking too long to respond.`)));

slide-60
SLIDE 60

`fire` `reject` `timeout` `success` `failure` `open` `close` `halfOpen` `fallback` `snapshot`

Events

Circuit breakers are event emitters

// Update the UI specifically for timeout errors circuit.on('timeout', () => $(element).prepend( mkNode(`${route} is taking too long to respond.`)));

slide-61
SLIDE 61

Status

// create a 10 sec window with 10 buckets of 1 sec const circuit = circuitBreaker(asyncFunc, { rollingCountTimeout: 10000, rollingCountBuckets: 10 }); // status is calculated every time status is accessed const status = circuit.status // print the entire statistical window console.log(status.window); // print the rolling stats console.log(status.stats);

slide-62
SLIDE 62

Status

// create a 10 sec window with 10 buckets of 1 sec const circuit = circuitBreaker(asyncFunc, { rollingCountTimeout: 10000, rollingCountBuckets: 10 }); // status is calculated every time status is accessed const status = circuit.status // print the entire statistical window console.log(status.window); // print the rolling stats console.log(status.stats);

slide-63
SLIDE 63

Status

// print the rolling stats console.log(status.stats); // { failures: 3, // fallbacks: 4, // successes: 44, // rejects: 4, // fires: 48, // timeouts: 1, // cacheHits: 0, // cacheMisses: 0 }

slide-64
SLIDE 64

Dashboard

http://techblog.netflix.com/2012/12/hystrix-dashboard-and-turbine.html

slide-65
SLIDE 65

Demo

slide-66
SLIDE 66

Obrigado & Questions

http://lanceball.com/qcon-saopaulo-2017/ https://github.com/lance/qcon-saopaulo-2017 Twitter - @lanceball GitHub - @lance