O Zipkin é um sistema de rastreamento distribuído de código aberto, desenvolvido pelo Twitter para rastrear dados em tempo real. Ele agrega dados de monitoramento em tempo real coletados de vários sistemas heterogêneos. Use o Zipkin para relatar dados de aplicações Java ao Managed Service for OpenTelemetry.
O Zipkin oferece suporte a diversos frameworks Java por meio da biblioteca de instrumentação Brave, incluindo Apache HttpClient, Dubbo, gRPC, JAX-RS 2.X, Jersey Server, JMS, Kafka, MySQL, Netty, OkHttp, Servlet, Spark, Spring Boot e Spring MVC.
Escolha o método de instrumentação adequado ao seu framework:
|
Método |
Mais indicado para |
Esforço |
|
Aplicações Spring Boot |
Menor — apenas configuração |
|
|
Spring Boot ou Spring 4.x sem Sleuth |
Baixo — beans de configuração Java |
|
|
Aplicações Spring MVC mais antigas |
Baixo — definições de beans em XML |
|
|
Aplicações Apache Dubbo RPC |
Baixo — configuração XML + filtro |
|
|
Frameworks personalizados ou controle refinado |
Médio — escrita de código de rastreamento |

Pré-requisitos
Obtenha o endpoint do Zipkin no console do Tracing Analysis:
Faça login no console do Tracing Analysis.
No painel de navegação à esquerda, clique em Cluster Configurations. Em seguida, clique na aba Access point information.
Na barra de navegação superior, selecione uma região. Na seção Cluster Information, ative Show Token.
Na seção Client, clique em Zipkin.
Copie o endpoint da coluna Related Information.

Se a aplicação executar em um ambiente de produção da Alibaba Cloud, use um ponto de acesso VPC. Caso contrário, use um endpoint público. Utilize o endpoint v2, a menos que tenha um motivo específico para usar o v1.
Nas seções abaixo, substitua os seguintes espaços reservados pelos valores reais:
|
Espaço reservado |
Descrição |
|
|
URL completa do endpoint Zipkin (termina com |
|
|
URL base sem o caminho (apenas para Spring Cloud Sleuth) |
Instrumentar com Spring Cloud Sleuth
O Spring Cloud Sleuth fornece auto-instrumentação para aplicações Spring Boot com configuração mínima. Esta é a abordagem recomendada para a maioria dos projetos Spring Boot.
Baixe o
e acesse o diretório
sleuthDemo
para obter um exemplo executável.
Etapa 1: Adicionar dependências do Maven
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-core</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
Etapa 2: Configure o application.yml
Defina baseUrl como o endpoint obtido na aba Access point information da página Cluster Configurations. Obtenha o endpoint público, que termina com api/v2/spans, diretamente no console. Para o Spring Cloud Sleuth, utilize apenas a parte da URL base, sem o caminho /api/v2/spans.
spring:
application:
# This ends up as the service name in zipkin
name: sleuthDemo
zipkin:
# Uncomment to send to zipkin, replacing 192.168.99.100 with your zipkin IP address
baseUrl: <endpoint_short>
sleuth:
sampler:
probability: 1.0
sample:
zipkin:
# When enabled=false, traces log to the console. Comment to send to zipkin
enabled: true
Etapa 3: Verifique a integração
Envie uma solicitação de teste para acionar o rastreamento:
curl http://localhost:3380/traced
Para conhecer outros caminhos de solicitação, consulte os métodos em com.alibaba.apm.SampleController no projeto de demonstração.
Instrumentar com Spring Boot ou Spring 4.0 MVC
A autoconfiguração do Spring gerencia a maior parte da configuração de rastreamento. Utilize este método para aplicações Spring Boot ou Spring 4.x que não usam o Spring Cloud Sleuth.
Baixe o
e acesse o diretório
springMvcDemo/webmvc4-boot
ou
springMvcDemo/webmv4
para obter um exemplo executável.
Etapa 1: Configure beans de rastreamento e filtro
/** Configuration for how to send spans to Zipkin */
@Bean Sender sender() {
return OkHttpSender.create("<endpoint>");
}
/** Configuration for how to buffer spans into messages for Zipkin */
@Bean AsyncReporter<Span> spanReporter() {
return AsyncReporter.create(sender());
}
/** Controls aspects of tracing such as the name that shows up in the UI */
@Bean Tracing tracing(@Value("${spring.application.name}") String serviceName) {
return Tracing.newBuilder()
.localServiceName(serviceName)
.propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
.currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(MDCScopeDecorator.create()) // puts trace IDs into logs
.build()
)
.spanReporter(spanReporter()).build();
}
/** decides how to name and tag spans. By default they are named the same as the http method. */
@Bean HttpTracing httpTracing(Tracing tracing) {
return HttpTracing.create(tracing);
}
/** Creates client spans for http requests */
// We are using a BPP as the Frontend supplies a RestTemplate bean prior to this configuration
@Bean BeanPostProcessor connectionFactoryDecorator(final BeanFactory beanFactory) {
return new BeanPostProcessor() {
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override public Object postProcessAfterInitialization(Object bean, String beanName) {
if (!(bean instanceof RestTemplate)) return bean;
RestTemplate restTemplate = (RestTemplate) bean;
List<ClientHttpRequestInterceptor> interceptors =
new ArrayList<>(restTemplate.getInterceptors());
interceptors.add(0, getTracingInterceptor());
restTemplate.setInterceptors(interceptors);
return bean;
}
// Lazy lookup so that the BPP doesn't end up needing to proxy anything.
ClientHttpRequestInterceptor getTracingInterceptor() {
return TracingClientHttpRequestInterceptor.create(beanFactory.getBean(HttpTracing.class));
}
};
}
/** Creates server spans for http requests */
@Bean Filter tracingFilter(HttpTracing httpTracing) {
return TracingFilter.create(httpTracing);
}
@Autowired SpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;
/** Decorates server spans with application-defined web tags */
@Override public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(webMvcTracingCustomizer);
}
Etapa 2: Registrar a autoconfiguração
Adicione a seguinte linha ao arquivo spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
brave.webmvc.TracingConfiguration
Instrumentar com Spring 2.5 MVC ou Spring 3.0 MVC
Para aplicações Spring MVC mais antigas, configure o rastreamento por meio de definições de beans em XML.
Baixe o
e acesse o diretório
springMvcDemo/webmvc3
ou
springMvcDemo/webmvc25
para obter um exemplo executável.
Etapa 1: Configure o objeto de rastreamento no applicationContext.xml
<bean class="zipkin2.reporter.beans.OkHttpSenderFactoryBean">
<property name="endpoint" value="<endpoint>"/>
</bean>
<!-- allows us to read the service name from spring config -->
<context:property-placeholder/>
<bean class="brave.spring.beans.TracingFactoryBean">
<property name="localServiceName" value="brave-webmvc3-example"/>
<property name="spanReporter">
<bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean">
<property name="encoder" value="JSON_V2"/>
<property name="sender" ref="sender"/>
<!-- wait up to half a second for any in-flight spans on close -->
<property name="closeTimeout" value="500"/>
</bean>
</property>
<property name="propagationFactory">
<bean class="brave.propagation.ExtraFieldPropagation" factory-method="newFactory">
<constructor-arg index="0">
<util:constant static-field="brave.propagation.B3Propagation.FACTORY"/>
</constructor-arg>
<constructor-arg index="1">
<list>
<value>user-name</value>
</list>
</constructor-arg>
</bean>
</property>
<property name="currentTraceContext">
<bean class="brave.spring.beans.CurrentTraceContextFactoryBean">
<property name="scopeDecorators">
<bean class="brave.context.log4j12.MDCScopeDecorator" factory-method="create"/>
</property>
</bean>
</property>
</bean>
<bean class="brave.spring.beans.HttpTracingFactoryBean">
<property name="tracing" ref="tracing"/>
</bean>
Etapa 2: Adicionar um interceptor
<bean class="brave.httpclient.TracingHttpClientBuilder"
factory-method="create">
<constructor-arg type="brave.http.HttpTracing" ref="httpTracing"/>
</bean>
<bean factory-bean="httpClientBuilder" factory-method="build"/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="brave.spring.webmvc.SpanCustomizingHandlerInterceptor"/>
</list>
</property>
</bean>
<!-- Loads the controller -->
<context:component-scan base-package="brave.webmvc"/>
Etapa 3: Adicionar um filtro de servlet
Adicione o filtro de rastreamento ao arquivo web.xml:
<!-- Add the delegate to the standard tracing filter and map it to all paths -->
<filter>
<filter-name>tracingFilter</filter-name>
<filter-class>brave.spring.webmvc.DelegatingTracingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>tracingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Instrumentar com Dubbo
Para aplicações Apache Dubbo, o Brave fornece um módulo de instrumentação dedicado.
Baixe o
e acesse o diretório
dubboDemo
para obter um exemplo executável.
Etapa 1: Adicionar dependências do Maven
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-dubbo-rpc</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-spring-beans</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-context-slf4j</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
<version>5.4.2</version>
</dependency>
Etapa 2: Configure o objeto de rastreamento
<bean class="zipkin2.reporter.beans.OkHttpSenderFactoryBean">
<property name="endpoint" value="<endpoint>"/>
</bean>
<bean class="brave.spring.beans.TracingFactoryBean">
<property name="localServiceName" value="double-provider"/>
<property name="spanReporter">
<bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean">
<property name="sender" ref="sender"/>
<!-- wait up to half a second for any in-flight spans on close -->
<property name="closeTimeout" value="500"/>
</bean>
</property>
<property name="currentTraceContext">
<bean class="brave.spring.beans.CurrentTraceContextFactoryBean">
<property name="scopeDecorators">
<bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/>
</property>
</bean>
</property>
</bean>
Etapa 3: Ative o filtro de rastreamento
Adicione o filtro de rastreamento às configurações do provedor e do consumidor:
<!-- Server-side configuration -->
<dubbo:provider filter="tracing" />
<!-- Client-side configuration -->
<dubbo:consumer filter="tracing" />
Instrumentar manualmente
Use a API do Brave diretamente quando nenhuma das integrações de framework acima atender ao seu caso de uso.
Baixe o
e acesse o diretório
manualDemo
para obter um exemplo executável.
Etapa 1: Adicionar dependências do Maven
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
<version>2.7.9</version>
</dependency>
Etapa 2: Crie um tracer
private static final String zipkinEndPoint = "<endpoint>";
...
// Create a sender to transmit spans over HTTP
OkHttpSender sender = OkHttpSender.newBuilder().endpoint(zipkinEndPoint).build();
// Create an async reporter to batch and send spans
Reporter<Span> reporter = AsyncReporter.builder(sender).build();
tracing = Tracing.newBuilder().localServiceName(localServiceName).spanReporter(reporter).build();
Etapa 3: Crie spans
Crie um span raiz e spans filhos para representar unidades de trabalho:
private void firstBiz() {
// Create a root span.
tracing.tracer().startScopedSpan("parentSpan");
Span span = tracing.tracer().currentSpan();
span.tag("key", "firstBiz");
secondBiz();
span.finish();
}
private void secondBiz() {
tracing.tracer().startScopedSpanWithParent("childSpan", tracing.tracer().currentSpan().context());
Span childSpan = tracing.tracer().currentSpan();
childSpan.tag("key", "secondBiz");
childSpan.finish();
System.out.println("end tracing,id:" + childSpan.context().traceIdString());
}
Etapa 4: Adicionar tags personalizadas (opcional)
As tags auxiliam na filtragem e na solução de problemas. Por exemplo, registre um código de status HTTP:
tracer.activeSpan().setTag("http.status_code", "500");
Etapa 5: Propagar o contexto de rastreamento entre serviços
Em um sistema distribuído, o contexto de rastreamento (TraceId, ParentSpanId, SpanId e Sampled) trafega entre os serviços por meio de cabeçalhos HTTP. Use Inject no lado do cliente para incorporar o contexto nas solicitações de saída e Extract no lado do servidor para lê-lo nas solicitações de entrada.

Injetar contexto no lado do cliente:
// start a new span representing a client request
oneWaySend = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
--snip--
// Add the trace context to the request, so it can be propagated in-band
tracing.propagation().injector(Request::addHeader)
.inject(oneWaySend.context(), request);
// fire off the request asynchronously, totally dropping any response
request.execute();
// start the client side and flush instead of finish
oneWaySend.start().flush();
Extrair contexto no lado do servidor:
// pull the context out of the incoming request
extractor = tracing.propagation().extractor(Request::getHeader);
// convert that context to a span which you can name and add tags to
oneWayReceive = nextSpan(tracer, extractor.extract(request))
.name("process-request")
.kind(SERVER)
... add tags etc.
// start the server side and flush instead of finish
oneWayReceive.start().flush();
// you should not modify this span anymore as it is complete. However,
// you can create children to represent follow-up work.
next = tracer.newSpan(oneWayReceive.context()).name("step2").start();
Verifique dados de rastreamento
Após concluir a instrumentação, execute a aplicação e envie algumas solicitações. Faça login no console do Tracing Analysis e verifique se os dados de rastreamento aparecem no painel da região correspondente.
Solução de problemas
Nenhum dado de rastreamento aparece após executar o programa de demonstração
Insira um breakpoint para depurar o método parseResponse em zipkin2.reporter.okhttp3.HttpCall e visualize o valor de retorno da solicitação de relato de dados. Se um erro 403 for retornado, a configuração do nome de usuário está inválida. Verifique a configuração do endpoint.