x Java Java 8 JUnit JSON
  • XML
  • JDBC Spring Boot Microservices React Contact Us

    Spring Cloud Sleuth Zipkin example

    When using a microservices architecture, a single transaction may span multiple microservices. If you want to debug any transaction or you want to investigate an issue, you need a unique id to identify the flow of transactions. Spring Cloud Sleuth provides the solution by implementing distributed tracing solution for Spring Cloud.

    Spring Cloud Sleuth uses correlation IDs (traceid) to trace logs. A correlation ID is a unique number or string (e.g. order id, user id) that's assigned to a transaction when a transaction is initiated. As the transaction flows across multiple services, the correlation ID is propagated from one service call to another. With Spring Cloud Sleuth, you'll automatically get correlation IDs added to the log statements you put in your microservices.

    We will also configure Zipkin in these microservices so that API call statistics will be send to Zipkin server. Zipkin is a distributed tracing platform that will allow us to trace transactions across multiple service invocations. Using Zipkin we can graphically check the time consumed by each microservice API.

    Step 1) Add spring-cloud-starter-sleuth dependency to pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>   
        <version>2.1.6.RELEASE</version>
        <relativePath />
    </parent>
    
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2.1.3.RELEASE</spring-cloud.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
            <version>${spring-cloud.version}</version>
        </dependency>
    
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-sleuth-zipkin</artifactId>
    	<version>${spring-cloud.version}</version>
    </dependency>
            
    </dependencies>

    Step 2) Create first microservice

    Add SleuthApplication, SleuthRestController classes and application.yml file. SleuthRestController will expose an endpoint that will we will call from browser and it will internally call second microservice to get the results. By default Zipkin server runs at port 9411. It it is running on some other port or host, we can configure the zipkin url using spring.zipkin.baseUrl property in application.yml file.

    We will need to define how often each service should write data to Zipkin. By default only 10% data is sent to Zipkin. However for our testing purpose we can make it 100% by using spring.sleuth.sampler.percentage property which should be set between 0 & 1. It is not recommended to set it to 1 as it will put hugh load on Zipkin server.

    package com.example;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    public class SleuthApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SleuthApplication.class, args);
        }
        
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
    }       

    package com.example;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class SleuthRestController {
    
        private final Logger LOG = LoggerFactory.getLogger(this.getClass());
    
        @Autowired
        private RestTemplate restTemplate;
    
        @RequestMapping(value = "/api")
        public String hello() {
            LOG.info("Hello Sleuth");
    
            return restTemplate.getForObject("http://localhost:8082/api2", String.class);
        }
    
    }   

    spring:
      application:
        name: sleuth-demo
      zipkin:
        baseUrl: http://localhost:9411
      sleuth:
        sampler:
          probability: 1.0
         
    server:
      port: 8081  

    Step 3) Create second microservice

    Add SleuthApplication2, SleuthRestController classes and application.properties file. SleuthRestController will expose an endpoint that will be called by first microservice.

    package com.example;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SleuthApplication2 {
    
        public static void main(String[] args) {
            SpringApplication.run(SleuthApplication2.class, args);
        }
    
    }       

    package com.example;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class SleuthRestController {
        
        private final Logger LOG = LoggerFactory.getLogger(this.getClass());
    
        
        @RequestMapping(value = "/api2") 
        public String hello() {
            LOG.info("Hello Sleuth you have invoked second microservice");
            return "Hello Sleuth you have invoked second microservice";
        }
    
    }  

    spring:
      application:
        name: sleuth-demo-2
      zipkin:
        baseUrl: http://localhost:9411
      sleuth:
        sampler:
          probability: 1.0
         
    server:
      port: 8082 

    Step 4) Configure Zipkin server

    You can launch Zipkin server in 2 ways. One is by downloading executable jar from latest release and then start the server using java -jar zipkin.jar command.

    Other way is to configure using Spring Boot by adding below dependency and then starting application with @EnableZipkinServer.

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
        </dependency>
        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
        </dependency>
    </dependencies>     

    package com.example;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import zipkin.server.EnableZipkinServer;
    
    
    @EnableZipkinServer
    @SpringBootApplication
    public class ZipkinServiceApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(ZipkinServiceApplication.class, args);
    	}
    	
    } 

    Step 4) Running the microservices and Zipkin server

    Run SleuthApplication, SleuthApplication2 and ZipkinServiceApplication, launch any browser and open http://localhost:8081/api. You will see below page displayed in the broswer.

    Hello Sleuth you have invoked second microservice

    Console Output :

    Observe the logs in SleuthApplication, it prints sleuth-demo,61a0a37a9c5988af,61a0a37a9c5988af,true

    Observe the logs in SleuthApplication2, it prints sleuth-demo-2,61a0a37a9c5988af,f7d587d622ac96cc,true where f7d587d622ac96cc is the span id.


    Step 5) Check microservices stats in Zipkin UI

    As Zipkin server is running on 9411 port, launch http://localhost:9411 url in browser to check time taken by each call in microservice in Zipkin UI. You need to click on 'Find a trace' to find the transaction flows across the microservices.

    Zipkin UI

    Zipkin UI






















    If you click on '2 spans' you will see how much time is taken by each microservice. You can also search for a specific transaction by providing trace id like 61a0a37a9c5988af

    Zipkin UI

    Zipkin UI

























    References :

    Spring Cloud Sleuth

    OpenZipkin

    Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *











    Share This