耐克公司的WingTips分布式跟踪系统

16-09-10 banq
         

分布式跟踪是一种通过分布式网络跟踪请求的系统,这样能够在复杂的微服务系统中创建一种透明的调用路径,一条请求可能会经过成百上千个微服务调用环节,如同树形结构一样分散开来,如果没有分布式跟踪,很难确定某个微服务是否是整个路径上的性能瓶颈。

分布式跟踪提供了近乎实时的监控和历史分析,它提供必要工具收集和解释跟踪,能够让你方便看到应用花费的时间。

一个分布式跟踪系统由以下部分组成:

1.每个分布式跟踪包含一个TraceID,代表整个跨多个服务器或微服务的请求,这些TraceID会是唯一64位整数long型。

2.在分布式跟踪系统中每个单元被定义为Span,Span通常分为overall-request-time和downstream-call-time两种,前者是服务器/微服务的整个请求花费时间,后者是下游花费时间,Span由SpanID标识,也是一种64位long型。

3.Span能够有父Span,这样建立跨多个服务器/服务的基于请求行为的树形图,ParentSpanID是Span的SpanID的父节点。

4.所有Span包含有关整个跟踪的TreacID。

5.Span包含SpanName,这是供人工读取的标识,比如GET_/some/endpoint是REST请求的整个Span,或者downstream-POST_https://otherservice.com/other/endpoint是执行另外一个服务的下游调用Span。

6.Span包含计时信息,一个开始时间戳和花费时间值。

Wingtips是一个基于Java 7的分布式跟踪解决方案,有几个模块:

wingtips-core - 提供分布式跟踪功能的核心库

wingtips-servlet-api - 基于Sevlet应用的插件,能够在一个Servlet过滤器中集成分布式跟踪。

wingtips-zipkin - 一个易于集成Zipkin的插件。

下面是每个请求一个线程框架场景下的伪代码演示:

import com.nike.wingtips.Span;
import com.nike.wingtips.Tracer;

// ======As early in the request cycle as possible======
try {
    // 检查请求比如请求头部决定父span是否存在
    Span parentSpan = extractParentSpanFromRequest(request);

    // 开始整个请求span (对于当前线程会成为"current span" ,除非或直至子Span sub-span被创建)
    if (parentSpan == null)
        Tracer.getInstance().startRequestWithRootSpan("newRequestSpanName");
    else
        Tracer.getInstance().startRequestWithChildSpan(parentSpan, "newRequestSpanName");

    // 推荐在响应头部包含整个请求的跟踪ID
    addTraceIdToResponseHeaders(response, Tracer.getInstance().getCurrentSpan());

    // 执行正常的请求逻辑
    doRequestLogic();   
}
finally {
    // ======As late in the request/response cycle as possible======
    Tracer.getInstance().completeRequestSpan(); // Completes the overall request span and logs it to SLF4J
}
<p>

如果基于非堵塞异步的 reactive场景,通过下面几个方法进行跟踪:

Tracer.registerWithThread(Deque)

Tracer.unregisterFromThread()

Tracer.getCurrentSpanStackCopy()

Nike-Inc/wingtips: WingTips is a distributed traci

         

3