[JAVA] MicroProfile OpenTracing with Helidon

Introduction

UL Systems Advent Calendar 2019-Day 18

Today, [Eclipse MicroProfile OpenTracing] with reference to Tracing MP Guide of Helidon ](Https://github.com/eclipse/microprofile-opentracing) and Jaeger I would like to try out distributed tracing visualization. (The Tracing MP Guide uses Zipkin, but this time I would like to use Jaeger because of the cute logo.)

Recently, it has become more common to configure the entire system with a microservice architecture. At that time, if a failure or delay occurs in the process that spans multiple services with the method trace used in the conventional monolithic system, it is difficult to determine where it occurs, so the distribution is traced throughout. A mechanism called tracing is required.

jaeger.png

What is Helidon

An open source-based framework for developing lightweight microservices that can be used to create microservices for Java, announced by Oracle in September 2018.

Features of Helidon

This time we will use Helidon MP, which supports MaicroProfile.

What is Eclipse MicroProfile?

Eclipse MicroProfile is a specification of the Enterprise Java API for microservices. It now includes APIs such as JAX-RS, JSON-P, and CDI, as well as APIs such as configuration, metrics, and fault tolerance. The Helidon MP used this time supports Eclipse MicroProfile 3.2.

What is OpenTracing?

OpenTracing consists of API specifications, frameworks and libraries that implement them, and project documentation. OpenTracing allows developers to add tracing functionality to their application code using APIs that are not locked to a particular product or vendor.

What is Jaeger

An open source OpenTracing compatible distributed tracing system inspired by Dapper and OpenZipkin and released by Uber Technologies. This time, the OpenTracing API part in the figure below is MicroProfile OpenTracing, and the jaeger-client part is the Client for Jaeger provided by Helidon.

20181125234256.png

Jaeger setup

First of all, I would like to set up the parts other than Client. Regarding the setup, the All-in-one Docker image is published, so use it. (Start by specifying only the minimum required ports)

$ docker run -d --name jaeger \
   -p 5778:5778 \
   -p 16686:16686 \
   -p 14268:14268 \
   jaegertracing/all-in-one:1.15

Description of each port

Helidon's jaeger-client seems to use HTTP 5778 by default. (This can be changed by setting)

キャプチャ004.JPG

Creating a Main service

Then create the main service project using the Helidon MP Maven archetype quickstart.

$ mvn archetype:generate -DinteractiveMode=false \
    -DarchetypeGroupId=io.helidon.archetypes \
    -DarchetypeArtifactId=helidon-quickstart-mp \
    -DarchetypeVersion=1.4.0 \
    -DgroupId=io.helidon.main_service \
    -DartifactId=main_service \
    -Dpackage=io.helidon.main_service

Added Jaeger Client

Add the following dependency to pom.xml and add Jaeger Client.

pom.xml(add to)


<dependency>
    <groupId>io.helidon.tracing</groupId>
    <artifactId>helidon-tracing-jaeger</artifactId>
</dependency>

Add tracing service name

Specify the service name to be linked to the tracing data sent from Helidon to Jaeger in META-INF / microprofile-config.properties.

microprofile-config.properties


tracing.service=helidon-main-service

Run and see the Main service

Now, I would like to see the results created so far. The project created by quickstart is created so that the server can be started by executing the Main method of the ʻio.helidon.main_service.Main` class.

If you access http: // localhost: 8080 / greet after starting the server, the service created by quickstart will be executed and you should see{"message": "Hello World!"}.

$ curl http://localhost:8080/greet
{"message":"Hello World!"}

If you look at the tracing data from the jaeger UI (http: // localhost: 16686 / search) after accessing it several times, you should see the following tracing data. キャプチャ003.JPG

Click each trace further to display the trace details page listing the spans. You can clearly see the root span and the relationships between all the spans in the trace, as well as timing information. キャプチャ005.JPG

You can also see the details of the span by clicking each span row. キャプチャ006.JPG

Tracing at the class or method level

In addition, tracing at the class or method level is possible by adding the @Traced annotation provided by MicroProfile OpenTracing.

GreetingProvider.java


@Traced
@ApplicationScoped
public class GreetingProvider {
...
}

キャプチャ007.JPG

Tracing across services

Next, I would like to do tracing across services.

Creating a Second service

Create it using the Helidon MP Maven archetype quickstart as well as the Main service and add the Jaeger Client.

$ mvn archetype:generate -DinteractiveMode=false \
    -DarchetypeGroupId=io.helidon.archetypes \
    -DarchetypeArtifactId=helidon-quickstart-mp \
    -DarchetypeVersion=1.4.0 \
    -DgroupId=io.helidon.second_service \
    -DartifactId=second_service \
    -Dpackage=io.helidon.second_service

pom.xml(add to)


<dependency>
    <groupId>io.helidon.tracing</groupId>
    <artifactId>helidon-tracing-jaeger</artifactId>
</dependency>

setting change

microprofile-config.properties(After change)


# Application properties. This is the default greeting
app.greeting=Hello From Second Service

# Microprofile server properties
server.port=8081

Operation check

If you run the Second service and check the operation, the following results will be obtained.

$ curl http://localhost:8081/greet
{"message":"Hello From Second Service World!"}

Calling the Second service from the Main service

Change to call the Second service from the Main service you created first.

First, you need to create a Rest Client in the Main service to call the Second service. Unlike the Tracing MP Guide, I'd like to create it using the Micro Profile Rest Client here.

SecondServiceClient.java


package io.helidon.main_service;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import javax.json.JsonObject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@RegisterRestClient(baseUri="http://localhost:8081")
public interface SecondServiceClient {
    @Path("/greet")
    @GET
    JsonObject getDefaultMessage();
}

Then, use the created Client to call the Second service from the Main service. Inject the created SecondServiceClient into the calling class and call the Second service using SecondServiceClient to the method that originally returned the response.

GreetResource.java


@Path("/greet")
@RequestScoped
public class GreetResource {
    @Inject
    @RestClient
    SecondServiceClient secondServiceClient;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public JsonObject getDefaultMessage() {
        // return createResponse("World");
        return secondServiceClient.getDefaultMessage();
    }

Operation check

Run the Main service on port 8080 and make sure the Second service is called.

$ curl http://localhost:8080/greet
{"message":"Hello From Second Service World!"}

Check distributed tracing data

This process is configured so that the request from the console turns the Main service and calls the Second service. キャプチャ009.JPG

If you look at the tracing data of this request in Jaeger UI, it will take that much processing time as a whole, and you can check the processing flow. キャプチャ008.JPG

Summary

This time I tried distributed tracing using Eclipse MicroProfile Open Tracing. If distributed tracing can be visualized when a distributed system is adopted, it may be easier to understand even if a system failure or delay occurs.

In addition to OpenTracing, Eclipse MicroProfile has specifications such as Eclipse MicroProfile Metrics and Eclipse MicroProfile Fault Tolerance, and Helidon also supports them. I think it can be considered as an option other than Spring Framework, such as migration from applications that are currently using Java EE.

Recommended Posts

MicroProfile OpenTracing with Helidon
Get in touch with Eclipse MicroProfile Health