美文网首页
Jaeger服务端埋点分析

Jaeger服务端埋点分析

作者: huiwq1990 | 来源:发表于2019-10-24 13:34 被阅读0次

    1 类介绍

    1.1 TracingFilter介绍

    配置

    配置类io.opentracing.contrib.spring.web.starter.ServerTracingAutoConfiguration#tracingFilter引入Bean。
    TraceFilter是普通的servlet filter,filter的引入有三种(我了解的)方式:
    1)在web.xml里配置引入
    2)在Filter类上面增加@WebFilter

    1. 通过bean注入
      特点是:前两种适合项目通过war包部署,最后适合springboot项目。

    功能

    从http协议头中获取span信息,如果SERVER_SPAN_CONTEXT为空,则根据头信息创建新的Span。

    1.2 Interceptor

    通过类io.opentracing.contrib.spring.web.starter.ServerTracingAutoConfiguration#tracingHandlerInterceptor引入。
    它主要处理业务日志,拦截controller等(??)

    2 源码解析

    Tracer创建

    Tracer主要是设置上报的服务器地址,采样率,项目名称等。
    io.opentracing.contrib.java.spring.jaeger.starter.JaegerAutoConfiguration#tracer调用io.jaegertracing.internal.JaegerTracer.Builder新建Tracer对象。

        private ScopeManager scopeManager = new ThreadLocalScopeManager();
        private BaggageRestrictionManager baggageRestrictionManager = new DefaultBaggageRestrictionManager();
        private boolean expandExceptionLogs;
        private final JaegerObjectFactory objectFactory;
        private boolean useTraceId128Bit;
        private boolean manualShutdown;
    
        public Builder(String serviceName) {
          this(serviceName, new JaegerObjectFactory());
        }
    

    这里有个点需要注意:ScopeManager的具体实现类是ThreadLocalScopeManager,稍后会解释。

    注册Tracer对象

    io.opentracing.contrib.spring.tracer.configuration.TracerRegisterAutoConfiguration#registerToGlobalTracer

    可以通过GlobalTracer.get()方法获取对象。

    Scope分析(非常重要)

    Scope是站在CPU角度激活或者失效Span。ScopeManager管理Scope。
    一个Scope里可以有多个span,但是只有一个激活的span。

        ThreadLocalScope(ThreadLocalScopeManager scopeManager, Span wrapped, boolean finishOnClose) {
            this.scopeManager = scopeManager;
            //绑定的span
            this.wrapped = wrapped;
            this.finishOnClose = finishOnClose;
            //暂存之前激活的span
            this.toRestore = scopeManager.tlsScope.get();
            // 设置当前线程绑定的scope
            scopeManager.tlsScope.set(this);
        }
    
        @Override
        public void close() {
            if (scopeManager.tlsScope.get() != this) {
                // This shouldn't happen if users call methods in the expected order. Bail out.
                return;
            }
    
            if (finishOnClose) {
                wrapped.finish();
            }
    // 恢复之前的指向
            scopeManager.tlsScope.set(toRestore);
        }
    

    在操作当span操作完成(span.finish)时,需要调用scope.close方法,触发关联新的激活span,否则调用链条会出错。

    Span创建

                final Span span = tracer.buildSpan(httpRequest.getMethod())
                        .asChildOf(extractedContext)
                        .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
                        .start();
    
                httpRequest.setAttribute(SERVER_SPAN_CONTEXT, span.context());
    
                for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {
                    spanDecorator.onRequest(httpRequest, span);
                }
    
                try (Scope scope = tracer.activateSpan(span)) {
                    chain.doFilter(servletRequest, servletResponse);
                    if (!httpRequest.isAsyncStarted()) {
                        for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {
                            spanDecorator.onResponse(httpRequest, httpResponse, span);
                        }
                    }
                // catch all exceptions (e.g. RuntimeException, ServletException...)
                } catch (Throwable ex) {
    

    span创建就是生成jaegerspan,并设置parent为从http头获取的span信息。

    激活span

    tracer.activateSpan是激活span,会触发创建一个ThreadLocalScope。
    结果是可以通过tracer.scopeManager.activeSpan();获取span信息。

    Span关闭

    span.finish会触发span上报。

      private void finishWithDuration(long durationMicros) {
        synchronized (this) {
          if (finished) {
            log.warn("Span has already been finished; will not be reported again.");
            return;
          }
          finished = true;
    
          this.durationMicroseconds = durationMicros;
        }
        if (context.isSampled()) {
          tracer.reportSpan(this);
        }
      }
    

    相关文章

      网友评论

          本文标题:Jaeger服务端埋点分析

          本文链接:https://www.haomeiwen.com/subject/ewirvctx.html