傳統 APM 聚焦在程式碼層面,不具備全棧多維度無盲點看問題的能力,同時由於插碼的阻礙往往難以覆蓋所有微服務,DeepFlow 依靠 eBPF 零程式碼修改採集全棧追蹤資料並聚合生成了呼叫關係,可以增強傳統 APM 的資料,大大縮短問題定界時間。對於已經使用傳統 APM 工具的使用者,可以考慮使用 DeepFlow 提供的 API 來增強應用依賴拓撲及呼叫追蹤,以獲得全棧資料追蹤能力。
本文以 SkyWalking 為例從落地實現角度來描述,如何將在傳統 APM 中整合 DeepFlow 的資料,增強傳統 APM 資料能力, 主要從以下兩個角度來:
- 依賴拓撲:增強檢視某歷史時間範圍內服務(POD)到服務(POD)全棧路徑拓撲以及全景上下游拓撲。
- 呼叫鏈追蹤:增強檢視某個應用 Span 對應系統 Span、網路 Span 時延消耗以及追蹤未插碼服務的能力。
開啟下文的閱讀之前,需要對 DeepFlow 目前已有的資料及術語有了解,下文預設讀者都有一定的認知。
01|全棧路徑拓撲-介面
增強檢視某歷史時間範圍內服務(POD)到服務(POD)應用和網路指標量能力,可以快速回答在某一段時間內端到端路徑是否存在瓶頸點,下面將結合 Skywalking 介紹產品 UI 介面如何融合
第一步:聚焦需要檢視的路徑(以下舉例透過拓撲圖路徑點選,大家可以根據環境的實際情況來定義使用流程)
聚焦需要檢視的路徑
點選全棧路徑拓撲
第二步:檢視全棧路徑拓撲(增強能力)
檢視全棧路徑拓撲
上圖拓撲中每一個節點都對應一個統計位置(tap_side),統計位置的說明參考 DeepFlow 官網的線上文件[1],以客戶端容器節點舉例說明具體的含義,表達是 cartservice 服務訪問 redis-cart 服務,在 cartservice 對應 POD 所在的容器節點上採集到的訪問資料,然後聚合的指標量。上圖檢視的指標量為響應時延,不難看出瓶頸在服務端容器網路,判斷過程如下:
客戶端時延:④=204.31ms,為請求服務端的總時延,由以下幾部分組成
- 客戶端容器網路:路徑①(也就是⑤-④),圖中所示為38.14us
- 雲網路:路徑②(也就是⑥-⑤),圖中所示為273.13us
- 服務端容器網路:路徑③(也就是⑦-⑥),圖中所示為204.25ms
- 服務端:即圖中⑦,為372.83us
02|全棧路徑拓撲-API
結合 API 看看如何實現,DeepFlow 的所有資料均可透過 SQL API 獲取。
呼叫方輸入客戶端名稱、服務端名稱、指標量以及時間範圍作為 API 的搜尋條件即可獲得全棧路徑拓撲資料。
第一步:獲取 Skywalking 路徑的客戶端服務及服務端名稱,根據需求明確需要檢視的指標量及檢視的時間範圍
Skywalking 輸入
第二步:查詢 DeepFlow 獲取應用/網路統計位置的資料,SQL 呼叫參考 DeepFlow 官網的線上文件[2]
SELECT Avg(`request`), /* 需要檢視的指標量 */ pod_service_0, /* 客戶端服務名稱,客戶端為 POD,則替換為 pod_0 */ tap_side, pod_service_1 /* 服務端服務名稱,服務端為 POD,則替換為 pod_1 */FROM vtap_app_edge_port /* 檢視應用指標使用 vtap_app_edge_port;檢視網路指標切換到 vtap_flow_edge_port */WHERE time>=1678760220 AND time<=1678762020 AND pod_service_0='deepflow-server' AND /* 過濾客戶端 */ pod_service_1='deepflow-server' /* 過濾服務端 */GROUP BY pod_service_0, tap_side, pod_service_1,
第三步:根據返回資料繪製拓撲圖
每個 tap_side 對應一個節點,節點根據 c-app/app/c-p/c/c-nd/c-hv/c-gw-hv/c-gw/local/rest/s-gw/s-gw-hv/s-hv/s-nd/s/s-p/s-app 從左到右排序,每個節點獨立顯示指標資料。
03|全景上下游拓撲-介面
增強某節點檢視全景上下游拓撲的能力,可快速發現未插碼範圍內被誰訪問了(比如追蹤上游的 Nginx 閘道器、安全策略未防住的訪問等等),以及自身訪問了誰,下面也將結合 Skywalking 介紹產品 UI 介面如何融合
第一步:聚焦需要檢視的節點(以下舉例透過拓撲圖節點點選,大家可以根據環境的實際情況來定義使用流程)
點選全景上下游拓撲
第二步:檢視全景上下游拓撲(增強能力)
檢視全景上下游拓撲
上圖為 tikcet-web 服務的全景上下游拓撲,其中 ① 是未插碼的 ingress-nginx-controller 服務,表明 ticket-web 服務對外都是透過 ingress 來訪問的,其中 ② 為未插碼的 kube-dns 服務,經常訪問服務慢,可能是因為 DNS 解析慢,而在應用拓撲是無法看出來此資訊的。
04|全景上下游拓撲-API
呼叫方輸入服務名稱、指標量以及時間範圍作為 API 的搜尋條件即可獲得全景上下游拓撲資料,需要兩次呼叫的 DeepFlow API,分別獲取到上游和下游的資料如下:
獲取上游資料
SELECT Avg(`request`), /* 需要檢視的指標量 */ pod_service_0, /* 客戶端服務名稱,客戶端為 POD,則替換為 pod_0 */ tap_side, pod_service_1 /* 服務端服務名稱,服務端為 POD,則替換為 pod_1 */FROM vtap_app_edge_port /* 檢視應用指標使用 vtap_app_edge_port;檢視網路指標切換到 vtap_flow_edge_port */WHERE time>=1678760220 AND time<=1678762020 AND pod_service_1='deepflow-server' /* 需要檢視上游資料的服務 */GROUP BY pod_service_0, tap_side, pod_service_1,
獲取下游資料
SELECT Avg(`request`), /* 需要檢視的指標量 */ pod_service_0, /* 客戶端服務名稱,客戶端為 POD,則替換為 pod_0 */ tap_side, pod_service_1 /* 服務端服務名稱,服務端為 POD,則替換為 pod_1 */FROM vtap_app_edge_port /* 檢視應用指標使用 vtap_app_edge_port;檢視網路指標切換到 vtap_flow_edge_port */WHERE time>=1678760220 AND time<=1678762020 AND pod_service_0='deepflow-server' /* 需要檢視下游資料的服務 */GROUP BY pod_service_0, tap_side, pod_service_1,
05|呼叫鏈追蹤-產品
在開始介紹如何增強呼叫追蹤的資料之前,先結合一張圖說明一些後續要使用到的術語
資料介紹圖
圖中 A 表示應用 Span(來源傳統 APM);S 表示網路 Span(來源 DeepFlow);N 表示網路 Span(來源 DeepFlow)圖中黑色部分為發起全棧呼叫追蹤的的應用 Span,後續統稱為 應用 Span Y圖中藍色部分為透過 應用 Span Y 追蹤的路徑中的系統和網路 Span圖中綠色部分為透過 應用 Span Y 追蹤的下游未插碼的 Span圖中紅色部分為透過 應用 Span Y 追蹤的上游未插碼的 Span
接下來將分別來討論上圖中藍色/綠色/紅色部分如何基於 SkyWalking 產品做 UI 融合(注:以下產品 UI 部分僅為示意圖):
第一步:聚焦需要檢視的應用 Span(以下舉例透過點選 Span,大家可以根據環境的實際情況來定義使用流程)
聚焦需要檢視的路徑
點選全棧呼叫追蹤
第二步:檢視全棧呼叫拓撲(增強能力)
檢視全棧呼叫拓撲
06|呼叫鏈追蹤-API
接下來看下結合 DeepFlow 的 SQL API 如何實現,基於前面的術語介紹圖,可知傳統 APM 結合 DeepFlow 的資料來完成全棧呼叫追蹤的能力,需要分藍色、綠色和紅色三部分來實現,接下來將分開介紹這三部分的資料實現。
藍色部分:根據 應用 Span 的 TraceID + SpanID 追蹤 DeepFlow 的系統 Span 和網路 Span,可以方便的檢視某次呼叫在系統和網路分佈消耗的時延,快速定界問題。可以透過 TraceID、SpanID 作為搜尋條件獲取 DeepFlow 的系統和網路 Span
藍色部分-追蹤圖
SELECT response_duration, start_time, end_time, resource_gl0_0, /* 客戶端 */ resource_gl0_1, /* 服務端 */ tap_port_type, /* eBPF、NIC ... */ tap_port, /* NIC Name */ trace_id, span_idFROM l7_flow_logWHERE trace_id = 'c5ad367da7ed41fc97921d91a0584bd8.63.16620935428909473' AND span_id = 'e05ee7a06d674085a16dfea36ed11b98.169.16620935428971714-2' AND /* 非必須,精確搜尋 */ time >= 1662093572 AND time <= 1662095372 /* 加速搜尋 */
此部分的細節部分可以參考DeepFlow 讓 SkyWalking 分散式追蹤無盲點[3]。
紅色部分:增強某個應用 Span 上游的 Span,對於插碼範圍以外(之前)的部分,例如追蹤出來從未插碼的客戶端 Span
紅色部分-追蹤原理解釋圖
對於這部分資料的追蹤,需要分幾個步驟來逐一進行關聯
- ① 根據應用 Span Y 的 TraceID + SpanID 追蹤 DeepFlow 的系統 Span,此時可能會得到多個系統 Span,只需要獲取與應用 Span Y緊鄰的系統 Span X繼續往下追蹤即可(可透過總時延最長來判斷)
- ② 獲取系統 Span X的 syscall_trace_id_request 作為其他系統 Span 的搜尋條件,得到系統 Span Z
SELECT response_duration, /* SELECT 欄位可以根據需求自定義即可*/ l7_protocol, Enum(request_type), request_resource, process_kname_0, process_kname_1, tap_side, req_tcp_seq, resp_tcp_seq, Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`, auto_instance_0, Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`, auto_instance_1, FROM l7_flow_log WHERE time>=1678764261 AND /*追蹤開始時間,建議設定比系統 Span X 的開始時間早 3min*/ time<=1678767861 AND /*追蹤結束時間,建議設定比系統 Span X 的結束時間晚 3min*// (syscall_trace_id_request=16787489195430278) /* 16787489195430278 為 系統 Span Y 的 syscall_trace_id_request */ORDER BY `end_time`
③ 獲取系統 Span Z 的 req_tcp_seq/resp_tcp_seq 作為其他系統 Span 和網路 Span 的搜尋條件,得到網路 Span Z.1/Z.2 以及系統 Span Q,此處邏輯特別注意:
req_tcp_seq !=0 & resp_tcp_seq !=0 則需要同時滿足 req_tcp_seq 和 resp_tcp_seq;如果其中一個為 0,則任意滿足一個即可
SELECT response_duration, /* SELECT 欄位可以根據需求自定義即可*/ l7_protocol, Enum(request_type), request_resource, process_kname_0, process_kname_1, tap_side, req_tcp_seq, resp_tcp_seq, Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`, auto_instance_0, Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`, auto_instance_1, FROM l7_flow_log WHERE time>=1678764261 AND time<=1678767861 AND (type=2 AND req_tcp_seq=3575241005 AND /* 3575241005 為系統 Span Z 的 req_tcp_seq*/ resp_tcp_seq=995863176) /* 995863176 為系統 Span Z 的 resp_tcp_seq*/ORDER BY `end_time`
④ 接下來可繼續追蹤系統 Span Q 的上游系統 Span,這裡將分兩種情況,如果上游的系統 Span 與系統 Span Q 在同一個執行緒,則重複步驟 [2]/[3] 即可,如果在不同執行緒/程式中,目前僅支援閘道器設定了 X-Request-ID 的情況下繼續追蹤,獲取系統 Span Q的 x-request-id 作為查詢其他系統 Span 和網路 Span 的搜尋條件,得到其上游的系統 Span M
SELECT response_duration, /* SELECT 欄位可以根據需求自定義即可*/ l7_protocol, Enum(request_type), request_resource, process_kname_0, process_kname_1, tap_side, req_tcp_seq, resp_tcp_seq, Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`, auto_instance_0, Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`, auto_instance_1, FROM l7_flow_log WHERE time>=1678764261 AND time<=1678767861 AND x_request_id=6e903947-5ef0-4c63-91a8-a2a599171633 /* 6e903947-5ef0-4c63-91a8-a2a599171633 為系統 Span Q 的 x_request_id*/ORDER BY `end_time`
⑤ 到此,已經根據上述步驟追蹤得到所有的上游 Span,接下來將確定父子關係,可直接根據總的響應時延,按從大到小降序排列即可
綠色部分:增強某個應用 Span 下游的 Span,對於插碼範圍以外(之後)的部分追蹤,例如追蹤出來未插碼的服務端 Span(DNS),此追蹤過程與紅色部分非常相似,僅步驟 ② 中的syscall_trace_id_request換成syscall_trace_id_response即可,此處不在贅述。
綠色部分-追蹤圖
07|什麼是 DeepFlow
DeepFlow[4] 是一款開源的高度自動化的可觀測性平臺,是為雲原生應用開發者建設可觀測效能力而量身打造的全棧、全鏈路、高效能資料引擎。DeepFlow 使用 eBPF、WASM、OpenTelemetry 等新技術,創新的實現了 AutoTracing、AutoMetrics、AutoTagging、SmartEncoding 等核心機制,幫助開發者提升埋點插碼的自動化水平,降低可觀測性平臺的運維複雜度。利用 DeepFlow 的可程式設計能力和開放介面,開發者可以快速將其融入到自己的可觀測性技術棧中。
GitHub 地址:https://github.com/deepflowys/deepflow
訪問 DeepFlow Demo[5],體驗高度自動化的可觀測性新時代。
參考資料
[1] 統計位置的說明參考 DeepFlow 官網的線上文件: https://deepflow.io/docs/zh/auto-metrics/metrics-without-inst...
[2] SQL 呼叫參考 DeepFlow 官網的線上文件: https://deepflow.io/docs/zh/server-integration/query/sql/
[3] DeepFlow 讓 SkyWalking 分散式追蹤無盲點: https://deepflow.io/blog/007-skywalking-distributed-tracing-w...
[4] DeepFlow: https://github.com/deepflowys/deepflow
[5] DeepFlow Demo: https://deepflow.yunshan.net/docs/zh/install/overview/