Jaeger架构

Jaeger组成

Jaeger Client - 为不同语言实现了符合 OpenTracing 标准的 SDK。应用程序通过 API 写入数据,client library 把 trace 信息按照应用程序指定的采样策略传递给 jaeger-agent。

Agent - 它是一个监听在 UDP 端口上接收 span 数据的网络守护进程,它会将数据批量发送给 collector。它被设计成一个基础组件,部署到所有的宿主机上。Agent 将 client library 和 collector 解耦,为 client library 屏蔽了路由和发现 collector 的细节。

Collector - 接收 jaeger-agent 发送来的数据,然后将数据写入后端存储。Collector 被设计成无状态的组件,因此您可以同时运行任意数量的 jaeger-collector。

Data Store - 后端存储被设计成一个可插拔的组件,支持将数据写入 cassandra、elastic search。

Query - 接收查询请求,然后从后端存储系统中检索 trace 并通过 UI 进行展示。Query 是无状态的,您可以启动多个实例,把它们部署在 nginx 这样的负载均衡器后面。

java ee sdk 的安装教程 java-sdk_opentracing

OpenTracing

OpenTracing 中的 Trace(调用链)通过归属于此调用链的 Span 来隐性的定义。

特别说明,一条 Trace(调用链)可以被认为是一个由多个 Span 组成的有向无环图(DAG图),Span 与 Span 的关系被命名为 References。

java ee sdk 的安装教程 java-sdk_java_02

OpenTracing的优势

  • OpenTracing 已进入 CNCF,正在为全球的分布式追踪,提供统一的概念和数据标准。
  • OpenTracing 通过提供平台无关、厂商无关的 API,使得开发人员能够方便的添加(或更换)追踪系统的实现。

例如:下面的示例 Trace 就是由8个 Span 组成:

java ee sdk 的安装教程 java-sdk_jaeger_03

有些时候,使用下面这种,基于时间轴的时序图可以更好的展现 Trace(调用链):

java ee sdk 的安装教程 java-sdk_opentracing_04


每个 Span 包含以下的状态:(译者注:由于这些状态会反映在 OpenTracing API 中,所以会保留部分英文说明)

  • An operation name,操作名称
  • A start timestamp,起始时间
  • A finish timestamp,结束时间
  • Span Tag,一组键值对构成的 Span 标签集合。键值对中,键必须为 string,值可以是字符串,布尔,或者数字 类型。
  • Span Log,一组 span 的日志集合。

    每次 log 操作包含一个键值对,以及一个时间戳。

键值对中,键必须为 string,值可以是任意类型。
但是需要注意,不是所有的支持 OpenTracing 的 Tracer,都需要支持所有的值类型。

  • SpanContext,Span 上下文对象 (下面会详细说明)
  • References(Span间关系),相关的零个或者多个 Span(Span 间通过 SpanContext 建立这种关系)

每一个 SpanContext 包含以下状态:

  • 任何一个 OpenTracing 的实现,都需要将当前调用链的状态(例如:trace 和 span 的 id),依赖一个独特的 Span 去跨进程边界传输
  • Baggage Items,Trace 的随行数据,是一个键值对集合,它存在于 trace 中,也需要跨进程边界传输。

一个完整的opentracing调用链包含 Trace + span + 无限极分类

  • Trace:追踪对象,一个Trace代表了一个服务或者流程在系统中的执行过程,如:test.com,redis,mysql等执行过程。一个Trace由多个span组成
  • span:记录Trace在执行过程中的信息,如:查询的sql,请求的HTTP地址,RPC调用,开始、结束、间隔时间等。
  • 无限极分类:服务与服务之间使用无限极分类的方式,通过HTTP头部或者请求地址传输到最低层,从而把整个调用链串起来。

当然opentracing只是一套标准,要玩转还需要配合Jaeger。

Jaeger Docker部署

docker run -d -p 5775:5775/udp -p 16686:16686 jaegertracing/all-in-one:latest

java-sdk使用

导入Pom文件

<dependency>
            <groupId>io.jaegertracing</groupId>
            <artifactId>jaeger-core</artifactId>
            <version>0.27.0</version>
        </dependency>
        <dependency>
            <groupId>io.opentracing</groupId>
            <artifactId>opentracing-api</artifactId>
            <version>0.31.0</version>
        </dependency>

Opentraceing.java

import java.net.SocketException;
import io.jaegertracing.Configuration;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;

public class Opentraceing {

    public static void main(String[] args) throws SocketException, InterruptedException {

        Configuration config = new Configuration("Hello Jaeger2");

        Configuration.SenderConfiguration sender = new Configuration.SenderConfiguration();
        sender.withAgentHost("10.100.7.47");
        sender.withAgentPort(5775);
        config.withReporter(new Configuration.ReporterConfiguration().withSender(sender).withFlushInterval(100).withLogSpans(false));

        config.withSampler(new Configuration.SamplerConfiguration().withType("const").withParam(1));

        io.opentracing.Tracer tracer = config.getTracer();
        System.out.println(tracer.toString());
        GlobalTracer.register(tracer);


        Tracer.SpanBuilder spanBuilder = GlobalTracer.get().buildSpan("hello");
        Span parent = spanBuilder.start();
        parent.log(100, "haha");


        Tracer.SpanBuilder spanBuilder2 = GlobalTracer.get().buildSpan("world").asChildOf(parent);
        Span child = spanBuilder2.start();
        child.log("haha2");
        child.finish();

        parent.finish();

        Thread.sleep(30000);
    }
}

结果输出:

java ee sdk 的安装教程 java-sdk_opentracing_05

总结

Jaeger也存在一些问题,在实际公司应用中,需要结合修改和新增部分功能,如:
1.实时计算,实时告警
2.Ui展示功能需要定制,目前只有链路展示
3.Java和其他语言互通需要定制