SpringBoot Microservices tracing with Zipkin and Sleuth
In this article, we are going to understand the microservices distributed tracing using Zipkin and Spring cloud sleuth framework.
Microservices are great architecture, though its comes with its own challenges. Complex microservices architecture have downstream and upstream dependencies with other microservices and everything is interconnected. Most of the time individual team just focus on their own services, so in microservices distributed environment it’s very difficult to find any latency or trace the actual issues at runtime.
1. Distributed Tracing
As the complexity of microservices architecture increases, uniform observability across the services and server instances become critical. Each service requests passes through multiple services layer, identifying latency or any run-time issues becomes increasingly difficult using traditional debugging techniques. Distributed tracing provides a holistic view of requests transiting through multiple services, allowing for immediate identification of issues.
1.1 Distributed Tracing Vocabulary
- Span – A span is an individual operation.
- Trace – A Trace is an end-to-end latency graph, composed of spans.
- Tracers – Tracers records spans and passes context required to connect them into a trace.
2. Zipkin
Zipkin is an open source distributed system that provides mechanisms for sending, receiving, storing, and visualizing traces details. This helps team to correlate activities between server instances and get a much deeper understanding of exactly what is going on in our services. Zipkin provide the UI interface to analyze the traces and call graph details between services.
2.1 Zipkin Installation
There are three different ways zipkin server can be installed.
- Java – We can execute the below
wget
command to download the latest zipkin server. In case we don’t havewget
installed, simply we can copy the below url and paste into our browser to download the latest zipkin server.
wget -O zipkin.jar 'https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec'
- Zipkin source – We can download the zipkin source code from below github url and run the zipkin application in your local machine: https://github.com/openzipkin/zipkin
- Docker – We can download the docker-zipkin container from https://github.com/openzipkin/docker-zipkin
For this sample application I have installed the Zipkin server using the Java method.
2.2 Zipkin UI
Zipkin UI provides following features to analyze the distributed tracing details across services:
- Search traces by service name, span name etc
- Trace dependency graph showing trace requests flow across services
- Provides the details of total trace time for each individual span
By analyzing the details provided by Zipkin UI, it becomes easier to find the latency or any particular services issues across the interconnected microservices architecture.
3. Spring Cloud Sleuth
Spring cloud sleuth
add traces and span ids to the Slf4j MDC
(Mapped Diagnostic context), to extract logs from a given trace or span. Sleuth
provide abstraction over common distributed tracing data models like traces, spans, annotations, key-value annotations. Sleuth instruments common ingress and egress points from Spring
applications (servlet filter, rest template, scheduled actions, message channels, zuul filters, feign client
).
3.1 Sleuth and Zipkin configuration at SpringBoot
Add following dependencies to the Springboot pom.xml to add the zipkin and spring cloud sleuth into the SpringBoot application.
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
4. Sample Application
For this article I have created a sample application which consist of three different microservices called UserGreetingService
, UserNameService
, UserAddressService
.
UserGreetingService
interns makes a call to UserNameService
and UserAddressService
services to constructs the complete greeting message for a user along with name and address details.
UserGreetingService.java
@SpringBootApplication @RestController @CrossOrigin public class UserGreetingService { @RequestMapping("/api/user/greet") public String greet() { String greetingMsg = "Hello"; String userName = restTemplate().getForObject("http://localhost:3001/api/user/name", String.class); String userAddress = restTemplate().getForObject("http://localhost:3002/api/user/address", String.class); return greetingMsg + " " + userName + "!\n\n" + userAddress; } @Bean RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(UserGreetingService.class, "--spring.application.name=user-greeting-service", "--server.port=3000" ); } }
To introduce the services latency, I have added Thread.sleep(1000)
and Thread.sleep(2000)
intentionally to UserNameService
and UserAddressService
services.
You can download the sample code from the github link – https://github.com/VishSinha/springbootzipkindemo
4.1 Start Zipkin Server
To start zipkin server in our local env, go to the directory where we have downloaded the zipkin server and open the command prompt or terminal and execute the following command:
java -jar zipkin-server-2.5.0-exec.jar
Once we start the zipkin server, Zipkin UI can be browsed using the url – http://localhost:9411/zipkin/
4.2 Run the Sample
Once you download the sample code from the github, start all the three microservices using your favorite IDE like eclipse, Intellij or using the command prompt.
Once all the three springboot microservices have been started, hit the UserGreetingService
endpoint url http://localhost:3000/api/user/greet using browser or postman.
Overall you will notice greeting service took more than 3 secs to render the response. Now, let’s open the Zipkin UI to analyze what’s happening behind the scene and why overall response time is more than 3 secs.
Open a browser window and render the Zipkin UI using the default url – http://localhost:9411/zipkin. This will render zipkin default search page.
Let’s select the user-greeting-service from the service name and click on the Find Traces button.
You will see there are total 3 spans of the greeting services along with total response time.
Click on the “3 spans” link, this will render details of each services response time and other details as below.
Further by clicking on each services span, we can get the details of trace ids, span ids, parent trace ids, server instance info and other tracing details for each services request. This can easily help us to troubleshoot any faulty microservices or latency issues.
Once you open the Dependencies section of Zipkin UI, this will render the services dependency graph across the services as below:
5. Conclusion
Overall zipkin is very easy to integrate cloud based microservices application and this provide lot of insights and information across services to analyze the services overall health. Using Zipkin, we can easily identify any faulty services and corrective action can be taken.
It’s enough to pass only
starter-zipkin
dependency. You don’t need to passstarter-sleuth
too. Also, the funny thing is that the span you’re showing has the tags not in order. Maybe you’ve just caught a bug ;) Which version of Sleuth have you been using?Hi Marcin, thanks for your comment here. Good that with this article we found a minor span tags order issue :-). I am using SpringBoot version – 1.5.10.RELEASE and spring-cloud version – Edgware.SR2 for this article sample code.
How zipkinn server is integrated with the springboot application. How zipkin server will find out springboot application
I am also facing same issue zipkin server is not getting integrated with spring boot application bedefault. I can see log with trace and span ids in microservices but nothing in zipkin server
Hi,
Thanks for the tutorial. I followed it line by line but Zipkin is not getting anything from the application. There seems to be absolutely no connection. Any thoughts on this?