Pular para o conteúdo

Arquitetura de software · Confiabilidade e segurança · 7 min de leitura

Circuit breaker e backpressure

Quando uma dependência fica lenta, insistir derruba quem chama. O circuit breaker para de chamar por um tempo; o backpressure faz o produtor desacelerar em vez de afogar o consumidor.

Fechado → Aberto: muitas falhasmuitas falhas1Aberto → Meio-aberto: após 30 sapós 30 s2Meio-aberto → Fechado: teste deu certoteste deu certo3Fechado — chamadas passamFechadochamadas passamAberto — falha na horaAbertofalha na horaMeio-aberto — testa 1 chamadaMeio-abertotesta 1 chamada

Arraste para o lado para ver o diagrama inteiro.

Aberto, o disjuntor responde na hora com erro ou valor alternativo, poupando threads e dando tempo para a dependência se recuperar. Se a chamada de teste falhar, ele volta a abrir.

Falhas em cascata

Um serviço de recomendações fica lento. Cada requisição que o chama segura uma thread ou conexão esperando o timeout; em segundos o pool acaba e o seu serviço também para de responder — inclusive nas rotas que nem usam recomendações. Timeouts curtos ajudam, mas continuar chamando algo que está falhando só piora para os dois lados.

Circuit breaker

  • Fechado: funcionamento normal; conta as falhas numa janela recente.
  • Aberto: passou do limite (ex.: 50% de falhas em 20 chamadas) — falha imediatamente, sem chamar, por um tempo.
  • Meio-aberto: deixa passar poucas chamadas de teste; se derem certo, fecha; senão, abre de novo.

Combine com um fallback útil: dados em cache, lista padrão, funcionalidade desligada (“recomendações indisponíveis”). E isole recursos por dependência (bulkhead): um pool de conexões para cada uma.

Backpressure

O problema inverso: um produtor mais rápido que o consumidor. Sem controle, a fila em memória cresce até estourar. Backpressure é o consumidor sinalizar quanto aguenta:

  • Filas limitadas que bloqueiam ou recusam quando cheias.
  • Reactive Streams: o consumidor pede request(n) itens.
  • Kotlin Flow: o coletor suspende o emissor naturalmente; buffer, conflate (fica só o mais recente) e collectLatest escolhem o que fazer com o excesso.
  • No servidor: descarte de carga — responder 503 rápido para parte das requisições é melhor que atender todas devagar.

No código

✓ ExemploKotlin
class CircuitBreaker(
    private val maxFailures: Int = 5,
    private val openFor: Duration = 30.seconds,
    private val clock: () -> Instant = Clock.System::now,
) {
    private enum class State { CLOSED, OPEN, HALF_OPEN }
    private var state = State.CLOSED
    private var failures = 0
    private var openedAt = Instant.DISTANT_PAST
    private val lock = Mutex()

    suspend fun <T> call(fallback: () -> T, block: suspend () -> T): T {
        lock.withLock {
            if (state == State.OPEN) {
                if (clock() - openedAt < openFor) return fallback()
                state = State.HALF_OPEN // tempo esgotado: deixa uma chamada testar
            }
        }
        return try {
            block().also { lock.withLock { state = State.CLOSED; failures = 0 } }
        } catch (e: CancellationException) {
            throw e
        } catch (e: Exception) {
            lock.withLock {
                failures++
                if (state == State.HALF_OPEN || failures >= maxFailures) {
                    state = State.OPEN
                    openedAt = clock()
                }
            }
            fallback()
        }
    }
}

// Uso: recomendações nunca derrubam a tela de produto.
val recs = breaker.call(fallback = { emptyList() }) { api.recommendations(productId) }

Versão didática: conta falhas seguidas, abre por 30 segundos e testa uma chamada antes de fechar. Em produção, use uma biblioteca (Resilience4j, Polly) com janela deslizante e métricas.

Em resumo

Vantagens e custos

Vantagens
  • Evita falhas em cascata.
  • Dá tempo para a dependência se recuperar.
  • Degradação controlada em vez de queda total.
Custos e riscos
  • Limites mal calibrados abrem à toa ou tarde demais.
  • Fallback precisa ser pensado por funcionalidade.
  • Mais um estado para observar e testar.

Perguntar à IA

Monte um prompt pronto sobre Circuit breaker e backpressure na sua linguagem e no seu caso, e abra num chat gratuito.

ChatGPT Claude Perplexity

O prompt vai para o site que você escolher. Não cole senhas, tokens nem dados reais de clientes. Para Gemini e outros, copie e cole.

Referências

Continue aprendendo

Todos os temas de arquitetura de software →