404 Not Found

404 Not Found


nginx

Spring Boot Actuator

O Actuator é o painel do Spring Boot—fornece status de saúde, métricas e informações de configuração—e oferece às equipes de operações uma "visão panorâmica."

1. O Que Você Vai Aprender


2. Uma História Real de um Engenheiro de Operações

(1) Dor: O ambiente de produção é como uma caixa preta

Bob é responsável pelas operações e manutenção do ambiente de produção do OrderFlow, mas a aplicação é uma caixa preta completa para ele: As conexões com o banco de dados estão funcionando corretamente? Quanta memória está sendo usada? Quais APIs estão respondendo lentamente? Toda vez que surge um problema, ele precisa pedir à Alice para adicionar logs ou reiniciar a aplicação para solucioná-lo, resultando em um Tempo Médio de Recuperação (MTTR) de mais de 1 hora. Charlie exigiu que o MTTR fosse reduzido para 10 minutos.

(2) Solução com o Actuator

O Actuator está pronto para uso imediato e oferece uma ampla variedade de endpoints de operações e manutenção:

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
BASH
curl http://localhost:8080/actuator/health
# {"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"}}}

(3) Resultado

Depois que Bob começou a usar o Actuator, /health monitorou a conectividade do banco de dados, /metrics acompanhou os tempos de resposta das APIs, e um HealthIndicator personalizado verificou o gateway de pagamento externo, reduzindo o MTTR de 1 hora para 5 minutos.


3. Visão Geral dos Endpoints do Actuator

(1) Lista de Endpoints Integrados

Endpoint Descrição Exposição Padrão
/actuator/health Status de Saúde da Aplicação ✅ Sim
/actuator/info Informações da Aplicação ✅ Sim
/actuator/metrics Lista de Indicadores ❌ Não
/actuator/metrics/{name} Valor de métrica específica ❌ Não
/actuator/env Configuração de Ambiente ❌ Não
/actuator/beans Lista de Beans ❌ Não
/actuator/loggers Nível de Log ❌ Não
/actuator/threaddump Thread Dump ❌ Não
/actuator/heapdump Heap Dump ❌ Não
/actuator/prometheus Métricas no formato Prometheus ❌ Não

(1) ▶ Exemplo: Habilitando a dependência do Actuator

XML
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Saída:

TEXT
// Execução bem-sucedida

(2) ▶ Exemplo: Configurando a Exposição de Endpoints

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,loggers
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
    metrics:
      enabled: true
  info:
    env:
      enabled: true

Saída:

TEXT
A configuração entrou em vigor.
Política de Exposição Valor de Configuração Descrição
Apenas Saúde e Informações include: health,info Mais seguro, Padrão
Exposição Sob Demanda include: health,info,metrics Recomendado
Mostrar Tudo include: "*" Apenas Ambiente de Desenvolvimento
Excluir Específicos exclude: env,beans Excluir de Todos

4. Explicação Detalhada do Endpoint de Saúde

(1) Regras de Agregação de Status de Saúde

100%
graph TD
    A["Agregador de<br/>Status de Saúde"] --> B["DiskSpace<br/>UP"]
    A --> C["DataSource<br/>UP"]
    A --> D["PaymentGateway<br/>DOWN"]
    A --> E["Redis<br/>UP"]
    D --> F["Geral: DOWN<br/>Qualquer DOWN → DOWN"]
Status Significado Regras de Agregação
UP Normal
DOWN Exceção Qualquer DOWN individual → Geral DOWN
DEGRADED Degradado Degradação de componente não crítico
OUT_OF_SERVICE Serviço Indisponível Qualquer um → Todos OUT_OF_SERVICE
UNKNOWN Desconhecido Padrão

(1) ▶ Exemplo: HealthIndicator Personalizado

JAVA
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {

    private final RestTemplate restTemplate;

    public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public Health health() {
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(
                "https://api.payment-gateway.com/ping", String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                return Health.up()
                    .withDetail("gateway", "reachable")
                    .withDetail("responseTime", response.getHeaders().getDate())
                    .build();
            }
            return Health.down()
                .withDetail("gateway", "unhealthy")
                .withDetail("statusCode", response.getStatusCode())
                .build();
        } catch (Exception e) {
            return Health.down()
                .withDetail("gateway", "unreachable")
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

Saída:

TEXT
// Execução bem-sucedida
💻 Saída:

JSON
{
  "status": "DOWN",
  "components": {
    "diskSpace": {"status": "UP", "details": {"total": 536870912000, "free": 268435456000}},
    "db": {"status": "UP", "details": {"database": "MySQL", "validationQuery": "SELECT 1"}},
    "paymentGateway": {"status": "DOWN", "details": {"gateway": "unreachable", "error": "Connection refused"}}
  }
}

5. Explicação Detalhada dos Endpoints de Métricas

(1) ▶ Exemplo: Visualizar métricas de requisições HTTP

BASH
# Listar todas as métricas disponíveis
curl http://localhost:8080/actuator/metrics

# Obter métrica específica: requisições do servidor HTTP
curl http://localhost:8080/actuator/metrics/http.server.requests

# Obter métrica filtrada
curl "http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/v1/orders&tag=status:200"

Saída:

TEXT
{"status":"ok","data":{}}
Métricas Comuns Descrição
http.server.requests Distribuição de Duração das Requisições HTTP
jvm.memory.used Uso de Memória da JVM
jvm.threads.live Número de Threads Ativas
process.cpu.usage Uso de CPU do Processo
disk.total / disk.free Espaço em Disco
hikaricp.connections.active Pool de Conexões do Banco de Dados

(2) ▶ Exemplo: Métricas de Negócio Personalizadas

JAVA
@Service
public class OrderMetrics {

    private final Counter orderCreatedCounter;
    private final Timer orderCreationTimer;
    private final AtomicLong pendingOrders;

    public OrderMetrics(MeterRegistry registry) {
        this.orderCreatedCounter = Counter.builder("orderflow.orders.created")
            .description("Total de pedidos criados")
            .tag("service", "orderflow")
            .register(registry);

        this.orderCreationTimer = Timer.builder("orderflow.orders.creation.time")
            .description("Tempo de criação do pedido")
            .register(registry);

        this.pendingOrders = registry.gauge("orderflow.orders.pending",
            new AtomicLong(0));
    }

    public void recordOrderCreated() {
        orderCreatedCounter.increment();
        pendingOrders.incrementAndGet();
    }

    public void recordOrderCompleted() {
        pendingOrders.decrementAndGet();
    }

    public Timer getCreationTimer() {
        return orderCreationTimer;
    }
}

Saída:

TEXT
// Execução bem-sucedida

6. Endpoints Personalizados

(1) ▶ Exemplo: Endpoint OrderStats Personalizado

JAVA
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {

    private final OrderRepository orderRepository;

    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @ReadOperation
    public Map<String, Object> orderStats() {
        long total = orderRepository.count();
        long pending = orderRepository.countByStatus("PENDING");
        long completed = orderRepository.countByStatus("COMPLETED");
        long cancelled = orderRepository.countByStatus("CANCELLED");
        return Map.of(
            "totalOrders", total,
            "pendingOrders", pending,
            "completedOrders", completed,
            "cancelledOrders", cancelled,
            "completionRate", total > 0
                ? String.format("%.2f%%", (double) completed / total * 100)
                : "N/A"
        );
    }

    @ReadOperation
    public Map<String, Object> orderStatsByStatus(
            @Selector String status) {
        long count = orderRepository.countByStatus(status.toUpperCase());
        return Map.of("status", status, "count", count);
    }
}

Saída:

TEXT
// Execução bem-sucedida
YAML
management:
  endpoint:
    orderstats:
      enabled: true
  endpoints:
    web:
      exposure:
        include: health,info,orderstats
💻 Saída:

BASH
curl http://localhost:8080/actuator/orderstats
# {"totalOrders":1523,"pendingOrders":45,"completedOrders":1420,"cancelledOrders":58,"completionRate":"93.30%"}

curl http://localhost:8080/actuator/orderstats/PENDING
# {"status":"PENDING","count":45}

7. Fortalecimento de Segurança

(1) Política de Segurança de Endpoints

Nível Política Descrição
Camada de Rede Porta de Gerenciamento Dedicada management.server.port=8081
Camada de Rede Vincular a IP Interno management.server.address=127.0.0.1
Camada de Aplicação Controle Spring Security .requestMatchers("/actuator/**").hasRole("ADMIN")
Camada de Endpoint Desabilitar Endpoints Sensíveis management.endpoint.env.enabled=false

(1) ▶ Exemplo: Configuração de Segurança em Nível de Produção

YAML
# application-prod.yml
management:
  server:
    port: 8081                    # Porta de gerenciamento separada
    address: 127.0.0.1            # Vincular apenas ao localhost
  endpoints:
    web:
      exposure:
        include: health,prometheus,orderstats
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
    env:
      enabled: false
    beans:
      enabled: false
    heapdump:
      enabled: false

Saída:

TEXT
Configuração de monitoramento carregada
Alvos do Prometheus: 3 ativos
Dashboard do Grafana: pronto
Ambiente Política de Exposição Porta de Gerenciamento
Desenvolvimento include: "*" Porta 8080
Teste include: health,info,metrics,env Mesma porta 8080
Produção include: health,prometheus Porta Dedicada 8081 + Rede Interna

8. Exemplo Abrangente: Configuração Completa do Actuator do OrderFlow

YAML
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus,orderstats
  endpoint:
    health:
      show-details: when-authorized
    orderstats:
      enabled: true
  metrics:
    tags:
      application: ${spring.application.name}
  info:
    env:
      enabled: true

info:
  app:
    name: OrderFlow Service
    version: @project.version@
    description: Microsserviço de gerenciamento de pedidos de e-commerce
JAVA
// PaymentGatewayHealthIndicator.java
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
    private final RestTemplate restTemplate;
    public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    @Override
    public Health health() {
        try {
            ResponseEntity<String> resp = restTemplate
                .getForEntity("https://api.payment.com/ping", String.class);
            return resp.getStatusCode().is2xxSuccessful()
                ? Health.up().withDetail("gateway", "reachable").build()
                : Health.down().withDetail("statusCode", resp.getStatusCode()).build();
        } catch (Exception e) {
            return Health.down().withDetail("error", e.getMessage()).build();
        }
    }
}

// OrderStatsEndpoint.java
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {
    private final OrderRepository orderRepository;
    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
    @ReadOperation
    public Map<String, Object> stats() {
        return Map.of(
            "total", orderRepository.count(),
            "pending", orderRepository.countByStatus("PENDING"),
            "completed", orderRepository.countByStatus("COMPLETED")
        );
    }
}

❓ Perguntas Frequentes

P Os endpoints do Actuator afetam o desempenho?
R Operações de leitura (health, metrics) têm overhead mínimo. Operações de heapdump e threaddump pausam a aplicação e são desabilitadas por padrão em ambientes de produção. O intervalo de coleta recomendado para endpoints Prometheus é de 15-30 segundos.
P Quem deve usar o endpoint de verificação de saúde?
R /health é para balanceadores de carga e probes do K8s; não expõe detalhes sensíveis. /health com detalhes é destinado às equipes de operações e requer permissões de ADMIN. Use show-details: when-authorized em ambientes de produção.
P Como personalizar as regras de agregação de status de saúde?
R Implemente o HealthAggregator ou use o bean StatusAggregator. A regra padrão é: Qualquer DOWN → Geral DOWN. Você pode personalizar a prioridade usando statusOrder.
P O /actuator/env expõe senhas?
R Ele exibe valores de configuração, mas por padrão, o Spring Boot 3.x mascara pares chave-valor que contêm password, secret, key e token (exibindo ••••••). Ainda assim, é recomendado desabilitar este endpoint em ambientes de produção.
P Quais são os benefícios de separar as portas de gerenciamento das portas da aplicação?
R 1) As portas de gerenciamento são vinculadas apenas à rede interna e não são expostas à internet pública; 2) O tráfego da aplicação e o tráfego de gerenciamento são isolados e não interferem entre si; 3) Diferentes políticas de segurança podem ser configuradas para as portas de gerenciamento.
P Como integrar as métricas do Actuator com o Prometheus?
R Adicione a dependência micrometer-registry-prometheus, exponha o endpoint prometheus e adicione um alvo de coleta na configuração do Prometheus. Isso será abordado em detalhes em uma aula posterior (L23).

📖 Resumo


📝 Exercícios

  1. Exercício Básico (Dificuldade ⭐): Adicione o Actuator ao OrderFlow, configure-o para expor os endpoints health, info e metrics, e verifique se /actuator/health retorna o status "UP".

  2. Exercício Avançado (Dificuldade: ⭐⭐): Implemente um PaymentGatewayHealthIndicator personalizado e um OrderStatsEndpoint, e configure uma porta de gerenciamento separada para o ambiente de produção.

  3. Desafio (Dificuldade: ⭐⭐⭐): Adicione a dependência micrometer-registry-prometheus, exponha o endpoint /actuator/prometheus, escreva métricas de negócio personalizadas (contagem de criação de pedidos, tempo de realização de pedidos) e considere convenções de nomenclatura e design de tags para as métricas.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%