Leaders Logo

Construindo um Mecanismo de Circuit Breaker Utilizando .NET

Introdução ao Padrão Circuit Breaker

O padrão Circuit Breaker é uma técnica utilizada no desenvolvimento de software para aumentar a resiliência de aplicações, especialmente em arquiteturas distribuídas (PUNITHAVATHY; PRIYA, 2024). Esse padrão atua como um interruptor que impede que chamadas a serviços falhem repetidamente, permitindo que o sistema se recupere antes de tentar uma nova chamada. Isso é especialmente útil em cenários onde a latência e a falha de serviços externos podem impactar a performance da aplicação. Em essência, o Circuit Breaker ajuda a evitar que um sistema inteiro falhe devido a problemas em um único componente.

Propósito

O Circuit Breaker é inspirado nos sistemas elétricos, onde um circuito pode ser interrompido para evitar sobrecargas. No contexto de software, ele funciona de maneira semelhante, permitindo que o sistema "desligue" as chamadas a um serviço que está falhando (PUNITHAVATHY; PRIYA, 2024). Isso evita que falhas em um serviço afetem todo o sistema, permitindo que ele se recupere antes de retomar as operações normais (FOWLER, 2014). Dessa forma, podemos considerar que o Circuit Breaker é:

  • Um mecanismo que previne chamadas repetidas a serviços instáveis, protegendo o sistema de falhas em cascata.
  • Inspirado em disjuntores elétricos, "abrindo" o circuito quando detecta falhas contínuas.
  • Composto por três estados: Closed (normal), Open (chamadas bloqueadas) e Half-Open (teste para retomar operações) (POLLY, 2023).
  • Utilizado para melhorar a estabilidade e resiliência de aplicações distribuídas (MICROSOFT, 2025).

Da mesma forma, é importante entender que o Circuit Breaker não é:

  • Um mecanismo de retry simples: embora possa ser combinado com retries, sua função principal é interromper chamadas a serviços problemáticos.
  • Um substituto para fallback: embora possa ser usado em conjunto com estratégias de fallback, eles têm propósitos distintos.
  • Uma ferramenta de monitoramento: embora forneça informações sobre falhas, não substitui sistemas de observabilidade.
  • Balanceador de carga: sua função é interromper chamadas a serviços instáveis, não distribuir tráfego entre serviços saudáveis.

Por Que Usar Circuit Breaker?

Quando um serviço externo falha, as chamadas subsequentes a esse serviço podem causar sobrecarga e latência desnecessárias, levando a um efeito cascata que pode comprometer a estabilidade da aplicação (COSTA et al., 2022). O padrão Circuit Breaker ajuda a evitar essa situação, protegendo a aplicação de falhas em cascata. Ele permite que a aplicação reaja rapidamente a problemas, liberando recursos e permitindo que o sistema se recupere mais rapidamente. Além disso, o Circuit Breaker pode ser configurado para fornecer feedback ao usuário, como mensagens de erro amigáveis, em vez de falhas silenciosas ou mensagens de erro genéricas.

Em um mundo onde a dependência de serviços externos é cada vez mais comum, a implementação de um Circuit Breaker se torna uma prática recomendada (COSTA et al., 2022). Ele não só melhora a resiliência da aplicação, mas também facilita o monitoramento e a manutenção do sistema, permitindo que as equipes de desenvolvimento identifiquem rapidamente problemas que podem surgir devido a falhas externas.

Implementando Circuit Breaker em .NET

Para implementar um mecanismo de Circuit Breaker em .NET, podemos usar a biblioteca Polly, que é uma biblioteca de resiliência para .NET que facilita a implementação de padrões como retry, timeout e circuit breaker. O Polly fornece uma API poderosa e flexível, permitindo que os desenvolvedores configurem políticas de resiliência que atendam às necessidades específicas de suas aplicações (PUNITHAVATHY; PRIYA, 2024).

Instalação do Polly

Para começar a usar o Polly, devemos instalar o pacote Polly via NuGet (POLLY, 2023). Isso pode ser feito através do console do NuGet com o seguinte comando:

Install-Package Polly

Alternativamente, você pode instalar o Polly utilizando o gerenciador de pacotes do Visual Studio. Basta procurar por "Polly" na seção de pacotes NuGet e clicar em instalar. Uma vez que o Polly está instalado, você pode começar a implementar suas políticas de resiliência em sua aplicação.

Configurando o Circuit Breaker

Após a instalação, podemos configurar um Circuit Breaker. O código a seguir demonstra como criar uma política de Circuit Breaker que abre o circuito após 3 falhas consecutivas e o mantém aberto por 30 segundos. Essa configuração é um ponto de partida e pode ser ajustada de acordo com as necessidades específicas de sua aplicação.


using Polly;
using System;
using System.Net.Http;
using System.Threading.Tasks;

public class CircuitBreakerExample
{
    private static readonly HttpClient httpClient = new HttpClient();
    
    public async Task<string> FetchDataAsync(string url)
    {
        var circuitBreakerPolicy = Policy
            .Handle<HttpRequestException>()
            .CircuitBreaker(3, TimeSpan.FromSeconds(30));

        try
        {
            return await circuitBreakerPolicy.ExecuteAsync(async () => 
            {
                var response = await httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            });
        }
        catch (BrokenCircuitException)
        {
            return "Circuit is open. Please try again later.";
        }
    }
}

Neste exemplo, estamos usando a política de Circuit Breaker do Polly para definir que, se ocorrerem três falhas consecutivas ao tentar acessar um URL, o circuito será aberto e permanecerá assim por 30 segundos. Durante esse tempo, qualquer tentativa de acesso ao serviço resultará em uma exceção BrokenCircuitException, que pode ser tratada para informar ao usuário que o serviço está temporariamente indisponível.

Testando o Circuit Breaker

Para testar o comportamento do Circuit Breaker, você pode simular chamadas a um serviço que falha. Aqui está um exemplo de como você poderia escrever um teste simples para verificar se o Circuit Breaker está funcionando conforme o esperado:


public async Task TestCircuitBreaker()
{
    var circuitBreakerExample = new CircuitBreakerExample();
    
    for (int i = 0; i < 10; i++)
    {
        var result = await circuitBreakerExample.FetchDataAsync("http://example.com/fail");
        Console.WriteLine(result);
    }
}
    

Neste teste, estamos chamando um serviço que sabemos que falhará. Após três falhas, o Circuit Breaker deve abrir e as tentativas subsequentes de chamada ao serviço devem resultar na mensagem "Circuit is open. Please try again later." sendo impressa no console. Isso confirma que o Circuit Breaker está funcionando conforme o esperado e que está protegendo a aplicação de sobrecargas desnecessárias.

Monitorando o Circuit Breaker

Monitorar o estado do Circuit Breaker é crucial para entender o desempenho da sua aplicação. O Polly permite que você registre eventos de estado do Circuit Breaker, o que pode ser extremamente útil para depuração e manutenção. Aqui está um exemplo de como fazer isso:


var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(
        handledEventsAllowedBeforeBreaking: 3,
        durationOfBreak: TimeSpan.FromSeconds(30),
        onBreak: (exception, breakDelay) =>
        {
            Console.WriteLine(
            $"[OPEN] Circuit opened due to: {exception.Message}. Waiting {breakDelay.TotalSeconds} seconds before retrying.");
        },
        onReset: () =>
        {
            Console.WriteLine(
            "[CLOSED] Circuit closed. Operations resumed successfully.");
        },
        onHalfOpen: () =>
        {
            Console.WriteLine(
            "[HALF-OPEN] Circuit is half-open. Testing service availability...");
        });
    

Neste exemplo, estamos adicionando dois manipuladores de eventos: um para quando o circuito é aberto (onBreak) e outro para quando o circuito é redefinido (onReset). Esses eventos permitem que você registre informações sobre o estado do Circuit Breaker, ajudando a identificar padrões de falhas e a ajustar as configurações conforme necessário.

Conclusão

O padrão Circuit Breaker contribui no aumento da resiliência de aplicações .NET. Usando a biblioteca Polly, é possível implementar essa técnica de forma simples e eficiente. Monitorar o estado do Circuit Breaker e ajustar suas configurações são passos fundamentais para garantir que sua aplicação continue a funcionar de maneira confiável, mesmo em face de falhas externas. Ao integrar o Circuit Breaker em sua estratégia de desenvolvimento, você estará proporcionando uma base mais robusta e segura para suas aplicações, melhorando a experiência do usuário e a confiabilidade do sistema a longo prazo.

Referências

  • PUNITHAVATHY, E.; PRIYA, N. Comparative Study of Static Resilience Patterns Over Dynamically Modified Resilience Patterns. 2024. reference.Description
  • PUNITHAVATHY, E.; PRIYA, N. Auto retry circuit breaker for enhanced performance in microservice applications. International Journal of Electrical & Computer Engineering (2088-8708), v. 14, n. 2, 2024. reference.Description
  • COSTA, Thiago M. et al. Avaliação de Desempenho de Dois Padrões de Resiliência para Microsserviços: Retry e Circuit Breaker. In: Simpósio Brasileiro de Redes de Computadores e Sistemas Distribuídos (SBRC). SBC, 2022. p. 517-530. reference.Description
  • POLLY, GitHub. Polly: The .NET resilience and transient-fault-handling library. Disponível em: https://www.pollydocs.org . Acesso em: 15 abril. 2025. reference.Description
  • FOWLER, M. Circuit Breaker. 2014. Disponível em https://martinfowler.com/bliki/CircuitBreaker.html. Acesso em: 15 abril. 2025. reference.Description
  • MICROSOFT. Circuit Breaker pattern. Disponível em https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker. Acesso em: 15 abril. 2025. reference.Description
Sobre o autor