1

Aplicando o Padrão Circuit Breaker em Asp.Net Core

#.NET Core #Arquitetura de Sistemas
J
Jean Passos

O PADRÃO


Quando desenvolvemos sistemas é muito comum integrá-los a recursos externos como bancos de dados e APIs para que o projeto seja satisfeito. No entanto, não podemos esperar que tais recursos estejam 100% do tempo disponíveis, pois todos eles são suscetíveis a falhas, seja por uma indisponibilidade do servidor, um problema de rede ou uma implantação malsucedida, o sistema que acessa tais recursos deve estar preparado para lidar com estas situações onde uma recuperação quase imediata, por meio de redundância por exemplo, nem sempre está disponível. É possível criarmos mecanismos para reenviar solicitações, porém reenvios sucessivos comumente não irão ajudar o sistema a se restabelecer. A fim de minimizar os impactos causados por estas eventuais falhas podemos lançar mão do padrão Circuit Breaker.


O padrão circuit breaker é análogo aos sistemas de circuito elétrico com um disjuntor para proteção, quando uma falha é detectada na rede o disjuntor desliga abrindo o circuito para que a corrente deixe de fluir e assim não haja maiores danos como superaquecimento nos fios, incêndios etc. Quando a fonte do problema é detectada e resolvida o dispositivo pode ser religado fechando o circuito e a corrente elétrica pode voltar a fluir. O padrão funciona com estes mesmos estados: aberto e fechado e adiciona mais um, o semiaberto.


No estado fechado os recursos são acessados normalmente e, caso uma exceção seja lançada ela é armazenada e o circuito passa para o estado aberto. Algumas implementações preveem uma quantidade limite de falhas antes do estado passar para o estado aberto, ou seja, o estado passa para aberto somente após um certo número de tentativas falhas


No estado aberto todas as requisições realizadas irão lançar imediatamente a última exceção armazenada, impedindo que novos acessos sejam realizados. No entanto estes acessos não podem ser rejeitados indefinidamente, pois esperamos que o recurso se restabeleça e a comunicação volte a acontecer, por este motivo o padrão prevê o armazenamento do momento (data e hora) em que foi detectado o problema e um limite de tempo que deve ser aguardado até que a aplicação possa realizar uma nova tentativa, quando este limite é atingido a aplicação passa para o estado semiaberto


No estado semiaberto é permitida a tentativa de transação com o recurso, caso seja bem sucedido o circuito passa para o estado fechado e a comunicação volta a acontecer, caso contrário, ou seja, a falha continua, o estado volta para aberto renovando o momento de detecção. Também neste estado existem variações de implementação que fecham o circuito apenas após um certo número de tentativas com resultado de sucesso.


PROJETO


Para demonstração de implementação e utilização do padrão criei e publiquei no repositório github apresentado no final do artigo, uma solução em Asp.Net Core chamada eLoja. A aplicação simula, de forma bem básica, uma loja virtual com apenas duas funcionalidades nas quais os usuários podem escolher produtos para comprar ou apenas se cadastrar. As duas disparam requisições aos seus serviços correspondentes e ambos estão "protegidos" pelo cricuit breaker ao acessá-los.


Foram criadas três soluções: eLoja.Api.Pedido.sln, eLoja.Api.Usuario.sln e eLoja.UI.sln. O foco deve ficar na última pois é a solução onde o padrão é implementado e utilizado, ela possui dois projetos: eLoja.UI.csproj e o eLoja.CircuitBreaker.csproj


eLoja.CircuitBreaker


As partes integrantes do padrão foram segregadas neste projeto a fim de destacar sua composição. O principal artefato a ser observado é o CircuitBreakerBase.cs, é nesta classe que estão definidas as operações de quando alterar o estado, o intervalo de tempo entre as tentativas de comunicação com o recurso, a quantidade de operações de sucesso ou falha antes do circuito ser aberto ou fechado, entre outros.


eLoja.UI


O objetivo deste projeto é demonstrar sua utilização, as classes presentes na pasta CircuitBreakers utilizam o padrão para realizar a requisição aos seus respectivos serviços, estas operações são passadas como parâmetro para o método que manipula o estado do circuito. Estas classes devem ser injetadas como serviços singleton nas controllers que a utilizarão. O fato de ser singleton é importante pois permite que apenas uma única instância seja criada para todo o tempo de vida da aplicação, uma vez que o objetivo é fazer com que o serviço reconhecidamente com falha não seja acessado em um determinado período de tempo, se faz necessário que o mecanismo não seja ativado por requisição pois não seria possível armazenar a referência do estado da comunicação, bem como a última exceção e a último momento em que o estado foi passado para aberto.


Fonte no github: https://github.com/jean-passos/circuit-breaker

0
28

Comentários (0)

None

Brasil