Circuit Breaker: construindo um software resiliente

Thais Ribeiro
luizalabs
Published in
6 min readNov 11, 2022

Oi pessoALL, hoje o assunto é sobre um padrão que deveríamos adotar, porém muita gente não conhece.

Para começar a entender, digamos que nós temos uma API que conecta em outros serviços, pode acontecer algum problema na rede, componentes que podem falhar no processo, não sabemos ao certo o que pode dar errado nessas requisições. O risco quando um serviço não responde é o gargalo que se cria e pode derrubar outros componentes do sistema.

A função do engenheiro de software é manter esses componentes vivos, essa resiliência é uma das qualidades arquitetônicas no projeto de software, ou seja, a capacidade do sistema de se adaptar e se recuperar de falhas. O circuit breaker é então, o padrão destinado a aumentar essa resiliência.

Vejamos um cenário fictício, mas bastante realista do que pode acontecer em um sistema:

Começaram as vendas para um festival anual, essas vendas são feitas pelo site yolapalloza, o primeiro lote vai estar disponível com um desconto de 25% e vai somente até as 3:00 am.
As vendas começaram 00:00 am e 00:15 o tráfego é 10 vezes maior do que o normal, os usuários estão recebendo tempo de respostas cada vez mais longos.

O sistema está escalonando automaticamente, mas leva em torno de 10 minutos para que novas instâncias sejam criadas, os usuários estão irritados e continuam enviando o pedido de compra, o que cria ainda mais solicitações. É 00:30 e os administradores do site começam a perceber que os serviços que consomem o serviço de “pedido”, estão ficando sem memória porque essas solicitações estão se acumulando, 00:33 o site ainda está funcionando, mas os pedidos estão expirando e os usuários começam a reclamar no twitter como estão chateados com o yolapalloza.

Só aqui podemos ver o caos que esse tipo de situação pode causar, esse desconforto poderia ter sido evitado, se os desenvolvedores e administradores do site tivessem estudado esse tipo de incidente. Se esse serviço tivesse sido envolvido por um circuit breaker, a falha seria detectada, o disjuntor iria desarmar e imediatamente retornaria um feedback para o usuário, evitando que os pedidos expirassem.

Esses feedbacks são uteis até para o front-end informar ao usuário que no momento o serviço está indisponível, até que o circuito esteja ativado novamente.

Entendendo a importância desse padrão, vamos entender como funciona um disjuntor para podermos seguir.

Como funciona um disjuntor?

É comum termos escutado no decorrer da vida, que a chave da eletricidade de casa caiu, gerando assim a falta de energia, ou até em casos que a fiação da casa é antiga, a queda da água quente do chuveiro.
Toda casa tem disjuntor, que nada mais é que um interruptor elétrico que opera automaticamente para proteger um circuito elétrico de danos por sobrecarga (ex: queda de raio) ou curto-circuito. O principal objetivo é interromper o fluxo da corrente quando um defeito é identificado, evitando assim que aparelhos eletrônicos queimem.

Photo by Markus Spiske on Unsplash

Por que saber isso é importante? Porque o funcionamento de um disjunto opera exatamente como CB faz.

O padrão CB é usado para interromper o processo de solicitação e resposta se um serviço não estiver funcionando

circuit breaker

Ele vai funcionar então da seguinte forma:

  • O consumidor irá usar o disjuntor para invocar um serviço remoto usando um proxy, que se comportará como uma barreira de circuito.
  • Quando o número de falhas atingir um determinado limite, o disjuntor desarma por um período de tempo definido
  • Durante esse tempo, toda solicitação ao servidor offline irá falhar. Após o período de tempo estabelecido, o disjuntor passa a permitir que um número limitado de teste passe, se as solicitações forem bem sucedidas o disjuntor volta para fechado e passa a operar normalmente, se ainda estiver com falha, o período de tempo limite será iniciado novamente.

E tem três estados:

  • Aberto (open): Quando o circuito estiver aberto, as solicitações recebidas retornarão erro sem nenhuma tentativa de executar a operação real.
  • Fechado (closed): Nesse estado o disjuntor funciona normalmente, quando acontece erro e atinge o limite, ele desarma e o circuito “abre”.
  • Meio aberto (half-open): Após um tempo, o disjuntor entra no estado “semi-aberto”. Nesse estado, o disjuntor permitirá a passagem de um número limitado de solicitações conforme dito no parágrafo acima.

Ainda sobre o funcionamento do padrão, o estado inicial será closed, e o proxy irá manter um contador com a quantidade de falhas produzidas durante a chamada, se o número de falhas exceder o especificado na configuração do proxy, ele muda seu estado para open e um cronômetro é iniciado.

Quando o temporizador termina seu ciclo, o estado muda para half-open.

Determinando os limites corretos

Os critérios para determinar os limites podem vir de várias formas, tais como: utilização de recursos, latência, tráfego, tempo de atividade, taxas de erro em um determinado período, tempo limite do servidor, etc.

Você pode fazer essas determinações analisando as chamadas de API, por exemplo.
Se ainda não possui uma solução de monitoramento, pode ser uma tarefa difícil de acertar nas primeiras tentativas, mas como alternativa, pode-se usar o Bearer Agent para monitorar e registrar chamadas para APIs automaticamente.

Devemos implantar CB nas nossas aplicações?

A respostá é: SIM! A incerteza que vem com o consumo de APIs externas ou até mesmo microsserviços que podem falhar, aumenta rapidamente a dívida técnica do nosso aplicativo. Quando confiamos em padrões comprovados como o CB, aumentamos a resiliência dos nossos serviços.

Bibliotecas

Neste artigo, vamos analisar brevemente o opossum para o Node.js, mas a maioria das linguagens tem sua biblioteca disponível.

Casos

Como dito antes, vamos analisar brevemente dois exemplos de chamadas para API externa, no Node.js.

A primeira é uma solicitação que retornará sucesso e o circuito continuará fechado.

O segundo exemplo, falhará assim que a função demorar mais de 1 segundo e apresentar falha, o disjuntor vai desarmar nesse momento.

Por hoje é isso, espero que tenham gostado e se quiserem saber mais sobre o padrão e as melhores estratégias, deixarei algumas referências de documentação oficial aqui embaixo. Até mais!

--

--

Thais Ribeiro
luizalabs

Software Engineer at Luizalabs, Community Leader at frontInUdi & Blogger