Arquitetura e Fundamentos do Sentinel para Resiliência de Microsserviços

O Sentinel é uma biblioteca robusta focada na proteção de serviços em arquiteturas distribuídas. Ele atua principalmente no controle de fluxo, isolamento de recursos e estabilidade do sistema, oferecendo mecanismos para evitar falhas em cascata e garantir a disponibilidade de aplicações críticas.

Conceitos Estruturais: Recursos e Regras

No ecossistema do Sentinel, dois pilares sustentam sua operação:

  • Recursos: Representam qualquer trecho de código ou serviço que necessite de proteção. Pode ser um método Java, um endpoint HTTP ou um serviço RPC. No Sentinel, definimos um recurso para monitorar sua execução.
  • Regras: São as políticas aplicadas aos recursos. Elas definem limites de tráfego (QPS), condições de interrupção (Circuit Breaker) ou proteções baseadas na carga do sistema. As regras podem ser alteradas dinamicamente sem reiniciar a aplicação.

Principais Estratégias de Proteção

1. Controle de Tráfego (Flow Control)

Diferente de uma limitação estática, o Sentinel ajusta o tráfego de entrada conforme a capacidade de processamento. Ele permite moldar picos de requisições, suavizando o fluxo para que o sistema não seja sobrecarregado repentinamente.

2. Tolerância a Falhas e Degradação

O Sentinel implementa o padrão Circuit Breaker. Se um serviço externo começa a responder letnamente ou apresenta alta taxa de erro, o Sentinel interrompe as chamadas temporariamente (estado aberto), protegendo os recursos locais de ficarem presos aguardando respostas que provavelmente falharão.

3. Proteção Adaptativa do Sistema

Além de olhar para recursos individuais, o Sentinel monitora métricas globais da máquina, como uso de CPU e tempo de resposta geral. Se o sistema atinge um estado crítico, ele pode rejeitar novas requisições preventivamente para evitar o colapso total (load shedding).

Implementação Prática

Para integrar o Sentinel em um projeto Maven, adicione a dependência principle:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.6</version>
</dependency>

Definindo um Recurso Manualmente

A forma mais direta de proteger um bloco de execução é utilziando a API SphU. Veja um exemplo de implementação:

public void processarTransacao() {
    // Definir a lógica de proteção
    try (Entry entrada = SphU.entry("ServicoTransacao")) {
        // Lógica de negócio que deve ser protegida
        executarPagamento();
    } catch (BlockException ex) {
        // Ação executada quando o limite de tráfego é atingido
        logger.warn("Transação bloqueada por excesso de carga.");
    }
}

Alternativamente, é possível utilizar anotações para simplificar o código, integrando com Spring AOP:

@SentinelResource(value = "ServicoTransacao", blockHandler = "tratarBloqueio")
public void executarPagamento() {
    // Lógica principal
}

Configuração de Regras de Fluxo

As regras determinam o comportamento do controle. No exemplo abaixo, limitamos o recurso a no máximo 15 requisições por segundo (QPS):

private static void configurarLimites() {
    List<FlowRule> listaRegras = new ArrayList<>();
    FlowRule regraFluxo = new FlowRule();
    
    regraFluxo.setResource("ServicoTransacao");
    regraFluxo.setGrade(RuleConstant.FLOW_GRADE_QPS);
    regraFluxo.setCount(15); // Limite de 15 QPS
    
    listaRegras.add(regraFluxo);
    FlowRuleManager.loadRules(listaRegras);
}

Arquitetura Interna e Classes Fundamentais

A inteligência do Sentinel reside no seu motor de processamento, que utiliza uma cadeia de responsabilidades (Slot Chain) para avaliar cada requisição.

  • ProcessorSlotChain: É o coração do sistema. Ele organiza diversos "slots" que realizam tarefas específicas, como coleta de estatísticas, verificação de regras de fluxo e validação de regras de sistema.
  • Context: Armazena metadados sobre a cadeia de chamadas atual, permitindo que o Sentinel entenda a origem da requisição e como ela se propaga.
  • Node: Estrutura responsável por armazenar as métricas em tempo real. Existem diferentes tipos, como o StatisticNode (base para métricas) e ClusterNode (visão global do recurso).
  • StatisticSlot: Um componente vital que registra sucessos, falhas e tempos de resposta (RT) usando janelas deslizantes (sliding windows).

Análise do Mecanismo de Decisão (DefaultController)

Quando uma requisição chega, o Sentinel consulta um controlador de tráfego para decidir se ela pode prosseguir. O DefaultController implementa a estratégia de rejeição imediata. Internamente, o método canPass realiza a seguinte lógica:

@Override
public boolean canPass(Node node, int quantidadeRequisitada, boolean prioridade) {
    int usoAtual = obterTokensUsados(node);
    
    // Verifica se a soma do uso atual com o solicitado ultrapassa o limite da regra
    if (usoAtual + quantidadeRequisitada > this.count) {
        // Se houver prioridade e for QPS, pode tentar ocupar o próximo slot de tempo
        if (prioridade && grade == RuleConstant.FLOW_GRADE_QPS) {
            long tempoEspera = node.tryOccupyNext(TimeUtil.currentTimeMillis(), quantidadeRequisitada, count);
            if (tempoEspera < OccupyTimeoutProperty.getOccupyTimeout()) {
                return true;
            }
        }
        return false;
    }
    return true;
}

Esse mecanismo garante que, em situações normais, o sistema responda instantaneamente, bloqueando o excesso sem adicionar latência desnecessária à infraestrutura.

Tags: sentinel java microservices Resilience Flow Control

Publicado em 7-28 07:44