耐克公司的WingTips分散式跟蹤系統

banq發表於2016-09-10
分散式跟蹤是一種透過分散式網路跟蹤請求的系統,這樣能夠在複雜的微服務系統中建立一種透明的呼叫路徑,一條請求可能會經過成百上千個微服務呼叫環節,如同樹形結構一樣分散開來,如果沒有分散式跟蹤,很難確定某個微服務是否是整個路徑上的效能瓶頸。

分散式跟蹤提供了近乎實時的監控和歷史分析,它提供必要工具收集和解釋跟蹤,能夠讓你方便看到應用花費的時間。

一個分散式跟蹤系統由以下部分組成:
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 class="indent">


如果基於非堵塞非同步的 reactive場景,透過下面幾個方法進行跟蹤:
Tracer.registerWithThread(Deque)
Tracer.unregisterFromThread()
Tracer.getCurrentSpanStackCopy()

Nike-Inc/wingtips: WingTips is a distributed traci

相關文章