skywalking的核心概念


 

 

 

 

 

 

 

 

在 SkyWalking 中,TraceSegment 是一個介於 Trace 與 Span 之間的概念,它是一條 Trace 的一段,可以包含多個 Span。在微服務架構中,一個請求基本都會涉及跨進程(以及跨線程)的操作,例如, RPC 調用、通過 MQ 異步執行、HTTP 請求遠端資源等,處理一個請求就需要涉及到多個服務的多個線程。TraceSegment 記錄了一個請求在一個線程中的執行流程(即 Trace 信息)。將該請求關聯的 TraceSegment 串聯起來,就能得到該請求對應的完整 Trace

 

1、一個Tracesegemnt記錄了一個請求在一個線程中的執行流程,一個trace由多個tracesegment構成,一個TraceSegment 是由多個 Span 構成的

下面我們先來介紹 TraceSegment 的核心字段:

traceSegmentId(ID 類型):TraceSegment 的全局唯一標識,是由前面介紹的 GlobalIdGenerator 生成的。
refs(List<TraceSegmentRef> 類型):它指向父 TraceSegment。在我們常見的 RPC 調用、HTTP 請求等跨進程調用中,一個 TraceSegment 最多只有一個父 TraceSegment,但是在一個 Consumer 批量消費 MQ 消息時,同一批內的消息可能來自不同的 Producer,這就會導致 Consumer 線程對應的 TraceSegment 有多個父 TraceSegment 了,當然,該 Consumer TraceSegment 也就屬於多個 Trace 了。
relatedGlobalTraces(DistributedTraceIds 類型):記錄當前 TraceSegment 所屬 Trace 的 Trace ID。
spans(List<AbstractTracingSpan> 類型):當前 TraceSegment 包含的所有 Span。
ignore(boolean 類型):ignore 字段表示當前 TraceSegment 是否被忽略。主要是為了忽略一些問題 TraceSegment(主要是對只包含一個 Span 的 Trace 進行采樣收集)。
isSizeLimited(boolean 類型):這是一個容錯設計,例如業務代碼出現了死循環 Bug,可能會向相應的 TraceSegment 中不斷追加 Span,為了防止對應用內存以及后端存儲造成不必要的壓力,每個 TraceSegment 中 Span 的個數是有上限的(默認值為 300),超過上限之后,就不再添加 Span了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

TraceSegment 中除了 Span 之外,還有另一個需要介紹的重要依賴 —— TraceSegmentRef,TraceSegment 通過 refs 集合記錄父 TraceSegment 的信息,它的核心字段大概可以分為 3 類:

 

 

 

 

 

 

邏輯概念:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 我們來看下span的管理,當請求通過tomcat的時候,創建一個entryspan,然后調用entryspan的start方法,會把entryspan放入到span隊列的activespanstack中,當請求經過springmvc的時候,不會在創建entryspan,只會重新調用entryspan的start方法,當在業務方法中調用接口的first方法的時候,會創建一份localspan,並且把localspan添加到activespanstack中,當firts方法調用結束的時候,localspan會出棧,當調用業務的end方法的時候,會創建一份localspan,並且把localspan添加到activespanstack中,當end方法調用結束的時候,localspan會出棧

接下來使用dubbo接口遠程調用say方法的時候,會創建一個exitspan,然后將exitspan添加到activespanstack中,當say方法調結束的時候,會將exitspan出棧,最后方法介紹,第一個entryspan出棧

 

 

 

 

 

 

 

 

 

 

 

 接下來我們總結下skywalking的核心概念的理論

skywalking的框圖如下所示

 

 1.博客參考https://www.upyun.com/opentalk/334.html

我們在一次調用里面,所經歷的一個線程,會生成一個 TraceSegment 。這里它經歷了 4 個線程,不管是否跨 JOM ,A 里面 1 個,B 里面 1 個,B 里面的 New Thread 1 個,C 里面 1 個,所以它經歷了四個線程后就會生成四 TraceSegment 對象。一次調用經過調用經歷一個線程就是產生一個TraceSegment,整個一個trace的調用鏈就是由多個TraceSegment構成的。

TraceSegment對應的就是數據庫中segment表,該表中記錄了對於的segment信息,我們來看該表的字段信息

CREATE TABLE `segment`  (
  `id` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `segment_id` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `trace_id` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `service_id` int(11) DEFAULT NULL,
  `service_instance_id` int(11) DEFAULT NULL,
  `endpoint_name` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `endpoint_id` int(11) DEFAULT NULL,
  `start_time` bigint(20) DEFAULT NULL,
  `end_time` bigint(20) DEFAULT NULL,
  `latency` int(11) DEFAULT NULL,
  `is_error` int(11) DEFAULT NULL,
  `data_binary` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci,
  `version` int(11) DEFAULT NULL,
  `time_bucket` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `SEGMENT_TRACE_ID`(`trace_id`) USING BTREE,
  INDEX `SEGMENT_ENDPOINT_ID`(`endpoint_id`) USING BTREE,
  INDEX `SEGMENT_LATENCY`(`latency`) USING BTREE,
  INDEX `SEGMENT_TIME_BUCKET`(`time_bucket`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;
  • trace_id:本次調用的唯一id,通過snowflake模式生成
  • endpoint_name:被調用的接口
  • latency:耗時
  • end_time:結束時間戳
  • endpoint_id:被調用的接口的唯一id
  • service_instance_id:被調用的實例的唯一id
  • version:本數據結構的版本號
  • start_time:開始時間戳
  • 我們現在來看下面的一個案例:

這里有一個很重要的字段信息,data_binary,這里面保存了當時TraceSegment下面的全部的span的信息,這里span的信息都是采用Base64編碼存儲到數據庫中的

我們模擬一個user應用調用order應用,我們發起了一個http://10.8.62.148:8094/testport這次調用在segment表中產生了下面三條記錄

在鏈路追蹤的頁面展示如下情況如下,鏈路展示是依據segment表中存儲的3條數據展示出來的

 

 

 

當在上面的圖上選擇某一條記錄點擊的時候,可以在右側彈出當前TraceSegment下面保存的span信息,span信息數據保存到data_binary這個字段中的

 

 

 

 

 

大概的效果就是上面的形式,接下來我們研究具體的原理

TraceSegment下面有span,整個trace的依賴依賴於span

以一個Trace為例:

 

 

 

首先是外部請求調用A,然后A依次同步調用了B和C,而B被調用時會去同步調用D,C被調用的時候會依次同步調用E和F,F被調用的時候會通過異步調用G,G則會異步調用H,最終完成一次調用。

上圖是通過Span之間的依賴關系來表現一個Trace,而在時間線上,則可以有如下的表達:

 

 

 上面我們了解了span之間的關系,接下來我們來看skywalking中是如何實現的

在應用訪問serverA的時候,對於入口,不管外圍調用是否前置,都會創建一個 entry span,在entryspan中會記錄下面的一些字段的信息,當前span屬於哪個TraceSegment,當前span是否有父span,當前span的訪問的方法的名稱等

 

 

要創建span, 我們要從當前的http的請求頭中提取前置上下文,這里seriviceA是入口的請求第一個點沒有前置,所以什么都沒拿到。然后會創建一個 exit span ,創建一個最出的埋點。之后會做一個 inject的操作,把當前的上下文例如當前span的id、當前span的訪問的方法等放在 HTTP 的頭里面,順帶這個 HTTP的調用發到 Service B 上。接下來就會創建一個TraceSegment記錄以及包當前創建的entrySpan保存到當前的這個TraceSegment記錄中,保存之后就會在segment表中增加一條記錄

   接下來,

 

 

 

 

 

 

 

首先是外部請求調用A,然后A依次同步調用了B和C,而B被調用時會去同步調用D,C被調用的時候會依次同步調用E和F,F被調用的時候會通過異步調用G,G則會異步調用H,最終完成一次調用。

上圖是通過Span之間的依賴關系來表現一個Trace,而在時間線上,則可以有如下的表達:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM