rescue_from StandardError do
render text: 'oops'
end
Slide 15
Slide 15 text
rescue_from StandardError do
render text: 'oops'
end
❓❓❓❓❓❓❓❓❓
❓❓❓❓❓❓❓❓❓
Slide 16
Slide 16 text
“You wrap a protected function call in
a circuit breaker object, which
monitors for failures.”
http://martinfowler.com/bliki/CircuitBreaker.html
Slide 17
Slide 17 text
https://pragprog.com/book/mnee/release-it
Slide 18
Slide 18 text
No content
Slide 19
Slide 19 text
No content
Slide 20
Slide 20 text
No content
Slide 21
Slide 21 text
No content
Slide 22
Slide 22 text
No content
Slide 23
Slide 23 text
No content
Slide 24
Slide 24 text
No content
Slide 25
Slide 25 text
No content
Slide 26
Slide 26 text
Estado + transições
Slide 27
Slide 27 text
✓ Timeouts
Slide 28
Slide 28 text
✓ Timeouts
✓ Downtimes
Slide 29
Slide 29 text
✓ Timeouts
✓ Downtimes
✓ Picos de erros
Slide 30
Slide 30 text
✓ Timeouts
✓ Downtimes
✓ Picos de erros
✓ Má configuração
Slide 31
Slide 31 text
★ Limite de falhas
Slide 32
Slide 32 text
★ Limite de falhas
★ Tempo para reset
Slide 33
Slide 33 text
★ Limite de falhas
★ Tempo para reset
★ Erros a ignorar
Slide 34
Slide 34 text
No content
Slide 35
Slide 35 text
❓API pública
❓Gestão do estado
❓Concorrência
Slide 36
Slide 36 text
jnunemaker/resilient
Slide 37
Slide 37 text
require 'resilient/circuit_breaker'
circuit_breaker = Resilient::CircuitBreaker.get('acme-co-api')
if circuit_breaker.allow_request?
begin
# API Call
circuit_breaker.success
rescue => boom
circuit_breaker.failure
# do fallback
end
else
# do fallback
end
Slide 38
Slide 38 text
circuit_breaker = Resilient::CircuitBreaker.get('example', {
# at what percentage of errors should we open the circuit
error_threshold_percentage: 50,
# do not try request again for 5 seconds
sleep_window_seconds: 5,
# do not open circuit until at least 5 requests have happened
request_volume_threshold: 5,
})
# etc etc etc
Slide 39
Slide 39 text
✅ Boa API pública
⚠ Não é distribuído
⚠ Não é concorrente
Semian.register(:mysql_shard0,
timeout: 0.5, error_threshold: 3, error_timeout: 10)
Semian[:mysql_shard0].acquire do
# Perform a MySQL query here
end
Slide 44
Slide 44 text
“Semian is not a trivial library to
understand, introduces complexity
and thus should be introduced with
care.”
https://github.com/shopify/semian#do-i-need-semian
Slide 45
Slide 45 text
“It is paramount that you understand
Semian before including it in
production as you may otherwise be
surprised by its behaviour.”
https://github.com/shopify/semian#do-i-need-semian
class CircuitBreaker
def initialize(client, name)
@client = client
@name = name
end
def method_missing(method, *args, &block)
Stoplight(@name) {
@client.public_send(method, *args, &block)
}.run
end
end
Slide 57
Slide 57 text
gh_client = GitHub::Client.new('acme-co-oauth2-token')
client = CircuitBreaker.new(gh_client, 'client-acme-co')
# Requests feito dentro do Circuit Breaker
client.repo('plataformatec/devise')
client.repo('plataformatec/simple_form')
client.repo('plataformatec/faraday-http-cache')
Slide 58
Slide 58 text
Pattern + Gem Você!
Slide 59
Slide 59 text
❓Monitoramento
Slide 60
Slide 60 text
Métricas
Slide 61
Slide 61 text
StatsD
Librato
NewRelic
AppSignal
…
Slide 62
Slide 62 text
Notificações
Slide 63
Slide 63 text
Notificações
Slide 64
Slide 64 text
Reset manual
Slide 65
Slide 65 text
❓Fallback vs raise
Slide 66
Slide 66 text
Escrita vs leitura
sync vs async
Slide 67
Slide 67 text
Executar uma operação em background
Retry + backoff