Tracing REST Services with Zipkin

Whether you deploy to the cloud or on-prem, one of the biggest challenges of a microservice or distributed architecture is monitoring.

Zipkin is a distributed tracing system that can help to solve some of these problems. Specifically, it helps gather data needed to troubleshoot latency issues.

In this article, we look at spring clouds support for Zipkin by setting up some spring boot REST services.

The example code is written in kotlin but can easily be ported over to java.

Source code for this example can be found on github:
codenerve-com/tutorials
Example code for blog posts written over @ codenerve.com - codenerve-com/tutorials

Prerequisites

You'll need some things to follow along with the example:

  • Java
  • Maven
  • Docker (including docker-compose)
  • The source code cloned and imported into your IDE

Setting the scene

To demonstrate Zipkin's tracing abilities, we are going to bring up some fictitious services that our service can make requests to.


Our service will return the tax of an employee based on their name:

$ curl http://localhost:8080/tax\?name\=michael
$ 10000.0

To do this, it needs some help for other services:

  • An employee service which will return employee information by name
  • A payroll service which will return the employees tax code by employee id.

Finally, our service will calculate and return the tax to be paid.

Additionally, we will bring up a Zipkin server which our service will push trace data to.


The employee and payroll service will be mocked out using mockserver. We will not be covering mockserver in this post.

There are two json files under the dist directory that tell the mock services how to respond to requests, including some delays which will slow down there response times.


Compose

To manage all this, we will be using a docker compose yml file:

version: '2.0'
services:
  zipkin:
    container_name: zipkin
    image: openzipkin/zipkin
    ports:
      - 8081:9411

  employee-service:
    container_name: employee-service
    image: mockserver/mockserver
    ports:
      - 8082:1080
    environment:
      MOCKSERVER_INITIALIZATION_JSON_PATH: /config/initializerJson.json
    volumes:
    - ./dist/employee-service:/config

  payroll-service:
    container_name: payroll-service
    image: mockserver/mockserver
    ports:
      - 8083:1080
    environment:
      MOCKSERVER_INITIALIZATION_JSON_PATH: /config/initializerJson.json
    volumes:
      - ./dist/payroll-service:/config
docker-compose.yml

Let's start everything up now by running:

docker-compose -f docker-compose.yml up

N.B you can optionally background the process by adding -d to the end of this command

Creating a Basic Rest Service

Creating the service is very simple, and if you're happy with spring boots defaults then this only involves adding a jar to your maven pom!

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.2.0.RC1</version>
</dependency>
pom.xml

Default properties such as zipkin urls can be overidden under src/main/resources/application.properties

A full list of properties are listed in the spring cloud documentation

Hitting the endpoint

Start the service in your IDE and navigate to it in your browser:

Service http://localhost:8080/tax?name=michael"
Zipkin UI http://localhost:8081
Mock Employee Service http://localhost:8082/employeeService
Mock Payroll Service http://localhost:8083/payrollService

Now navigate to the Zipkin UI. Click on Find Traces and you will see the trace you created by opening the service url.

zipkin ui

Click on a span to expand it:

zipkin ui

Apache Benchmark

Additionally you could use a tool like apache benchmark to put the service under some load. This will create more traces that can be viewed in the zipkin ui:

ab -n 500 -c 20 "http://localhost:8080/tax?name=michael"

Conclusion

We've seen just how easy it is to add tracing to your spring cloud application.

For more info, see the spring cloud docs or the openzipkin examples on github.

Michael Whyte

Michael Whyte