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.
- Site oficial: http://skywalking.apache.org/
- Downloads: http://skywalking.apache.org/downloads/
- GitHub: https://github.com/apache/skywalking
Comparação entre Frameworks de Rastreamento
Existem várias soluções no mercado para rastreamento distribuído:
- Zipkin: Ferramenta da Twitter, amplamente adotada via Spring Cloud Sleuth. Leve e de fácil implantação.
- Pinpoint: Solução coreana baseada em injeção de bytecode, com forte UI e sem invasão de código no cliente.
- 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.
- 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:
- 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}
- Copie o driver JDBC do MySQL para o diretório
oap-libs, pois ele não vem incluído por padrão - 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