Databend 全鏈路追蹤
全鏈路追蹤意味著能夠追蹤到每一個呼叫請求的完整呼叫鏈路、收集效能資料並反饋異常。Databend 使用 tracing 賦能可觀測性,實現全鏈路追蹤。
Databend 與 Tracing
初步瞭解 Databend 怎麼實現全鏈路追蹤。
初識 Tracing
Tracing 是由 Tokio 團隊維護的 Rust 應用跟蹤框架,用來收集結構化的、基於事件的診斷資訊。
專案地址:https://github.com/tokio-rs/tracing
示例:
use tracing::{info, Level}; use tracing_subscriber; fn main() { let collector = tracing_subscriber::fmt() // filter spans/events with level TRACE or higher. .with_max_level(Level::TRACE) // build but do not install the subscriber. .finish(); tracing::collect::with_default(collector, || { info!("This will be logged to stdout"); }); info!("This will _not_ be logged to stdout"); }
Databend 中的 Tracing
Databend 的 tracing-subscriber 被統一整合在 common/tracing,由 query 和 meta 共用。
// Use env RUST_LOG to initialize log if present. // Otherwise use the specified level. let directives = env::var(EnvFilter::DEFAULT_ENV).unwrap_or_else(|_x| level.to_string()); let env_filter = EnvFilter::new(directives); let subscriber = Registry::default() .with(env_filter) # 根據環境變數過濾 .with(JsonStorageLayer) # 利用 tracing-bunyan-formatter 格式化為 json .with(stdout_logging_layer) # 標準輸出 .with(file_logging_layer) # 輸出到檔案,預設位於 `_logs` 目錄下 .with(jaeger_layer); # opentelemetry-jaeger #[cfg(feature = "console")] let subscriber = subscriber.with(console_subscriber::spawn()); # tokio console tracing::subscriber::set_global_default(subscriber) .expect("error setting global tracing subscriber");
具體到內部的 tracing 記錄,大致有兩類:
- 普通:與其他 log 方式一樣,利用 info!、debug! 來收集資訊。
use common_tracing::tracing;
tracing::info!("{:?}", conf);
tracing::info!("DatabendQuery {}", *databend_query::DATABEND_COMMIT_VERSION);
- Instruments:在呼叫函式時建立並進入 tracing span(跨度),span 表示程式在特定上下文中執行的時間段。
use common_tracing::tracing::debug_span; #[tracing::instrument(level = "debug", skip_all)] async fn read(&mut self) -> Result<Option<DataBlock>> { ... fetched_metadata = read_metadata_async(&mut self.reader) .instrument(debug_span!("parquet_source_read_meta")) .await .map_err(|e| ErrorCode::ParquetError(e.to_string()))?; ... }
示例:
{
"v": 0,
"name": "[email protected]:3307",
"msg": "Shutdown server.",
"level": 30,
"hostname": "dataslime",
"pid": 53341,
"time": "2022-05-11T00:51:56.374807359Z",
"target": "databend_query",
"line": 153,
"file": "query/src/bin/databend-query.rs"
}
觀測 Databend 追蹤的方式
Databend 原生提供了多種觀測方式,以方便診斷和除錯:
-
http tracing :訪問 localhost:8080/v1/logs(根據配置)
-
stdout/filelog :檢查終端輸出或 _logs 目錄(根據配置)
-
system.tracing 表 :執行 select * from system.tracing limit 20;
-
jaeger :執行 jaeger ,訪問 http://127.0.0.1:16686/
-
console :按特定方式構建後,執行 tokio-console
Jaeger 分散式追蹤
使用 Jaeger 對 Databend 進行全鏈路追蹤。
Opentelemetry & Jaeger
OpenTelemetry 是工具、API 和 SDK 的集合。使用它來檢測、生成、收集和匯出遙測資料(度量、日誌和追蹤),以幫助您分析軟體的效能和行為。Jaeger 是一個開源的端到端分散式追蹤系統。由 Uber 捐贈給 CNCF 。它可以用於監視基於微服務的分散式系統,提供以下能力:
- 分散式上下文傳播
- 分散式事務監視
- 根本原因分析
- 服務依賴性分析
- 效能/延遲優化
Step by Step
遵循下述步驟,即可使用 Jaeger 探索 Databend :
- 構建二進位制程式:cargo build(可以使用 --bin 指定)
- 將日誌級別設定為 DEBUG ,執行需要除錯的應用程式。例如,LOG_LEVEL=DEBUG ./databend-query
- 執行 jaeger :docker run -d -p6831:6831/udp -p6832:6832/udp -p16686:16686 jaegertracing/all-in- one:latest
- 開啟 http://127.0.0.1:16686/ 以檢視 jaeger 收集的資訊
結果探索
x 軸是執行時刻,y 軸是持續的時間,圓點反映 span 的聚集程度。
執行下述語句即可得到上圖所示追蹤結果:
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 SELECT * FROM t1;
Timeline
下圖是點選最大的圓點得到的追蹤情況:
使用 timeline 模式來展現 tracing 的各個跨度之間的關係。以時間為主線進行分析,方便使用者觀看在某個時間點觀看程式資訊。
點開第一個跨度,可以看到這是執行 INSERT INTO t1 SELECT *FROM t1 查詢時的情況。
Graph
切換到 graph 模式,可以看到各個 span 之間的呼叫鏈,每個 span 具體用時 ,以及百分比。
通過這個檢視使用者很容易知道系統瓶頸,快速定位問題。
Compare
連起來的各個部分形成整個 trace 的呼叫鏈。因為比較時一般會比較兩個相同型別的呼叫,所以看到的會是重合後的檢視。
對於顏色的一個說明:
- 深綠色,表示這個 span 只存在於 trace-B 中,A 沒有這個 span
- 深紅色,表示這個 span 只存在於 trace-A 中,B 沒有這個 span
- 淺綠色,表示這個 span 在 trace-B(右邊這個)的數量多
- 淺紅色,表示這個 span 在 trace-A(左邊這個)的數量多
tokio-console 診斷
tokio-console 診斷
tokio-rs 團隊出品的診斷和除錯工具,可以幫助我們診斷與 tokio 執行時相關的問題。
console 是什麼
tokio-console 是專為非同步程式設計的除錯與診斷工具,能夠列出 tokio 的任務,提供對程式的任務和資源的實時、易於導航的檢視,總結了它們的當前狀態和歷史行為。主要包含以下元件:
- 傳輸診斷資料的協議
- 用於收集診斷資料的儀器
- 當然,用於展示和探索診斷資料的實用工具\
專案地址:https://github.com/tokio-rs/console
Step by Step
- 使用特定的 rustflags 和 features 來構建:RUSTFLAGS="--cfg tokio_unstable" cargo build --features tokio-console ,也可以只構建單個二進位制程式,使用 --bin 進行指定。
- 將日誌級別設定為 TRACE ,執行需要除錯的應用程式 LOG_LEVEL=TRACE databend-query 或者 databend-meta --single --log-level=TRACE。可以使用 TOKIO_CONSOLE_BIND 指定埠,以避免潛在的埠搶佔問題。
- 執行 tokio-console,預設連線到 http://127.0.0.1:6669
結果探索
任務
先看什麼是 tokio 任務:
- 任務是一個輕量級的、非阻塞的執行單元。類似作業系統的執行緒,但是是由 tokio 執行時管理,一般叫做“綠色執行緒”,與 Go 的 goroutine,Kotlin 的 coroutine 類似。
- 任務是協同排程的。大多數作業系統實現搶佔式多工。作業系統允許每個執行緒執行一段時間,然後搶佔它,暫停該執行緒並切換到另一個執行緒。另一方面,任務實現協同多工。一個任務被允許執行直到它讓出執行權,執行時會切換到執行下一個任務。
基礎檢視
通過左右切換,可以得到總忙時間或輪詢次數等指標對任務進行排序。控制檯通過高亮來提示較大差異,比如從毫秒到秒的切換。
控制檯還實現了一個“警告”系統。通過監視應用程式中任務的執行時操作,控制檯可以檢測可能提示 bug 或效能問題的行為模式,並突出顯示這些行為模式供使用者分析。比如已經運行了很長時間而沒有讓步的任務,喚醒的次數比被其他任務喚醒的次數還要多的任務。
任務檢視
上下切換選中任務,enter 檢視關於每個任務的翔實資料,比如輪詢持續時間的直方圖。
不僅列出任務。console 還會插入非同步互斥和訊號量等資源。Tokio Console 的資源詳細資訊檢視顯示了哪些任務已經進入臨界區,哪些任務正在等待獲得訪問許可權。
還能做什麼
還能做什麼
與分散式追蹤和日誌系統相關的一些其他內容。
可觀測性 + +
目前還有一系列關於可觀測性和 Tracing 的 Issue 有待解決:
- Integrate tokio metrics for query task based tokio runtime monitoring #4205
- Configure on jaeger tracing address similar to metrics api server #3633
- Summary of todos about distributed tracing #1227
- Query traces and analysis, based on user behavior. #1177
- Http stack traces #1085
- Shuffle read/write metrics #1004
另外,更進一步的考量是,如何基於可觀測性來自動/半自動地發現問題並對系統進行調優。瞭解更多
瞭解更多
Tracing
Jaeger
tokio-console
關於 Databend
Databend 是一款開源、彈性、低成本,基於物件儲存也可以做實時分析的新式數倉。期待您的關注,一起探索雲原生數倉解決方案,打造新一代開源 Data Cloud。
-
Databend 文件:https://databend.rs/
-
Wechat:Databend
文章首發於公眾號:Databend