Backend Development 7 min read

How to Set Up Distributed Tracing with Spring Cloud, Nacos, and Zipkin

This guide walks through configuring Spring Cloud microservices with Nacos service discovery, adding Zipkin for distributed tracing, and persisting trace data to Elasticsearch, including all necessary Maven dependencies, YAML settings, controller code, and verification steps.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Set Up Distributed Tracing with Spring Cloud, Nacos, and Zipkin

Environment

spring cloud Hoxton.SR11 + spring cloud alibaba 2.2.5.RELEASE + zipkin 2.23.2 + nacos 1.4.1 + Elasticsearch 7.8.0 + Kibana 7.8.0

service‑producer module

<code>&lt;dependencies&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-alibaba-nacos-discovery&lt;/artifactId&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-zipkin&lt;/artifactId&gt;
  &lt;/dependency&gt;
&lt;/dependencies&gt;</code>
<code>server:
  port: 9100
---
spring:
  cloud:
    nacos:
      username: dev
      password: 123456
      discovery:
        enabled: true
        serverAddr: localhost:8848
        namespace: 7205e69c-ac51-4ac1-bbe9-87c28689b88b
---
spring:
  application:
    name: service-producer
---
# Zipkin service address
spring:
  zipkin:
    base-url: http://127.0.0.1:9411
  sleuth:
    sampler:
      probability: 1.0</code>

API

<code>@RestController
@RequestMapping("discovery")
public class DiscoveryController {

  @NacosInjected
  private NamingService namingService;
  @Resource
  private DiscoveryClient discoverClient;

  @GetMapping(value = "/get")
  public Object get(@RequestParam String serviceName) throws Exception {
    Map<String, Object> res = new HashMap<>();
    res.put("services", discoverClient.getServices());
    res.put("instances", discoverClient.getInstances(serviceName));
    res.put("port", 9000);
    return res;
  }
}</code>

service‑consumer module

Dependencies and configuration are the same as service‑producer.

Configure RestTemplate

<code>@LoadBalanced
@Bean
public RestTemplate restTemplate() {
  return new RestTemplate();
}</code>

API

<code>@RestController
@RequestMapping("/consumer")
public class ConsumerController {

  @Resource
  private RestTemplate restTemplate;

  @GetMapping("/get")
  public Object invoke(String serviceName) {
    return restTemplate.getForObject(
      "http://service-producer/discovery/get?serviceName=" + serviceName,
      Object.class);
  }
}</code>

service‑gateway (Zuul) module

<code>&lt;dependencies&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-netflix-zuul&lt;/artifactId&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-alibaba-nacos-discovery&lt;/artifactId&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-alibaba-nacos-config&lt;/artifactId&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-zipkin&lt;/artifactId&gt;
  &lt;/dependency&gt;
&lt;/dependencies&gt;</code>
<code>server:
  port: 10001
---
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000
  OkToRetryOnAllOperations: false
  MaxAutoRetries: 1
  MaxAutoRetriesNextServer: 1
---
zuul:
  ignoredServices: '*'
  prefix: /api
  stripPrefix: true
  routes:
    service-producer:
      path: /api-a/**
      serviceId: service-consumer
      customSensitiveHeaders: true
      sensitiveHeaders:
  addHostHeader: true
  host:
    connectTimeoutMillis: 20000
    socketTimeoutMillis: 20000
  ignoreLocalService: true
---
spring:
  zipkin:
    base-url: http://127.0.0.1:9411
  sleuth:
    sampler:
      probability: 1.0
---
spring:
  application:
    name: service-gateway
---
spring:
  cloud:
    nacos:
      username: dev
      password: 123456
      discovery:
        enabled: true
        serverAddr: localhost:8848
        namespace: 7205e69c-ac51-4ac1-bbe9-87c28689b88b</code>

Zipkin service

For Spring Boot 2.x and later you can run Zipkin without building your own server; download and start it as follows:

<code>java -jar zipkin.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=localhost:9200</code>

After restarting the three services, access the API endpoints and view the trace data in Zipkin UI and Kibana.

Persisting trace logs

By default Zipkin stores traces in memory; to persist them you can use memory, MySQL, Cassandra, or Elasticsearch. This guide uses Elasticsearch for its simplicity.

Run Zipkin with Elasticsearch storage:

<code>java -jar zipkin.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=localhost:9200</code>

After restarting the services and invoking the APIs, Kibana will automatically create an index and display the trace logs.

At this point, distributed tracing for the microservice system is fully configured.

microservicesElasticsearchDistributed TracingSpring CloudZipkin
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.