Circuit Breaker
Introdução:
Micro-serviços por muitas vezes se comunicam com outros serviços externos e uma boa prática utilizada para tolerância a falhas é o padrão Circuit Breaker.
Esse padrão é similar a um quadro de energia residencial, imagine que temos algum eletrodoméstico consumindo muita mais energia do que a rede suporta, o quadro de distribuição desarma a chave evitando um dano maior, como um incêndio ou curto-circuito.
O mesmo conceito é aplicado para micro-serviços, imagine que a aplicação A se comunique com a aplicação B utilizando o protocolo HTTP, caso B esteja offline ou falhe, a aplicação A deve ter uma resposta limpa, e não uma falha mais grave que gere um problema em cascata na arquitetura de micro-serviços.
Vamos ver na prática como esse padrão opera.
Estados de um Circuit Breaker:
Closed:
Quando não há erros no fluxo de chamadas, o Circuit Breaker mantém o estado como closed, quando o número de falhas ultrapassa o limite determinado, ele passa para o estado Open.
Open:
O Circuit Breaker retorna um erro mesmo sem executar a chamada.
Half-open:
Depois do período do timeout, se uma única chamada falhar, o estado volta para open, se não falhar, o circuit breaker volta ao estado close.
Exemplo de implementação
Para esse exemplo iremos utilizar Java, Feign Client e Hystrix.
Primeiramente nossa aplicação está rodando na URL http://localhost:8081, e faz uma chamada GET para um Fake Service que está rodando na URL http://localhost:8080.
O primeiro passo é configurar nosso Feign Client com as informações da aplicação que iremos consumir:
@FeignClient(name = "fake-client", url = "http://localhost:8080")
public interface FakeClient {
@GetMapping
String get();
}
Agora vamos fazer um serviço para utilizar esse cliente.
@Service
@AllArgsConstructor
public class FakeClientService {
private FakeClient fakeClient;
public String getValue() {
return this.fakeClient.get();
}
}
Ao rodar nossa aplicação esse é o resultado:
Mas e se a aplicação que nosso sistema está consumindo cair? O que será que acontece?
Se for um catálogo de compra, nenhum produto será exibido para o cliente, se for um tela de relatório, nenhuma informação será mostrada pro usuário, e assim por diante.
E se não tratarmos as excessões? Nosso querido Internal Service Error será exibido.
Pois bem, o Circuit Breaker veio para resolver esse problema.
Vamos refatorar esse código. ❤
O Hysterix fornece uma série de mecanismos para que possamos lidar com esse tipo de problema, para esse exemplo vamos utilizar fallbackMethod, veja o exemplo abaixo:
@Service
@AllArgsConstructor
public class FakeClientService {
private FakeClient fakeClient;
@HystrixCommand(fallbackMethod = "reliable")
public String getValue() {
return this.fakeClient.get();
}
public String reliable() {
return "Service down";
}
}
O HystrixCommand tem o atributo fallbackMethod, que indica qual método será chamado caso o Fake Client falhe.
Nesse exemplo, se o Fake Service estiver down, será exibida a mensagem Service down, porém esse recurso abre um leque de opções para sua aplicação.
Caso o Fake Service esteja down, podemos recuperar os dados do cache ou mesmo fazer uma chamada para uma aplicação de backup, como no exemplo abaixo:
@Service
@AllArgsConstructor
public class FakeClientService {
private FakeClient fakeClient;
private BackupFakeClient backupFakeClient;
@HystrixCommand(fallbackMethod = "backupService")
public String getValue() {
return this.fakeClient.get();
}
@HystrixCommand(fallbackMethod = "reliable")
public String backupService() {
return "Backup " + this.backupFakeClient.get();
}
public String reliable() {
return "Service down";
}
}
Dessa forma, nossa aplicação fica um pouco mais resistente a falhas, diminuindo problemas em cascata e provendo uma melhor experiência para os consumidores do nosso serviço.
Conclusão
Quando usar o Circuit Breaker
De forma geral, esse padrão é indicado quando temos interoperabilidade de sistemas.
Circuit Breaker fornece uma arquitetura robusta e tolerante a falhas que permite que um sistema tenha alta disponibilidade, seja auto recuperável e forneça logs para monitoramento.
Para mais informações:
https://microservices.io/patterns/reliability/circuit-breaker.html