Slide 1

Slide 1 text

Resilient Systems with Circuit Breaker

Slide 2

Slide 2 text

Guilherme Cavalcanti github.com/guiocavalcanti

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

– Release It! “A resilient system keeps processing transactions, even when there are transient impulses, persistent stresses, or component failures disrupting normal processing.”

Slide 5

Slide 5 text

Transactions { Not DB transactions Checkout process User signup 3rd party service communication

Slide 6

Slide 6 text

KEEPS Processing { Failures in one transaction affects the others 3rd party service failures

Slide 7

Slide 7 text

Transient impulses { Transaction peak Appear on reddid

Slide 8

Slide 8 text

Persistent stress { High transaction per minute Christmas, Black Friday, etc

Slide 9

Slide 9 text

Release It • Michael Nygard — @mtnygard • Resilience • Capacity • Deployment e Monitoring

Slide 10

Slide 10 text

Resilience patterns • Timeouts • Bulkheads • Fail fast • Handshking • Circuit Breaker

Slide 11

Slide 11 text

Circuit Breaker • Nowadays it’s common to have apps composed by many other apps communicating via API • 3rd party services call will fail • Failure chain

Slide 12

Slide 12 text

Example App App App NGINX Service x x x

Slide 13

Slide 13 text

Client Circuit Breaker Service Timeout Timeout

Slide 14

Slide 14 text

Naive implementation

Slide 15

Slide 15 text

Estados Closed Open Threshold reached Success one time failure

Slide 16

Slide 16 text

Initialization class CircuitBreaker! ! def initialize(options = {})! @timeout = options.fetch(:timeout, 0.01)! @failure_threshold = options.fetch(:failure_threshold, 5)! @silent = false! @failure_count = 0! end

Slide 17

Slide 17 text

#handle • Strategy pattern • Circuit state • Try to execute and capture exceptions def handle(&block)! case state! when :closed then try_to_execute &block! when :open then handle_open! end! end

Slide 18

Slide 18 text

#try to… • Failure counter • Tri timeout • Reset counter def try_to_execute(&block)! begin! yield_with_timeout(&block)! reset! rescue Timeout::Error! record_failure! raise $!! end! end! ! def yield_with_timeout(&b)! Timeout::timeout(@timeout, &b)! end! ! def reset! @failure_count = 0! end! ! def record_failure! @failure_count += 1! end!

Slide 19

Slide 19 text

#STATE ! def state! (@failure_count >= @failure_threshold) ? :open : :closed! end

Slide 20

Slide 20 text

Using require "circuit_breaker"! ! circuit = CircuitBreaker.new! conn = Faraday.new! ! circuit.handle do! conn.get('http://api.foo.com/me.json')! end! ! circuit.handle do! conn.get('http://api.foo.com/accounts.json')! end

Slide 21

Slide 21 text

Problem Closed Open Falhas consecutivas Sucesso Falha esporádica Success

Slide 22

Slide 22 text

Strategy • Half open state • Come back to closed after a while

Slide 23

Slide 23 text

Closed Open threshold reached Success One time failure Half 
 Open Timeout reset Success Failure

Slide 24

Slide 24 text

.new class CircuitBreaker! ! def initialize(options = {})! @invocation_timeout = options.fetch(:timeout, 0.01)! @failure_threshold = options.fetch(:failure_threshold, 5)! @silent = false! @failure_count = 0! @reset_timeout = 0.1! @last_failure = nil ! end

Slide 25

Slide 25 text

Mudanças • Try to execute • Last failure time • Reset last failure time def handle(&b)! case state! when :closed, :half_open! try_to_execute &b! when :open then handle_open! end! end! ! def try_to_execute(&block)! begin! yield_with_timeout(&block)! reset! rescue Timeout::Error! record_failure! raise $!! end! end! ! def yield_with_timeout(&b)! Timeout::timeout(@timeout, &b)! end! ! def reset! @failure_count = 0! @last_failure_time = nil! end! ! def record_failure! @last_failure_time = Time.now! @failure_count += 1! end!

Slide 26

Slide 26 text

#STate def state! case! when (@failure_count >= @failure_threshold) &&! (Time.now - @last_failure_time) > @reset_timeout! :half_open! when (@failure_count >= @failure_threshold)! :open! else! :closed! end! end

Slide 27

Slide 27 text

Improvements • Use AAsm or Statesman to manage state machine • Monitoring infrastructure using dependency injection • Distributed Circuit breaker • Detect errors other than timeout

Slide 28

Slide 28 text

References • Circuit Breaker, Martin Fowler • Release It, Michael Nygard • Gem Circuit Breaker • Faraday