Rastreamento Distribuído de Microsserviços com Apache SkyWalking

Introdução ao Rastreamento Distribuído

Em arquiteturas de microsserviços compostas por dezenas ou centenas de serviços, surgem desafios como: como conectar toda a cadeia de chamadas para localizar problemas rapidamente, como mapear dependências entre serviços, como analisar o desempenho de cada interface e como acompanhar a ordem de processamento de um fluxo de negócio completo.

O que é o Apache SkyWalking

O SkyWalking é uma ferramenta de APM (Application Performance Management) de código aberto, idealizada em 2015 e ingressou no incubador da Apache em 2017. É projetada para arquiteturas de microsserviços, cloud-native e baseadas em contêineres (Docker, Kubernetes, Mesos). Oferece rastreamento distribuído, análise de métricas de desempenho e análise de dependências entre aplicações e serviços.

Comparação entre Frameworks de Rastreamento

Existem várias soluções no mercado para rastreamento distribuído:

  1. Zipkin: Ferramenta da Twitter, amplamente adotada via Spring Cloud Sleuth. Leve e de fácil implantação.
  2. Pinpoint: Solução coreana baseada em injeção de bytecode, com forte UI e sem invasão de código no cliente.
  3. SkyWalking: Solução chinesa também baseada em injeção de bytecode, com boa UI e sem invasão de código. Atualmente projeto da Apache.
  4. CAT: Plataforma da Dianping para rastreamento, monitoramento, coleta de logs e alertas.

Análise de Desempenho

Testes com JMeter simulando 500, 750 e 1000 usuários simultâneos, cada thread enviando 30 requisições com think time de 10ms e taxa de amostragem de 100%, revelaram que o agente do SkyWalking tem o menor impacto na vazão. O Zipkin ficou em posição intermediária. O Pinpoint apresentou impacto mais significativo — em 500 usuários, a vazão caiu de 1385 para 774. O impacto sobre CPU e memória ficou em torno de 10% para todos os componentes.

Principais Características do SkyWalking

  • Múltiplos mecanismos de monitoramento: sondas de linguagem e service mesh
  • Sondas automáticas para Java, .NET Core e Node.js
  • Leve e eficiente, sem necessidade de plataforma de big data
  • Arquitetura modular: UI, armazenamento e gerenciamento de cluster com múltiplas opções
  • Suporte a alertas
  • Excelente visualização de dados

Implantação do SkyWalking

A arquitetura do SkyWalking é composta por quatro elementos principais:

  • Agente: Acoplado à aplicação, coleta dados de monitoramento
  • OAP Server: Processa os dados recebidos dos agentes, armazena em banco de dados e responde a requisições da interface web. Geralmente em cluster
  • Web UI: Interface de visualização dos dados
  • Armazenamento: Banco de dados como MySQL, Elasticsearch, etc.

Download e Configuração Inicial

Baixe o pacote em http://skywalking.apache.org/downloads/. Para alterar a porta padrão da interface web (8080), edite o arquivo webapp/webapp.yml. Inicie os serviços executando bin/startup.bat (Windows) ou bin/startup.sh (Linux), o que sobe tanto o OAP Server quanto a Web UI.

Serviço OAP (Observability Analysis Platform)

O OAP Server expõe duas portas:

  • 11800: Recebe dados de monitoramento dos agentes (gRPC)
  • 12800: Atende requisições da interface web (HTTP)

As portas podem ser redefinidas em config/application.yml. A Web UI utiliza por padrão a porta 8080, configurável em webapp/webapp.yml através da propriedade server.port. O endereço do OAP é definido em collector.ribbon.listOfServers.

Conceitos Fundamentais

  • Serviço (Service): Conjunto de workloads que oferecem o mesmo comportamento. O nome pode ser definido via agente
  • Instância de Serviço (Service Instance): Cada workload individual dentro do conjunto, correspondendo a um processo real no sistema operacional
  • Endpoint: Caminho de requisição recebido por um serviço, como URI HTTP ou classe + assinatura de método gRPC

Integração com Microsserviços

Ambiente Linux — Execução via JAR

Configure o agente SkyWalking através do parâmetro -javaagent no script de inicialização:

#!/bin/bash
# Configurações do agente
export SW_AGENT_NAME=ms-tracking-demo
export SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
export SW_AGENT_SPAN_LIMIT=2000
export AGENT_PATH=-javaagent:/opt/skywalking/agent/skywalking-agent.jar

java $AGENT_PATH -jar ms-tracking-demo-1.0.0.jar

Equivalente a passar os parâmetros diretamente na linha de comando:

java -javaagent:/opt/skywalking/agent/skywalking-agent.jar \
  -DSW_AGENT_NAME=ms-tracking-demo \
  -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 \
  -jar ms-tracking-demo-1.0.0.jar

Os parâmetros correspondem às propriedades em agent/config/agent.config. A passagem via linha de comando tem prioridade sobre o arquivo de configuração.

Ambiente Windows — No IntelliJ IDEA

Configure os argumentos JVM nas opções de execução da aplicação:

-javaagent:D:\skywalking\agent\skywalking-agent.jar
-DSW_AGENT_NAME=ms-tracking-demo
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.100:11800

O endereço do collector pode ser remoto, mas o caminho do skywalking-agent.jar deve apontar para o disco local.

Rastreamento entre Múltiplos Microsserviços

Basta adicionar o parâmetro -javaagent em cada microsserviço. Para que o gateway apareça na topologia, copie o plugin de gateway de agent/optional-plugins para agent/plugins.

Persistência de Dados de Rastreamento

Por padrão, o SkyWalking utiliza H2 (banco em memória). Os dados são perdidos ao reiniciar. Para persistir em MySQL:

  1. Edite config/application.yml, alterando o seletor de storage:
storage:
  selector: ${SW_STORAGE:mysql}
  mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/sw_db"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root}

  1. Copie o driver JDBC do MySQL para o diretório oap-libs, pois ele não vem incluído por padrão
  2. Reinicie o SkyWalking e verifique a criação automática das tabelas no banco

Customização do Rastreamento

Adicione a dependência do toolkit compatível com a versão do SkyWalking:

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-trace</artifactId>
    <version>8.5.0</version>
</dependency>

Anotação @Trace

Para que um método de negócio apareça na cadeia de rastreamento na interface web, basta anotá-lo com @Trace.

Anotações @Tag e @Tags

Para registrar parâmetros e valores de retorno, utilize @Tag ou @Tags:

@Trace
@Tag(key = "resultado", value = "returnedObj")
public List<User> findAll() {
    return userMapper.selectAll();
}

@Trace
@Tags({
    @Tag(key = "parametro", value = "arg[0]"),
    @Tag(key = "usuario", value = "returnedObj")
})
public User findById(Integer id) {
    return userMapper.selectById(id);
}

Profile de Desempenho

O SkyWalking permite criar tarefas de profiling baseadas em nome de serviço e endpoint. Ao chamar o endpoint monitorado, o sistema grava a análise e exibe qual linha de código está mais lenta.

Integração com Frameworks de Log

Adicione a dependência do toolkit para Logback:

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>8.5.0</version>
</dependency>

Crie ou edite o arquivo logback-spring.xml incluindo o placeholder %tid (Trace ID), que permite buscar diretamente na interface do SkyWalking:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            </layout>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="stdout"/>
    </root>
</configuration>

Envio de Logs via gRPC

A partir da versão 8.4.0, é possível encaminhar logs diretamente ao OAP Server. Adicione o appender gRPC no logback-spring.xml:

<appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </encoder>
</appender>

<root level="info">
    <appender-ref ref="grpc-log" />
</root>

Se o OAP estiver em outro servidor, configure o endereço remoto em agent/config/agent.config:

plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:127.0.0.1}
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}

Funcionalidade de Alertas

Os alertas foram introduzidos na versão 6.x e são definidos em config/alarm-settings.yml, divididos em duas partes: regras de alerta e webhooks.

Regras de Alerta

O SkyWalking traz regras pré-definidas, como:

  • Tempo médio de resposta do serviço > 1s nos últimos 3 minutos
  • Taxa de sucesso do serviço < 80% nos últimos 2 minutos
  • Tempo médio de resposta de endpoint > 1s nos últimos 2 minutos
  • Tempo médio de acesso a banco > 1s nos últimos 2 minutos

Pirncipais campos de configuração:

  • Rule name: Nome único, deve terminar com _rule
  • Metrics name: Nome da métrica definida no script OAL
  • Include/Exclude names: Filtra entidades afetadas pela regra
  • Threshold: Valor limite
  • OP: Operador (>, <, =)
  • Period: Janela de tempo para verificação
  • Count: Quantas vezes o limite deve ser ultrapassado no Period para disparar o alerta
  • Silence period: Período de silenciamento após um alerta
  • Message: Texto do alerta

Webhooks

O SkyWalking envia alertas via POST HTTP com Content-Type application/json, serializando uma lista de AlarmMessage. Exemplo do payload:

[
  {
    "scopeId": 1,
    "scope": "SERVICE",
    "name": "serviceA",
    "id0": "12",
    "id1": "",
    "ruleName": "service_resp_time_rule",
    "alarmMessage": "alarmMessage xxxx",
    "startTime": 1560524171000
  }
]

Implementação de Alertas por E-mail

O SkyWalking não envia e-mails diretamente — ele chama o webhook configurado. Implemente um endpoint que receba o alerta e encaminhe por e-mail. Adicione a dependência:

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

Configure o servidor SMTP em application.yml:

server:
  port: 9134

spring:
  mail:
    host: smtp.163.com
    username: seu_email@163.com
    password: sua_chave_smtp
    default-encoding: utf-8
    port: 465
    protocol: smtp
    properties:
      mail:
        smtp:
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory

DTO para receber os dados do alerta:

@Data
public class AlarmNotification {
    private Integer scopeId;
    private String scope;
    private String name;
    private Integer id0;
    private Integer id1;
    private String ruleName;
    private String alarmMessage;
    private Long startTime;
}

Controller que recebe o alerta e envia o e-mail:

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/alarm")
public class AlarmNotificationController {

    private final JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String emailFrom;

    @PostMapping("/receive")
    public void handleAlarm(@RequestBody List<AlarmNotification> alarms) {
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom(emailFrom);
        msg.setTo(emailFrom);
        msg.setSubject("Notificação de Alerta SkyWalking");
        msg.setText(formatAlarmContent(alarms));
        mailSender.send(msg);
        log.info("Alerta enviado por e-mail com sucesso");
    }

    private String formatAlarmContent(List<AlarmNotification> alarms) {
        StringBuilder content = new StringBuilder();
        for (AlarmNotification alarm : alarms) {
            content.append("Escopo: ").append(alarm.getScope())
                .append("\nEntidade: ").append(alarm.getName())
                .append("\nID: ").append(alarm.getId0())
                .append("\nRegra: ").append(alarm.getRuleName())
                .append("\nMensagem: ").append(alarm.getAlarmMessage())
                .append("\nTimestamp: ").append(alarm.getStartTime())
                .append("\n------------------------\n\n");
        }
        return content.toString();
    }
}

Registre o webhook em config/alarm-settings.yml:

webhooks:
  - http://127.0.0.1:9134/alarm/receive

Alta Disponibilidade do SkyWalking

Em ambientes de produção, o OAP Server deve operar em cluster. O SkyWalking registra cada instância do OAP no Nacos como serviço de registro. Enquanto houver ao menos uma instância ativa, o rastreamento continua funcionando.

Requisitos para um cluster:

  • Um Nacos (ou cluster Nacos)
  • Um Elasticsearch ou MySQL (ou cluster correspondente)
  • Mínimo de 2 instâncias do OAP Server
  • UI com Nginx como proxy de entrada (opcionalmente com múltiplas instâncias)

Em config/application.yml, configure o Nacos como registry e o Elasticsearch como storage. Na configuração da Web UI (webapp/webapp.yml), defina múltiplos endereços em collector.ribbon.listOfServers:

collector:
  ribbon:
    listOfServers: 192.168.3.10:12800,192.168.3.12:12800

Nas aplicações, aponte o agente para os OAP Servers do cluster:

-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.10:11800,192.168.3.12:11800

Tags: skywalking apm Distributed Tracing microsservicos apache

Publicado em 7-4 09:04