• Jaeger-2.客户端使用 (Java版本)


        主要用到了opentracing相关的jar包,而且用到了jaeger的java客户端实现。

    一段简单的代码

      首先创建一个简单的loveyou类,里面有一个简单的方法hello。本部分之与OpenTracing有关,与Jaeger关系并不是很大。在hello方法体的前后,加入几行简单的代码,主要是根据OpenTracing规范定义的api进行一些调用信息等内容的添加。

    public class LoveYou {

      Tracer tracer;
      public LoveYou() {

       tracer = JaegerTracerHelper.initTracer("loveYouService");

      }

      public void hello(String name) {

        Span span = tracer.buildSpan("hello").start();

        span.setTag("name", name);

        System.out.println("Hello " + name);

        span.log("Love service say hello to " + name);

        span.finish();

      }

      public static void main(String[] args) {

        new LoveYou().hello("小姐姐味道");

      }

    }

      代码主要加入了以下几个重要的信息。

      1、构建了一个新的span,每个span有三个id:rootid、parentid、id。它们构成了树状调用链的每个具体节点。

      2、给新加的span添加了一个tag信息,用来进行一些自定义标识。tag有一些标准的清单,但也可以自定义。

      3、给新加的span添加了log。log信息会附着在信息span上,一块被收集起来,仅定义一些比较重要的信息,包括异常栈等。一些不重要的信息不建议使用log,它会占用大量存储空间。


          执行代码后,可以在jaeger的ui端看到这次的调用信息。如下: 

    构建jaeger实现

    我们的OpenTracing数据是如何构建,并发送到Jaeger的server端呢?就是通过下面的代码完成的。

     public class JaegerTracerHelper {

      public static JaegerTracer initTracer(String service) {
        
        final String endPoint = "http://10.30.94.8:14268/api/traces";

        final CompositeReporter compositeReporter = new CompositeReporter(new RemoteReporter.Builder().withSender(new HttpSender.Builder(endPoint).build()).build(),new LoggingReporter());

        final Metrics metrics = new Metrics(new NoopMetricsFactory());

        JaegerTracer.Builder builder = new JaegerTracer.Builder(service).withReporter(compositeReporter).withMetrics(metrics).withExpandExceptionLogs().withSampler(new ConstSampler(true));

        return builder.build();

         }

    }

    实现一个2层深度的链

      以上代码,仅产生了一个span,也就是一个方法调用。接下来,我们看一下如何完成一个多层的调用链条。接下来还是要修改LoveYou类。我们把调用方法hello拆解一下,拆成dispatchhello两个方法,并在hello方法里sleep一秒钟。

    期望生成两条trace信息。

    dispatch

     public void dispatch(String cmd, String content) {

      Span span = tracer.buildSpan("dispatch").start();
      tracer.activateSpan(span);

      if (cmd.equals("hello")) {

        this.hello(content);

      }

      if (null != span) {

        span.setTag("cmd", cmd);

        span.finish();

      }

    }

    hello

    public void hello(String name) {
     
      Span span = tracer.buildSpan("hello").start();

      tracer.activateSpan(span);

      System.out.println("Hello " + name);

      try {

        Thread.sleep(TimeUnit.SECONDS.toMillis(1));

      } catch (InterruptedException e) {

        e.printStackTrace();

      }

      span.setTag("name", name);

      span.log("Love service say hello to " + name);

      span.finish();

    }

      与示例一不同的是,每次生成span之后,我们还要将其激活一下 

      tracer.activateSpan(span);
      它的目的主要是让span实例在当前的ctx里面保持活跃(比如一个线程)。这样,如果新的span判断当前有活跃的span,则将它们放在同一个scope中。这样,链条就串起来了。

    以下是程序运行后的效果。 

    采样

      有时候,我们的服务QPS非常高,瞬间能够生成大量的trace信息。这些信息是非常相近的,且会给存储产生很大的压力。

      如果不需要统计一些QPS之类的信息,就可以使用sampler,仅收集部分trace。

      还记得我们使用javaapi构建的jaeger实例么?其中,有这么一行代码:

      .withSampler(new ConstSampler(true))

      这就是最简单的采样,意思是收集所有的信息。jaeger支持四种不同的采样类型。

    Constant

      这是一个布尔开关,如果sampler.param=1,则代表收集所有的trace,如果为0,则代表什么都不收集。

    Probabilistic

      基于概率进行采样,比如sampler.param=0.1,则代表有1/10的trace将被收集。

    Rate Limiting

      限流方式,使用令牌桶限流。 sampler.param=2.0 则代表每秒有2个trace被收集,超出的将被抛弃。

    Remote

      通过远程配置方式配置,这也是默认的方式。比如在Collector中配置strategies.json

     {

      "service_strategies": [

      {

        "service": "foo",

        "type": "probabilistic",

        "param": 0.8,

        "operation_strategies": [

        {

            "operation": "op1",

            "type": "probabilistic",

            "param": 0.2

        },

        {

            "operation": "op2",

            "type": "probabilistic",

            "param": 0.4

        }

       ]

      },

      {

        "service": "bar",

        "type": "ratelimiting",

        "param": 5

      }

      ],

      "default_strategy": {

      "type": "probabilistic",

      "param": 0.5

      }

    }

    End

      通过OpenTracing的Api,可以很容易的实现调用链功能。但可以看到,由于存在各种各样的客户端,主要工作量就集中在对这些客户端的兼容上。比如线程池、SpringCloud、MQ、数据库连接池等等等等。

      使用Aop可以省去一些编码和侵入,但可控制性会弱一些。

      接下来,我们给一个简单的OkHttp+SpringBoot调用,也就是分布式应用,添加trace功能。

  • 相关阅读:
    2020软件工程作业04
    2020软件工程作业02
    第一周作业
    2019春总结作业
    12周作业
    第十一周作业
    第十周阅读
    第9周编程总结
    编程总结模版
    第8周编程总结
  • 原文地址:https://www.cnblogs.com/liboware/p/12491916.html
Copyright © 2020-2023  润新知